FreeBASIC  0.91.0
gfx_core.c
Go to the documentation of this file.
1 /* core internal routines */
2 
3 #include "fb_gfx.h"
4 
5 static void (*fb_hPutPixelSolid)(FB_GFXCTX *ctx, int x, int y, unsigned int color);
6 static void *(*fb_hPixelSetSolid)(void *dest, int color, size_t size);
7 static void (*fb_hPutPixelAlpha)(FB_GFXCTX *ctx, int x, int y, unsigned int color);
8 static void *(*fb_hPixelSetAlpha)(void *dest, int color, size_t size);
9 static unsigned int (*fb_hGetPixel)(struct FB_GFXCTX *ctx, int x, int y);
10 
11 #ifdef HOST_X86
12 extern void *fb_hPixelSet2MMX(void *dest, int color, size_t size);
13 extern void *fb_hPixelSet4MMX(void *dest, int color, size_t size);
14 extern void *fb_hPixelSetAlpha4MMX(void *dest, int color, size_t size);
15 extern void fb_hPutPixelAlpha4MMX(FB_GFXCTX *ctx, int x, int y, unsigned int color);
16 #endif
17 
18 
20 
21 
22 /*:::::*/
24 {
25  EVENT *slot;
26 
27  EVENT_LOCK();
29  fb_hMemCpy(slot, e, sizeof(EVENT));
30  if (((__fb_gfx->event_tail + 1) & (MAX_EVENTS - 1)) == __fb_gfx->event_head)
33  EVENT_UNLOCK();
34 }
35 
36 void fb_hPostEvent_code_end(void) { }
37 
38 
39 /*:::::*/
41 {
43 
44  context = (FB_GFXCTX *)fb_TlsGetCtx(FB_TLSKEY_GFX, sizeof(FB_GFXCTX));
45  if ((__fb_gfx) && (context->id != __fb_gfx->id)) {
46  /* context has to be initialized; default to screen */
47  if (context->line)
48  free(context->line);
49  fb_hMemSet(context, 0, sizeof(FB_GFXCTX));
50  context->id = __fb_gfx->id;
51  context->old_view_w = __fb_gfx->w;
52  context->old_view_h = context->max_h = __fb_gfx->h;
53  context->line = (unsigned char **)malloc(__fb_gfx->h * sizeof(unsigned char *));
54  if ((__fb_gfx->depth > 4) && (__fb_gfx->depth <= 8))
55  context->fg_color = 15;
56  else
57  context->fg_color = __fb_gfx->color_mask;
58  context->bg_color = MASK_A_32 & __fb_gfx->color_mask;
59  context->flags = CTX_BUFFER_INIT;
60  fb_hPrepareTarget(context, NULL);
62  }
63 
64  return context;
65 }
66 
67 
68 /*:::::*/
69 void fb_hPrepareTarget(FB_GFXCTX *context, void *target)
70 {
71  PUT_HEADER *header;
72  unsigned char *data;
73  int i, h;
74 
75  if (target) {
76  if (target != context->last_target) {
77  if (context->last_target == NULL)
78  fb_hMemCpy(context->old_view, context->view, sizeof(int) * 4);
79  header = (PUT_HEADER *)target;
80  context->view_x = 0;
81  context->view_y = 0;
82  if (header->type == PUT_HEADER_NEW) {
83  context->view_w = header->width;
84  context->view_h = h = header->height;
85  context->target_bpp = header->bpp;
86  context->target_pitch = header->pitch;
87  fb_hSetupFuncs(header->bpp);
88  data = (unsigned char *)target + sizeof(PUT_HEADER);
89  }
90  else {
91  context->view_w = header->old.width;
92  context->view_h = h = header->old.height;
93  context->target_bpp = __fb_gfx->bpp;
94  context->target_pitch = context->view_w * __fb_gfx->bpp;
95  data = (unsigned char *)target + 4;
96  }
97  if (h > context->max_h) {
98  context->line = (unsigned char **)realloc(context->line, h * sizeof(unsigned char *));
99  context->max_h = h;
100  }
101  for (i = 0; i < h; i++)
102  context->line[i] = data + (i * context->target_pitch);
103  context->flags |= CTX_BUFFER_SET;
104  }
105  }
106  else if (context->flags & (CTX_BUFFER_SET | CTX_BUFFER_INIT)) {
107  fb_hMemCpy(context->view, context->old_view, sizeof(int) * 4);
108  context->target_bpp = __fb_gfx->bpp;
109  context->target_pitch = __fb_gfx->pitch;
110  for (i = 0; i < __fb_gfx->h; i++)
111  context->line[i] = __fb_gfx->page[context->work_page] + (i * __fb_gfx->pitch);
113  context->flags &= ~(CTX_BUFFER_SET | CTX_BUFFER_INIT);
114  }
115  context->last_target = target;
116 }
117 
119 {
120  if ((__fb_gfx->flags & ALPHA_PRIMITIVES) && (context->target_bpp == 4) && ((color & MASK_A_32) != MASK_A_32)) {
121  context->put_pixel = fb_hPutPixelAlpha;
122  context->pixel_set = fb_hPixelSetAlpha;
123  }
124  else {
125  context->put_pixel = fb_hPutPixelSolid;
126  context->pixel_set = fb_hPixelSetSolid;
127  }
128  context->get_pixel = fb_hGetPixel;
129 }
130 
131 /*:::::*/
132 void fb_hTranslateCoord(FB_GFXCTX *context, float fx, float fy, int *x, int *y)
133 {
134  if (context->flags & CTX_WINDOW_ACTIVE) {
135  fx = ((fx - context->win_x) * context->view_w) / context->win_w;
136  fy = ((fy - context->win_y) * context->view_h) / context->win_h;
137  }
138 
139  *x = (int)(fx > 0 ? fx + 0.5 : fx - 0.5);
140  *y = (int)(fy > 0 ? fy + 0.5 : fy - 0.5);
141 
143  *y = context->view_h - 1 - *y;
144 
145  if ((context->flags & CTX_VIEW_SCREEN) == 0) {
146  *x += context->view_x;
147  *y += context->view_y;
148  }
149 }
150 
151 
152 /*:::::*/
153 void fb_hFixRelative(FB_GFXCTX *context, int coord_type, float *x1, float *y1, float *x2, float *y2)
154 {
155  coord_type &= COORD_TYPE_MASK;
156 
157  switch (coord_type) {
158 
159  case COORD_TYPE_R:
160  case COORD_TYPE_RA:
161  *x1 += context->last_x;
162  *y1 += context->last_y;
163  break;
164 
165  case COORD_TYPE_RR:
166  *x1 += context->last_x;
167  *y1 += context->last_y;
168  /* fallthrough */
169 
170  case COORD_TYPE_AR:
171  *x2 += *x1;
172  *y2 += *y1;
173  break;
174  }
175 
176  if (x2) {
177  context->last_x = *x2;
178  context->last_y = *y2;
179  }
180  else {
181  context->last_x = *x1;
182  context->last_y = *y1;
183  }
184 }
185 
186 
187 /*:::::*/
188 void fb_hFixCoordsOrder(int *x1, int *y1, int *x2, int *y2)
189 {
190  if (*x2 < *x1)
191  SWAP(*x1, *x2);
192 
193  if (*y2 < *y1)
194  SWAP(*y1, *y2);
195 }
196 
197 
198 /*:::::*/
199 static void fb_hPutPixel1(FB_GFXCTX *ctx, int x, int y, unsigned int color)
200 {
201  ctx->line[y][x] = color;
202 }
203 
204 
205 /*:::::*/
206 static void fb_hPutPixel2(FB_GFXCTX *ctx, int x, int y, unsigned int color)
207 {
208  ((unsigned short *)ctx->line[y])[x] = color;
209 }
210 
211 
212 /*:::::*/
213 static void fb_hPutPixel4(FB_GFXCTX *ctx, int x, int y, unsigned int color)
214 {
215  ((unsigned int *)ctx->line[y])[x] = color;
216 }
217 
218 
219 /*:::::*/
220 static void fb_hPutPixelAlpha4(FB_GFXCTX *ctx, int x, int y, unsigned int color)
221 {
222  unsigned int dc, srb, sg, drb, dg, a;
223  unsigned int *d = ((unsigned int *)ctx->line[y]) + x;
224 
225  dc = *d;
226  a = color >> 24;
227  srb = color & MASK_RB_32;
228  sg = color & MASK_G_32;
229  drb = dc & MASK_RB_32;
230  dg = dc & MASK_G_32;
231  srb = ((srb - drb) * a) >> 8;
232  sg = ((sg - dg) * a) >> 8;
233  *d = ((drb + srb) & MASK_RB_32) | ((dg + sg) & MASK_G_32) | (color & MASK_A_32);
234 }
235 
236 
237 /*:::::*/
238 static unsigned int fb_hGetPixel1(FB_GFXCTX *ctx, int x, int y)
239 {
240  return ctx->line[y][x];
241 }
242 
243 
244 /*:::::*/
245 static unsigned int fb_hGetPixel2(FB_GFXCTX *ctx, int x, int y)
246 {
247  return ((unsigned short *)ctx->line[y])[x];
248 }
249 
250 
251 /*:::::*/
252 static unsigned int fb_hGetPixel4(FB_GFXCTX *ctx, int x, int y)
253 {
254  return ((unsigned int *)ctx->line[y])[x];
255 }
256 
257 
258 /*:::::*/
259 static void *fb_hPixelSet2(void *dest, int color, size_t size)
260 {
261  unsigned short *d = (unsigned short *)dest;
262 
263  for (; size; size--)
264  *d++ = color;
265 
266  return dest;
267 }
268 
269 
270 /*:::::*/
271 static void *fb_hPixelSet4(void *dest, int color, size_t size)
272 {
273  unsigned int *d = (unsigned int *)dest;
274 
275  for (; size; size--)
276  *d++ = color;
277 
278  return dest;
279 }
280 
281 
282 /*:::::*/
283 void *fb_hPixelSetAlpha4(void *dest, int color, size_t size)
284 {
285  unsigned int sc, srb, sg, sa, dc, drb, dg, a, irb, ig;
286  unsigned int *d = (unsigned int *)dest;
287 
288  sc = (unsigned int)color;
289  srb = sc & MASK_RB_32;
290  sg = sc & MASK_G_32;
291  sa = sc & MASK_A_32;
292  a = sc >> 24;
293  for (; size; size--) {
294  dc = *d;
295  drb = dc & MASK_RB_32;
296  dg = dc & MASK_G_32;
297  irb = ((srb - drb) * a) >> 8;
298  ig = ((sg - dg) * a) >> 8;
299  dc = ((drb + irb) & MASK_RB_32) | ((dg + ig) & MASK_G_32) | sa;
300  *d++ = dc;
301  }
302  return dest;
303 }
304 
305 
306 /*:::::*/
307 static void *fb_hPixelCpy2(void *dest, const void *src, size_t size)
308 {
309  return fb_hMemCpy(dest, src, size << 1);
310 }
311 
312 
313 /*:::::*/
314 static void *fb_hPixelCpy4(void *dest, const void *src, size_t size)
315 {
316  return fb_hMemCpy(dest, src, size << 2);
317 }
318 
319 
320 /*:::::*/
321 void fb_hSetupFuncs(int bpp)
322 {
323 #ifdef HOST_X86
324  if (fb_CpuDetect() & 0x800000) {
325  __fb_gfx->flags |= HAS_MMX;
328  }
329  else {
330 #endif
331  fb_hMemCpy = memcpy;
332  fb_hMemSet = memset;
333 #ifdef HOST_X86
334  }
335 #endif
336  switch (bpp) {
337  case 1:
342  break;
343 
344  case 2:
347 #ifdef HOST_X86
348  if (__fb_gfx->flags & HAS_MMX)
349  fb_hPixelSetSolid = fb_hPixelSetAlpha = fb_hPixelSet2MMX;
350  else
351 #endif
354  break;
355 
356  default:
359 #ifdef HOST_X86
360  if (__fb_gfx->flags & HAS_MMX)
361  fb_hPixelSetSolid = fb_hPixelSet4MMX;
362  else
363 #endif
367 #ifdef HOST_X86
368  if (__fb_gfx->flags & HAS_MMX) {
369  fb_hPutPixelAlpha = fb_hPutPixelAlpha4MMX;
370  fb_hPixelSetAlpha = fb_hPixelSetAlpha4MMX;
371  }
372  else {
373 #endif
376 #ifdef HOST_X86
377  }
378 #endif
379  }
380  else {
383  }
384  break;
385  }
386 
388 }