1 /*
2    (c) Copyright 2001-2011  The world wide DirectFB Open Source Community (directfb.org)
3    (c) Copyright 2000-2004  Convergence (integrated media) GmbH
4 
5    All rights reserved.
6 
7    Written by Denis Oliver Kropp <dok@directfb.org>,
8               Andreas Hundt <andi@fischlustig.de>,
9               Sven Neumann <neo@directfb.org>,
10               Ville Syrjälä <syrjala@sci.fi> and
11               Claudio Ciccani <klan@users.sf.net>.
12 
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Lesser General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17 
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Lesser General Public License for more details.
22 
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; if not, write to the
25    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26    Boston, MA 02111-1307, USA.
27 */
28 
29 #include <config.h>
30 
31 #include <limits.h>
32 #include <string.h>
33 
34 #include <directfb.h>
35 #include <directfb_util.h>
36 
37 #include <direct/debug.h>
38 #include <direct/memcpy.h>
39 
40 #include <fusion/conf.h>
41 #include <fusion/fusion.h>
42 #include <fusion/shmalloc.h>
43 #include <fusion/arena.h>
44 
45 #include <core/core.h>
46 #include <core/coredefs.h>
47 #include <core/coretypes.h>
48 
49 #include <core/core_parts.h>
50 #include <core/gfxcard.h>
51 #include <core/fonts.h>
52 #include <core/state.h>
53 #include <core/palette.h>
54 #include <core/surface.h>
55 #include <core/surface_buffer.h>
56 #include <core/surface_pool.h>
57 #include <core/system.h>
58 
59 #include <core/CoreGraphicsStateClient.h>
60 
61 #include <gfx/generic/generic.h>
62 #include <gfx/clip.h>
63 #include <gfx/util.h>
64 
65 #include <direct/hash.h>
66 #include <direct/mem.h>
67 #include <direct/messages.h>
68 #include <direct/modules.h>
69 #include <direct/utf8.h>
70 #include <direct/util.h>
71 
72 #include <misc/conf.h>
73 #include <misc/util.h>
74 
75 
76 D_DEBUG_DOMAIN( Core_Graphics,    "Core/Graphics",    "DirectFB Graphics Core" );
77 D_DEBUG_DOMAIN( Core_GraphicsOps, "Core/GraphicsOps", "DirectFB Graphics Core Operations" );
78 D_DEBUG_DOMAIN( Core_GfxState,    "Core/GfxState",    "DirectFB Graphics Core State" );
79 
80 
81 DEFINE_MODULE_DIRECTORY( dfb_graphics_drivers, "gfxdrivers", DFB_GRAPHICS_DRIVER_ABI_VERSION );
82 
83 /**********************************************************************************************************************/
84 
85 static void dfb_gfxcard_find_driver( CoreDFB *core );
86 static void dfb_gfxcard_load_driver( void );
87 
88 static void fill_tri( DFBTriangle *tri, CardState *state, bool accelerated );
89 
90 /**********************************************************************************************************************/
91 
92 DFB_CORE_PART( graphics_core, GraphicsCore );
93 
94 /**********************************************************************************************************************/
95 
96 static CoreGraphicsDevice *card;   /* FIXME */
97 
98 /* Hook for registering additional screen(s) and layer(s) in app or lib initializing DirectFB. */
99 void (*__DFB_CoreRegisterHook)( CoreDFB *core, CoreGraphicsDevice *device, void *ctx ) = NULL;
100 void  *__DFB_CoreRegisterHookCtx = NULL;
101 
102 
103 /** public **/
104 
105 static DFBResult
dfb_graphics_core_initialize(CoreDFB * core,DFBGraphicsCore * data,DFBGraphicsCoreShared * shared)106 dfb_graphics_core_initialize( CoreDFB               *core,
107                               DFBGraphicsCore       *data,
108                               DFBGraphicsCoreShared *shared )
109 {
110      DFBResult            ret;
111      int                  videoram_length;
112      int                  auxram_length;
113      FusionSHMPoolShared *pool = dfb_core_shmpool( core );
114 
115      D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_initialize( %p, %p, %p )\n", core, data, shared );
116 
117      D_ASSERT( data != NULL );
118      D_ASSERT( shared != NULL );
119 
120 
121      card = data;   /* FIXME */
122 
123      data->core   = core;
124      data->shared = shared;
125 
126 
127      /* fill generic driver info */
128      gGetDriverInfo( &shared->driver_info );
129 
130      /* fill generic device info */
131      gGetDeviceInfo( &shared->device_info );
132 
133      if (!shared->device_info.limits.dst_max.w)
134           shared->device_info.limits.dst_max.w = INT_MAX;
135 
136      if (!shared->device_info.limits.dst_max.h)
137           shared->device_info.limits.dst_max.h = INT_MAX;
138 
139      /* Limit video ram length */
140      videoram_length = dfb_system_videoram_length();
141      if (videoram_length) {
142           if (dfb_config->videoram_limit > 0 &&
143               dfb_config->videoram_limit < videoram_length)
144                shared->videoram_length = dfb_config->videoram_limit;
145           else
146                shared->videoram_length = videoram_length;
147      }
148 
149      /* Limit auxiliary memory length (currently only AGP) */
150      auxram_length = dfb_system_auxram_length();
151      if (auxram_length) {
152           if (dfb_config->agpmem_limit > 0 &&
153               dfb_config->agpmem_limit < auxram_length)
154                shared->auxram_length = dfb_config->agpmem_limit;
155           else
156                shared->auxram_length = auxram_length;
157      }
158 
159      /* Build a list of available drivers. */
160      direct_modules_explore_directory( &dfb_graphics_drivers );
161 
162      /* Load driver */
163      if (dfb_system_caps() & CSCAPS_ACCELERATION)
164           dfb_gfxcard_find_driver( core );
165 
166      if (data->driver_funcs) {
167           const GraphicsDriverFuncs *funcs = data->driver_funcs;
168 
169           data->driver_data = D_CALLOC( 1, shared->driver_info.driver_data_size );
170 
171           card->device_data   =
172           shared->device_data = SHCALLOC( pool, 1, shared->driver_info.device_data_size );
173 
174           ret = funcs->InitDriver( card, &card->funcs,
175                                    card->driver_data, card->device_data, core );
176           if (ret) {
177                SHFREE( pool, shared->device_data );
178                SHFREE( pool, shared->module_name );
179                D_FREE( card->driver_data );
180                card = NULL;
181                return ret;
182           }
183 
184           ret = funcs->InitDevice( data, &shared->device_info,
185                                    data->driver_data, data->device_data );
186           if (ret) {
187                funcs->CloseDriver( card, card->driver_data );
188                SHFREE( pool, shared->device_data );
189                SHFREE( pool, shared->module_name );
190                D_FREE( card->driver_data );
191                card = NULL;
192                return ret;
193           }
194 
195           if (data->funcs.EngineReset)
196                data->funcs.EngineReset( data->driver_data, data->device_data );
197      }
198 
199      D_INFO( "DirectFB/Graphics: %s %s %d.%d (%s)\n",
200              shared->device_info.vendor, shared->device_info.name,
201              shared->driver_info.version.major,
202              shared->driver_info.version.minor, shared->driver_info.vendor );
203 
204      if (dfb_config->software_only) {
205           if (data->funcs.CheckState) {
206                data->funcs.CheckState = NULL;
207 
208                D_INFO( "DirectFB/Graphics: Acceleration disabled (by 'no-hardware')\n" );
209           }
210      }
211      else {
212           data->caps   = shared->device_info.caps;
213           data->limits = shared->device_info.limits;
214      }
215 
216      fusion_skirmish_init2( &shared->lock, "GfxCard", dfb_core_world(core), fusion_config->secure_fusion );
217 
218      if (__DFB_CoreRegisterHook)
219          __DFB_CoreRegisterHook( core, card, __DFB_CoreRegisterHookCtx );
220 
221      D_MAGIC_SET( data, DFBGraphicsCore );
222      D_MAGIC_SET( shared, DFBGraphicsCoreShared );
223 
224      return DFB_OK;
225 }
226 
227 static DFBResult
dfb_graphics_core_join(CoreDFB * core,DFBGraphicsCore * data,DFBGraphicsCoreShared * shared)228 dfb_graphics_core_join( CoreDFB               *core,
229                         DFBGraphicsCore       *data,
230                         DFBGraphicsCoreShared *shared )
231 {
232      DFBResult          ret;
233      GraphicsDriverInfo driver_info;
234 
235      D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_join( %p, %p, %p )\n", core, data, shared );
236 
237      D_ASSERT( data != NULL );
238      D_MAGIC_ASSERT( shared, DFBGraphicsCoreShared );
239 
240      card = data;   /* FIXME */
241 
242      data->core   = core;
243      data->shared = shared;
244 
245      /* Initialize software rasterizer. */
246      gGetDriverInfo( &driver_info );
247 
248      /* Build a list of available drivers. */
249      direct_modules_explore_directory( &dfb_graphics_drivers );
250 
251      /* Load driver. */
252      if (dfb_system_caps() & CSCAPS_ACCELERATION)
253           dfb_gfxcard_load_driver();
254 
255      if (data->driver_funcs) {
256           const GraphicsDriverFuncs *funcs = data->driver_funcs;
257 
258           data->driver_data = D_CALLOC( 1, shared->driver_info.driver_data_size );
259 
260           data->device_data = shared->device_data;
261 
262           ret = funcs->InitDriver( card, &card->funcs,
263                                    card->driver_data, card->device_data, core );
264           if (ret) {
265                D_FREE( data->driver_data );
266                data = NULL;
267                return ret;
268           }
269      }
270      else if (shared->module_name) {
271           D_ERROR( "DirectFB/Graphics: Could not load driver used by the running session!\n" );
272           data = NULL;
273           return DFB_UNSUPPORTED;
274      }
275 
276      D_INFO( "DirectFB/Graphics: %s %s %d.%d (%s)\n",
277              shared->device_info.vendor, shared->device_info.name,
278              shared->driver_info.version.major,
279              shared->driver_info.version.minor, shared->driver_info.vendor );
280 
281      if (dfb_config->software_only) {
282           if (data->funcs.CheckState) {
283                data->funcs.CheckState = NULL;
284 
285                D_INFO( "DirectFB/Graphics: Acceleration disabled (by 'no-hardware')\n" );
286           }
287      }
288      else {
289           data->caps   = shared->device_info.caps;
290           data->limits = shared->device_info.limits;
291      }
292 
293      D_MAGIC_SET( data, DFBGraphicsCore );
294 
295      return DFB_OK;
296 }
297 
298 static DFBResult
dfb_graphics_core_shutdown(DFBGraphicsCore * data,bool emergency)299 dfb_graphics_core_shutdown( DFBGraphicsCore *data,
300                             bool             emergency )
301 {
302      DFBGraphicsCoreShared *shared;
303      FusionSHMPoolShared   *pool = dfb_core_shmpool( data->core );
304 
305      D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " );
306 
307      D_MAGIC_ASSERT( data, DFBGraphicsCore );
308      D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared );
309 
310      shared = data->shared;
311 
312      dfb_gfxcard_lock( GDLF_SYNC );
313 
314      if (data->driver_funcs) {
315           const GraphicsDriverFuncs *funcs = data->driver_funcs;
316 
317           funcs->CloseDevice( data, data->driver_data, data->device_data );
318           funcs->CloseDriver( data, data->driver_data );
319 
320           direct_module_unref( data->module );
321 
322           SHFREE( pool, card->device_data );
323           D_FREE( card->driver_data );
324      }
325 
326      fusion_skirmish_destroy( &shared->lock );
327 
328      if (shared->module_name)
329           SHFREE( pool, shared->module_name );
330 
331 
332      D_MAGIC_CLEAR( data );
333      D_MAGIC_CLEAR( shared );
334 
335      return DFB_OK;
336 }
337 
338 static DFBResult
dfb_graphics_core_leave(DFBGraphicsCore * data,bool emergency)339 dfb_graphics_core_leave( DFBGraphicsCore *data,
340                          bool             emergency )
341 {
342      DFBGraphicsCoreShared *shared;
343 
344      D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " );
345 
346      D_MAGIC_ASSERT( data, DFBGraphicsCore );
347      D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared );
348 
349      shared = data->shared;
350 
351      if (data->driver_funcs) {
352           data->driver_funcs->CloseDriver( data, data->driver_data );
353 
354           direct_module_unref( data->module );
355 
356           D_FREE( data->driver_data );
357      }
358 
359 
360      D_MAGIC_CLEAR( data );
361 
362      return DFB_OK;
363 }
364 
365 static DFBResult
dfb_graphics_core_suspend(DFBGraphicsCore * data)366 dfb_graphics_core_suspend( DFBGraphicsCore *data )
367 {
368      DFBGraphicsCoreShared *shared;
369 
370      D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_suspend( %p )\n", data );
371 
372      D_MAGIC_ASSERT( data, DFBGraphicsCore );
373      D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared );
374 
375      shared = data->shared;
376 
377      dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC | GDLF_RESET | GDLF_INVALIDATE );
378 
379      return DFB_OK;
380 }
381 
382 static DFBResult
dfb_graphics_core_resume(DFBGraphicsCore * data)383 dfb_graphics_core_resume( DFBGraphicsCore *data )
384 {
385      DFBGraphicsCoreShared *shared;
386 
387      D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_resume( %p )\n", data );
388 
389      D_MAGIC_ASSERT( data, DFBGraphicsCore );
390      D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared );
391 
392      shared = data->shared;
393 
394      dfb_gfxcard_unlock();
395 
396      return DFB_OK;
397 }
398 
399 /**********************************************************************************************************************/
400 
401 DFBResult
dfb_gfxcard_lock(GraphicsDeviceLockFlags flags)402 dfb_gfxcard_lock( GraphicsDeviceLockFlags flags )
403 {
404      DFBResult              ret;
405      DFBGraphicsCoreShared *shared;
406      GraphicsDeviceFuncs   *funcs;
407 
408      D_ASSERT( card != NULL );
409      D_ASSERT( card->shared != NULL );
410 
411      shared = card->shared;
412      funcs  = &card->funcs;
413 
414      ret = fusion_skirmish_prevail( &shared->lock );
415      if (ret)
416           return ret;
417 
418      if ((flags & GDLF_SYNC) && funcs->EngineSync) {
419           ret = funcs->EngineSync( card->driver_data, card->device_data );
420           if (ret) {
421                if (funcs->EngineReset)
422                     funcs->EngineReset( card->driver_data, card->device_data );
423 
424                shared->state = NULL;
425 
426                fusion_skirmish_dismiss( &shared->lock );
427 
428                return ret;
429           }
430      }
431 
432      if ((shared->lock_flags & GDLF_RESET) && funcs->EngineReset)
433           funcs->EngineReset( card->driver_data, card->device_data );
434 
435      if (shared->lock_flags & GDLF_INVALIDATE) {
436           if (funcs->InvalidateState)
437                funcs->InvalidateState( card->driver_data, card->device_data );
438           shared->state = NULL;
439      }
440 
441      shared->lock_flags = flags;
442 
443      return DFB_OK;
444 }
445 
446 void
dfb_gfxcard_unlock(void)447 dfb_gfxcard_unlock( void )
448 {
449      D_ASSERT( card != NULL );
450      D_ASSERT( card->shared != NULL );
451 
452      fusion_skirmish_dismiss( &card->shared->lock );
453 }
454 
455 /*
456  * Signal beginning of a sequence of operations using this state.
457  * Any number of states can be 'drawing'.
458  */
459 void
dfb_gfxcard_start_drawing(CoreGraphicsDevice * device,CardState * state)460 dfb_gfxcard_start_drawing( CoreGraphicsDevice *device, CardState *state )
461 {
462      D_ASSERT( device != NULL );
463      D_MAGIC_ASSERT( state, CardState );
464 
465      if (device->funcs.StartDrawing)
466           device->funcs.StartDrawing( device->driver_data, device->device_data, state );
467 }
468 
469 /*
470  * Signal end of sequence, i.e. destination surface is consistent again.
471  */
472 void
dfb_gfxcard_stop_drawing(CoreGraphicsDevice * device,CardState * state)473 dfb_gfxcard_stop_drawing( CoreGraphicsDevice *device, CardState *state )
474 {
475      D_ASSERT( device != NULL );
476      D_MAGIC_ASSERT( state, CardState );
477 
478      if (device->funcs.StopDrawing)
479           device->funcs.StopDrawing( device->driver_data, device->device_data, state );
480 }
481 
482 /*
483  * This function returns non zero if acceleration is available
484  * for the specific function using the given state.
485  */
486 bool
dfb_gfxcard_state_check(CardState * state,DFBAccelerationMask accel)487 dfb_gfxcard_state_check( CardState *state, DFBAccelerationMask accel )
488 {
489      CoreSurface       *dst;
490      CoreSurface       *src;
491      CoreSurfaceBuffer *dst_buffer;
492      CoreSurfaceBuffer *src_buffer;
493 
494      int cx2, cy2;
495 
496      D_ASSERT( card != NULL );
497      D_MAGIC_ASSERT( state, CardState );
498      D_MAGIC_ASSERT_IF( state->destination, CoreSurface );
499      D_MAGIC_ASSERT_IF( state->source, CoreSurface );
500 
501      D_DEBUG_AT( Core_GraphicsOps, "%s( %p, 0x%08x ) [%d,%d - %d,%d]\n",
502                  __FUNCTION__, state, accel, DFB_REGION_VALS( &state->clip ) );
503 
504      D_ASSERT( state->clip.x2 >= state->clip.x1 );
505      D_ASSERT( state->clip.y2 >= state->clip.y1 );
506      D_ASSERT( state->clip.x1 >= 0 );
507      D_ASSERT( state->clip.y1 >= 0 );
508 
509      if (DFB_BLITTING_FUNCTION(accel)) {
510           D_DEBUG_AT( Core_GfxState, "%s( %p, 0x%08x )  blitting %p -> %p\n", __FUNCTION__,
511                       state, accel, state->source, state->destination );
512      }
513      else {
514           D_DEBUG_AT( Core_GfxState, "%s( %p, 0x%08x )  drawing -> %p\n", __FUNCTION__,
515                       state, accel, state->destination );
516      }
517 
518      if (state->clip.x1 < 0) {
519           state->clip.x1   = 0;
520           state->modified |= SMF_CLIP;
521      }
522 
523      if (state->clip.y1 < 0) {
524           state->clip.y1   = 0;
525           state->modified |= SMF_CLIP;
526      }
527 
528      D_DEBUG_AT( Core_GfxState, "  <- checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\n",
529                  state->checked, state->accel, state->modified, state->mod_hw );
530 
531      dst = state->destination;
532      src = state->source;
533 
534      /* Destination may have been destroyed. */
535      if (!dst) {
536           D_BUG( "no destination" );
537           return false;
538      }
539 
540      /* Destination buffer may have been destroyed (suspended). i.e by a vt-switching */
541      if (dst->num_buffers == 0 ) {
542           return false;
543      }
544 
545      /* Source may have been destroyed. */
546      if (DFB_BLITTING_FUNCTION( accel )) {
547           if (!src) {
548                D_BUG( "no source" );
549                return false;
550           }
551 
552           /* Mask may have been destroyed. */
553           if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR) && !state->source_mask) {
554                D_BUG( "no mask" );
555                return false;
556           }
557 
558           /* Source2 may have been destroyed. */
559           if (accel == DFXL_BLIT2 && !state->source2) {
560                D_BUG( "no source2" );
561                return false;
562           }
563      }
564 
565      dst_buffer = dfb_surface_get_buffer( dst, state->to );
566      D_MAGIC_ASSERT( dst_buffer, CoreSurfaceBuffer );
567 
568      D_ASSUME( state->clip.x2 < dst->config.size.w );
569      D_ASSUME( state->clip.y2 < dst->config.size.h );
570 
571      cx2 = state->destination->config.size.w  - 1;
572      cy2 = state->destination->config.size.h - 1;
573 
574      if (state->clip.x2 > cx2) {
575           state->clip.x2 = cx2;
576 
577           if (state->clip.x1 > cx2)
578                state->clip.x1 = cx2;
579 
580           state->modified |= SMF_CLIP;
581      }
582 
583      if (state->clip.y2 > cy2) {
584           state->clip.y2 = cy2;
585 
586           if (state->clip.y1 > cy2)
587                state->clip.y1 = cy2;
588 
589           state->modified |= SMF_CLIP;
590      }
591 
592 
593      /*
594       * If there's no CheckState function there's no acceleration at all.
595       */
596      if (!card->funcs.CheckState)
597           return false;
598 
599      /*
600       * Check if this function has been disabled temporarily.
601       */
602      if (state->disabled & accel)
603           return false;
604 
605      /* If destination or blend functions have been changed... */
606      if (state->modified & (SMF_DESTINATION | SMF_SRC_BLEND | SMF_DST_BLEND | SMF_RENDER_OPTIONS)) {
607           /* ...force rechecking for all functions. */
608           state->checked = DFXL_NONE;
609      }
610      else {
611           /* If source/mask or blitting flags have been changed... */
612           if (state->modified & (SMF_SOURCE | SMF_BLITTING_FLAGS | SMF_SOURCE_MASK | SMF_SOURCE_MASK_VALS)) {
613                /* ...force rechecking for all blitting functions. */
614                state->checked &= ~DFXL_ALL_BLIT;
615           }
616           else if (state->modified & SMF_SOURCE2) {
617                /* Otherwise force rechecking for blit2 function if source2 has been changed. */
618                state->checked &= ~DFXL_BLIT2;
619           }
620 
621           /* If drawing flags have been changed... */
622           if (state->modified & SMF_DRAWING_FLAGS) {
623                /* ...force rechecking for all drawing functions. */
624                state->checked &= ~DFXL_ALL_DRAW;
625           }
626      }
627 
628      D_DEBUG_AT( Core_GfxState, "  -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\n",
629                  state->checked, state->accel, state->modified, state->mod_hw );
630 
631      /* If the function needs to be checked... */
632      if (!(state->checked & accel)) {
633           /* Unset unchecked functions. */
634           state->accel &= state->checked;
635 
636           /* Call driver to (re)set the bit if the function is supported. */
637           card->funcs.CheckState( card->driver_data, card->device_data, state, accel );
638 
639           /* Add the function to 'checked functions'. */
640           state->checked |= accel;
641 
642           /* Add additional functions the driver might have checked, too. */
643           state->checked |= state->accel;
644      }
645 
646      D_DEBUG_AT( Core_GfxState, "  -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\n",
647                  state->checked, state->accel, state->modified, state->mod_hw );
648 
649      /* Move modification flags to the set for drivers. */
650      state->mod_hw   |= state->modified;
651      state->modified  = 0;
652 
653      /*
654       * If back_buffer policy is 'system only' and the GPU does not fully
655       * support system memory surfaces there's no acceleration available.
656       */
657      if ((dst_buffer->policy == CSP_SYSTEMONLY &&
658           !(card->caps.flags & CCF_READSYSMEM &&
659             card->caps.flags & CCF_WRITESYSMEM)) || /* Special check required if driver does not check itself. */
660                                                     ( !(card->caps.flags & CCF_RENDEROPTS) &&
661                                                        (state->render_options & DSRO_MATRIX) ))
662      {
663           /* Clear 'accelerated functions'. */
664           state->accel   = DFXL_NONE;
665           state->checked = DFXL_ALL;
666      }
667      else if (DFB_BLITTING_FUNCTION( accel )) {
668           /*
669            * If the front buffer policy of the source is 'system only'
670            * no accelerated blitting is available.
671            */
672           src_buffer = dfb_surface_get_buffer( src, state->from );
673 
674           D_MAGIC_ASSERT( src_buffer, CoreSurfaceBuffer );
675 
676           if (src_buffer->policy == CSP_SYSTEMONLY && !(card->caps.flags & CCF_READSYSMEM)) {
677                /* Clear 'accelerated blitting functions'. */
678                state->accel   &= ~DFXL_ALL_BLIT;
679                state->checked |=  DFXL_ALL_BLIT;
680           }
681      }
682 
683      D_DEBUG_AT( Core_GfxState, "  => checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\n",
684                  state->checked, state->accel, state->modified, state->mod_hw );
685 
686      /* Return whether the function bit is set. */
687      return !!(state->accel & accel);
688 }
689 
690 /*
691  * This function returns non zero after successful locking the surface(s)
692  * for access by hardware. Propagate state changes to driver.
693  */
694 static bool
dfb_gfxcard_state_acquire(CardState * state,DFBAccelerationMask accel)695 dfb_gfxcard_state_acquire( CardState *state, DFBAccelerationMask accel )
696 {
697      DFBResult               ret;
698      CoreSurface            *dst;
699      CoreSurface            *src;
700      DFBGraphicsCoreShared  *shared;
701      CoreSurfaceAccessFlags  access = CSAF_WRITE;
702 
703      D_ASSERT( card != NULL );
704      D_ASSERT( card->shared != NULL );
705 
706      D_MAGIC_ASSERT( state, CardState );
707      D_MAGIC_ASSERT_IF( state->destination, CoreSurface );
708      D_MAGIC_ASSERT_IF( state->source, CoreSurface );
709 
710      dst    = state->destination;
711      src    = state->source;
712      shared = card->shared;
713 
714      /* find locking flags */
715      if (DFB_BLITTING_FUNCTION( accel )) {
716           if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL |
717                                       DSBLIT_BLEND_COLORALPHA   |
718                                       DSBLIT_DST_COLORKEY))
719                access |= CSAF_READ;
720      }
721      else if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_DST_COLORKEY))
722           access |= CSAF_READ;
723 
724      if (DFB_BLITTING_FUNCTION(accel)) {
725           D_DEBUG_AT( Core_GfxState, "%s( %p, 0x%08x )  blitting %p -> %p\n", __FUNCTION__,
726                       state, accel, state->source, state->destination );
727      }
728      else {
729           D_DEBUG_AT( Core_GfxState, "%s( %p, 0x%08x )  drawing -> %p\n", __FUNCTION__,
730                       state, accel, state->destination );
731      }
732 
733      /*
734       * Push our own identity for buffer locking calls (locality of accessor)
735       */
736      Core_PushIdentity( 0 );
737 
738      /* lock destination */
739      ret = dfb_surface_lock_buffer( dst, state->to, CSAID_GPU, access, &state->dst );
740      if (ret) {
741           D_DEBUG_AT( Core_Graphics, "Could not lock destination for GPU access!\n" );
742           Core_PopIdentity();
743           return false;
744      }
745 
746      /* if blitting... */
747      if (DFB_BLITTING_FUNCTION( accel )) {
748           /* ...lock source for reading */
749           ret = dfb_surface_lock_buffer( src, state->from, CSAID_GPU, CSAF_READ, &state->src );
750           if (ret) {
751                D_DEBUG_AT( Core_Graphics, "Could not lock source for GPU access!\n" );
752                dfb_surface_unlock_buffer( dst, &state->dst );
753                Core_PopIdentity();
754                return false;
755           }
756 
757           state->flags |= CSF_SOURCE_LOCKED;
758 
759           /* if using a mask... */
760           if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {
761                /* ...lock source mask for reading */
762                ret = dfb_surface_lock_buffer( state->source_mask, state->from, CSAID_GPU, CSAF_READ, &state->src_mask );
763                if (ret) {
764                     D_DEBUG_AT( Core_Graphics, "Could not lock source mask for GPU access!\n" );
765                     dfb_surface_unlock_buffer( src, &state->src );
766                     dfb_surface_unlock_buffer( dst, &state->dst );
767                     Core_PopIdentity();
768                     return false;
769                }
770 
771                state->flags |= CSF_SOURCE_MASK_LOCKED;
772           }
773 
774           /* if using source2... */
775           if (accel == DFXL_BLIT2) {
776                /* ...lock source2 for reading */
777                ret = dfb_surface_lock_buffer( state->source2, state->from, CSAID_GPU, CSAF_READ, &state->src2 );
778                if (ret) {
779                     D_DEBUG_AT( Core_Graphics, "Could not lock source2 for GPU access!\n" );
780 
781                     if (state->flags & CSF_SOURCE_MASK_LOCKED)
782                          dfb_surface_unlock_buffer( src, &state->src_mask );
783 
784                     dfb_surface_unlock_buffer( src, &state->src );
785                     dfb_surface_unlock_buffer( dst, &state->dst );
786                     Core_PopIdentity();
787                     return false;
788                }
789 
790                state->flags |= CSF_SOURCE2_LOCKED;
791           }
792      }
793 
794      /*
795       * Make sure that state setting with subsequent command execution
796       * isn't done by two processes simultaneously.
797       *
798       * This will timeout if the hardware is locked by another party with
799       * the first argument being true (e.g. DRI).
800       */
801      ret = dfb_gfxcard_lock( GDLF_NONE );
802      if (ret) {
803           D_DERROR( ret, "Core/Graphics: Could not lock GPU!\n" );
804 
805           dfb_surface_unlock_buffer( dst, &state->dst );
806 
807           if (state->flags & CSF_SOURCE_LOCKED) {
808                dfb_surface_unlock_buffer( src, &state->src );
809                state->flags &= ~CSF_SOURCE_LOCKED;
810           }
811 
812           /* if source mask got locked this value is true */
813           if (state->flags & CSF_SOURCE_MASK_LOCKED) {
814                dfb_surface_unlock_buffer( state->source_mask, &state->src_mask );
815 
816                state->flags &= ~CSF_SOURCE_MASK_LOCKED;
817           }
818 
819           Core_PopIdentity();
820 
821           return false;
822      }
823 
824      /* if we are switching to another state... */
825      if (state != shared->state || state->fusion_id != shared->holder) {
826           D_DEBUG_AT( Core_GfxState, "  -> switch from %p [%lu] to %p [%lu]\n",
827                       shared->state, shared->holder, state, state->fusion_id );
828 
829           /* ...set all modification bits and clear 'set functions' */
830           state->mod_hw |= SMF_ALL;
831           state->set     = 0;
832 
833           shared->state  = state;
834           shared->holder = state->fusion_id;
835      }
836 
837      dfb_state_update( state, state->flags & (CSF_SOURCE_LOCKED | CSF_SOURCE2_LOCKED | CSF_SOURCE_MASK_LOCKED) );
838 
839      D_DEBUG_AT( Core_GfxState, "  -> mod_hw 0x%08x, modified 0x%08x\n", state->mod_hw, state->modified );
840 
841      /* Move modification flags to the set for drivers. */
842      state->mod_hw   |= state->modified;
843      state->modified  = SMF_ALL;
844 
845      /*
846       * If function hasn't been set or state is modified,
847       * call the driver function to propagate the state changes.
848       */
849      D_DEBUG_AT( Core_GfxState, "  -> mod_hw 0x%08x, set 0x%08x\n", state->mod_hw, state->set );
850      if (state->mod_hw || !(state->set & accel)) {
851           card->funcs.SetState( card->driver_data, card->device_data,
852                                 &card->funcs, state, accel );
853 
854           D_DEBUG_AT( Core_GfxState, "  => mod_hw 0x%08x, set 0x%08x\n", state->mod_hw, state->set );
855      }
856 
857      if (state->modified != SMF_ALL)
858           D_ONCE( "USING OLD DRIVER! *** Use 'state->mod_hw' NOT 'modified'." );
859 
860      state->modified = 0;
861 
862      return true;
863 }
864 
865 /*
866  * Unlock destination and possibly the source.
867  */
868 static void
dfb_gfxcard_state_release(CardState * state)869 dfb_gfxcard_state_release( CardState *state )
870 {
871      D_ASSERT( card != NULL );
872      D_ASSERT( card->shared != NULL );
873      D_MAGIC_ASSERT( state, CardState );
874      D_ASSERT( state->destination != NULL );
875 
876      if (!dfb_config->software_only) {
877           /* start command processing if not already running */
878           if (card->funcs.EmitCommands)
879                card->funcs.EmitCommands( card->driver_data, card->device_data );
880 
881           /* Store the serial of the operation. */
882 #if FIXME_SC_2
883           if (card->funcs.GetSerial) {
884                card->funcs.GetSerial( card->driver_data, card->device_data, &state->serial );
885 
886               state->destination->back_buffer->video.serial = state->serial;
887           }
888 #endif
889      }
890 
891      /* allow others to use the hardware */
892      dfb_gfxcard_unlock();
893 
894      /* destination always gets locked during acquisition */
895      dfb_surface_unlock_buffer( state->destination, &state->dst );
896 
897      /* if source got locked this value is true */
898      if (state->flags & CSF_SOURCE_LOCKED) {
899           dfb_surface_unlock_buffer( state->source, &state->src );
900 
901           state->flags &= ~CSF_SOURCE_LOCKED;
902      }
903 
904      /* if source mask got locked this value is true */
905      if (state->flags & CSF_SOURCE_MASK_LOCKED) {
906           dfb_surface_unlock_buffer( state->source_mask, &state->src_mask );
907 
908           state->flags &= ~CSF_SOURCE_MASK_LOCKED;
909      }
910 
911      /* if source2 got locked this value is true */
912      if (state->flags & CSF_SOURCE2_LOCKED) {
913           dfb_surface_unlock_buffer( state->source2, &state->src2 );
914 
915           state->flags &= ~CSF_SOURCE2_LOCKED;
916      }
917 
918      Core_PopIdentity();
919 }
920 
921 /** DRAWING FUNCTIONS **/
922 
923 #define DFB_TRANSFORM(x, y, m, affine) \
924 do { \
925      s32 _x, _y, _w; \
926      if (affine) { \
927           _x = ((x) * (m)[0] + (y) * (m)[1] + (m)[2] + 0x8000) >> 16; \
928           _y = ((x) * (m)[3] + (y) * (m)[4] + (m)[5] + 0x8000) >> 16; \
929      } \
930      else { \
931           _x = ((x) * (m)[0] + (y) * (m)[1] + (m)[2]); \
932           _y = ((x) * (m)[3] + (y) * (m)[4] + (m)[5]); \
933           _w = ((x) * (m)[6] + (y) * (m)[7] + (m)[8]); \
934           if (!_w) { \
935                _x = (_x < 0) ? -0x7fffffff : 0x7fffffff; \
936                _y = (_y < 0) ? -0x7fffffff : 0x7fffffff; \
937           } \
938           else { \
939                _x /= _w; \
940                _y /= _w; \
941           } \
942      } \
943      (x) = _x; \
944      (y) = _y; \
945 } while (0)
946 
947 void
dfb_gfxcard_fillrectangles(const DFBRectangle * rects,int num,CardState * state)948 dfb_gfxcard_fillrectangles( const DFBRectangle *rects, int num, CardState *state )
949 {
950      D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %p )\n", __FUNCTION__, rects, num, state );
951 
952      D_ASSERT( card != NULL );
953      D_ASSERT( card->shared != NULL );
954      D_MAGIC_ASSERT( state, CardState );
955      D_ASSERT( rects != NULL );
956      D_ASSERT( num > 0 );
957 
958      /* The state is locked during graphics operations. */
959      dfb_state_lock( state );
960 
961      /* Signal beginning of sequence of operations if not already done. */
962      dfb_state_start_drawing( state, card );
963 
964      if (!(state->render_options & DSRO_MATRIX)) {
965           while (num > 0) {
966                if (dfb_rectangle_region_intersects( rects, &state->clip ))
967                     break;
968 
969                rects++;
970                num--;
971           }
972      }
973 
974      if (num > 0) {
975           int          i = 0;
976           DFBRectangle rect;
977 
978           /* Check for acceleration and setup execution. */
979           if (dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ) &&
980               dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE ))
981           {
982                /*
983                 * Now everything is prepared for execution of the
984                 * FillRectangle driver function.
985                 */
986                for (; i<num; i++) {
987                     if (!(state->render_options & DSRO_MATRIX) &&
988                         !dfb_rectangle_region_intersects( &rects[i], &state->clip ))
989                          continue;
990 
991                     rect = rects[i];
992 
993                     if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h) {
994                          dfb_clip_rectangle( &state->clip, &rect );
995 
996                          if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h)
997                               break;
998                     }
999                     else if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
1000                              !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLRECTANGLE ))
1001                          dfb_clip_rectangle( &state->clip, &rect );
1002 
1003                     if (!card->funcs.FillRectangle( card->driver_data,
1004                                                     card->device_data, &rect ))
1005                          break;
1006                }
1007 
1008                /* Release after state acquisition. */
1009                dfb_gfxcard_state_release( state );
1010           }
1011 
1012           if (i < num) {
1013                /* Use software fallback. */
1014                if (!(state->render_options & DSRO_MATRIX)) {
1015                     if (gAcquire( state, DFXL_FILLRECTANGLE )) {
1016                          for (; i<num; i++) {
1017                               rect = rects[i];
1018 
1019                               if (dfb_clip_rectangle( &state->clip, &rect ))
1020                                    gFillRectangle( state, &rect );
1021                          }
1022 
1023                          gRelease( state );
1024                     }
1025                }
1026                else if (state->matrix[1] == 0 && state->matrix[3] == 0) {
1027                     /* Scaled/Translated Rectangles */
1028                     DFBRectangle tr[num];
1029                     int          n = 0;
1030 
1031                     for (; i<num; i++) {
1032                          int x1, y1, x2, y2;
1033 
1034                          x1 = rects[i].x;    y1 = rects[i].y;
1035                          x2 = x1+rects[i].w; y2 = y1+rects[i].h;
1036                          DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix);
1037                          DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix);
1038 
1039                          if (x1 < x2) {
1040                               tr[n].x = x1;
1041                               tr[n].w = x2-x1;
1042                          } else {
1043                               tr[n].x = x2;
1044                               tr[n].w = x1-x2;
1045                          }
1046                          if (y1 < y2) {
1047                               tr[n].y = y1;
1048                               tr[n].h = y2-y1;
1049                          }
1050                          else {
1051                               tr[n].y = y2;
1052                               tr[n].h = y1-y2;
1053                          }
1054 
1055                          if (dfb_clip_rectangle( &state->clip, &tr[n] ))
1056                               n++;
1057                     }
1058 
1059                     if (n > 0) {
1060                          state->render_options &= ~DSRO_MATRIX;
1061                          state->modified       |= SMF_RENDER_OPTIONS;
1062 
1063                          dfb_gfxcard_fillrectangles( tr, n, state );
1064 
1065                          state->render_options |= DSRO_MATRIX;
1066                          state->modified       |= SMF_RENDER_OPTIONS;
1067                     }
1068                }
1069                else {
1070                     /* Rotated rectangle. Split into triangles. */
1071                     if (gAcquire( state, DFXL_FILLRECTANGLE )) {
1072                          for (; i<num; i++) {
1073                               DFBTriangle tri;
1074 
1075                               tri.x1 = rects[i].x;            tri.y1 = rects[i].y;
1076                               tri.x2 = rects[i].x+rects[i].w; tri.y2 = rects[i].y;
1077                               tri.x3 = rects[i].x+rects[i].w; tri.y3 = rects[i].y+rects[i].h;
1078                               DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix);
1079                               DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix);
1080                               DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix);
1081 
1082                               dfb_sort_triangle( &tri );
1083                               if (tri.y3 - tri.y1 > 0)
1084                                    fill_tri( &tri, state, false );
1085 
1086                               tri.x1 = rects[i].x;            tri.y1 = rects[i].y;
1087                               tri.x2 = rects[i].x+rects[i].w; tri.y2 = rects[i].y+rects[i].h;
1088                               tri.x3 = rects[i].x;            tri.y3 = rects[i].y+rects[i].h;
1089                               DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix);
1090                               DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix);
1091                               DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix);
1092 
1093                               dfb_sort_triangle( &tri );
1094                               if (tri.y3 - tri.y1 > 0)
1095                                    fill_tri( &tri, state, false );
1096                          }
1097 
1098                          gRelease( state );
1099                     }
1100                }
1101           }
1102      }
1103 
1104      /* Unlock after execution. */
1105      dfb_state_unlock( state );
1106 }
1107 
1108 static void
build_clipped_rectangle_outlines(DFBRectangle * rect,const DFBRegion * clip,DFBRectangle * ret_outlines,int * ret_num)1109 build_clipped_rectangle_outlines( DFBRectangle    *rect,
1110                                   const DFBRegion *clip,
1111                                   DFBRectangle    *ret_outlines,
1112                                   int             *ret_num )
1113 {
1114      DFBEdgeFlags edges = dfb_clip_edges( clip, rect );
1115      int          t     = (edges & DFEF_TOP ? 1 : 0);
1116      int          tb    = t + (edges & DFEF_BOTTOM ? 1 : 0);
1117      int          num   = 0;
1118 
1119      DFB_RECTANGLE_ASSERT( rect );
1120 
1121      D_ASSERT( ret_outlines != NULL );
1122      D_ASSERT( ret_num != NULL );
1123 
1124      if (edges & DFEF_TOP) {
1125           DFBRectangle *out = &ret_outlines[num++];
1126 
1127           out->x = rect->x;
1128           out->y = rect->y;
1129           out->w = rect->w;
1130           out->h = 1;
1131      }
1132 
1133      if (rect->h > t) {
1134           if (edges & DFEF_BOTTOM) {
1135                DFBRectangle *out = &ret_outlines[num++];
1136 
1137                out->x = rect->x;
1138                out->y = rect->y + rect->h - 1;
1139                out->w = rect->w;
1140                out->h = 1;
1141           }
1142 
1143           if (rect->h > tb) {
1144                if (edges & DFEF_LEFT) {
1145                     DFBRectangle *out = &ret_outlines[num++];
1146 
1147                     out->x = rect->x;
1148                     out->y = rect->y + t;
1149                     out->w = 1;
1150                     out->h = rect->h - tb;
1151                }
1152 
1153                if (rect->w > 1 || !(edges & DFEF_LEFT)) {
1154                     if (edges & DFEF_RIGHT) {
1155                          DFBRectangle *out = &ret_outlines[num++];
1156 
1157                          out->x = rect->x + rect->w - 1;
1158                          out->y = rect->y + t;
1159                          out->w = 1;
1160                          out->h = rect->h - tb;
1161                     }
1162                }
1163           }
1164      }
1165 
1166      *ret_num = num;
1167 }
1168 
dfb_gfxcard_drawrectangle(DFBRectangle * rect,CardState * state)1169 void dfb_gfxcard_drawrectangle( DFBRectangle *rect, CardState *state )
1170 {
1171      DFBRectangle rects[4];
1172      bool         hw = false;
1173      int          i = 0, num = 0;
1174 
1175      D_ASSERT( card != NULL );
1176      D_ASSERT( card->shared != NULL );
1177      D_MAGIC_ASSERT( state, CardState );
1178      DFB_RECTANGLE_ASSERT( rect );
1179 
1180      D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %dx%d, %p )\n", __FUNCTION__, DFB_RECTANGLE_VALS(rect), state );
1181 
1182      /* The state is locked during graphics operations. */
1183      dfb_state_lock( state );
1184 
1185      /* Signal beginning of sequence of operations if not already done. */
1186      dfb_state_start_drawing( state, card );
1187 
1188      if (!(state->render_options & DSRO_MATRIX) &&
1189          !dfb_rectangle_region_intersects( rect, &state->clip ))
1190      {
1191           dfb_state_unlock( state );
1192           return;
1193      }
1194 
1195      if (D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) ||
1196          D_FLAGS_IS_SET( card->caps.clip, DFXL_DRAWRECTANGLE ) ||
1197          !dfb_clip_needed( &state->clip, rect ))
1198      {
1199           if (rect->w <= card->limits.dst_max.w && rect->h <= card->limits.dst_max.h &&
1200               dfb_gfxcard_state_check( state, DFXL_DRAWRECTANGLE ) &&
1201               dfb_gfxcard_state_acquire( state, DFXL_DRAWRECTANGLE ))
1202           {
1203                hw = card->funcs.DrawRectangle( card->driver_data,
1204                                                card->device_data, rect );
1205 
1206                dfb_gfxcard_state_release( state );
1207           }
1208      }
1209 
1210      if (!hw && !(state->render_options & DSRO_MATRIX)) {
1211           build_clipped_rectangle_outlines( rect, &state->clip, rects, &num );
1212 
1213           if (!num) {
1214                dfb_state_unlock( state );
1215                return;
1216           }
1217 
1218           if (dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ) &&
1219               dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE ))
1220           {
1221                for (; i<num; i++) {
1222                     hw = rects[i].w <= card->limits.dst_max.w && rects[i].h <= card->limits.dst_max.h
1223                          && card->funcs.FillRectangle( card->driver_data,
1224                                                        card->device_data, &rects[i] );
1225                     if (!hw)
1226                          break;
1227                }
1228 
1229                dfb_gfxcard_state_release( state );
1230           }
1231      }
1232 
1233      if (!hw) {
1234           if (!(state->render_options & DSRO_MATRIX)) {
1235                if (gAcquire( state, DFXL_FILLRECTANGLE )) {
1236                     for (; i<num; i++)
1237                          gFillRectangle( state, &rects[i] );
1238 
1239                     gRelease( state );
1240                }
1241           }
1242           else {
1243                 if (gAcquire( state, DFXL_DRAWLINE )) {
1244                     DFBRegion line;
1245                     int       x1, x2, x3, x4;
1246                     int       y1, y2, y3, y4;
1247 
1248                     x1 = rect->x;         y1 = rect->y;
1249                     x2 = rect->x+rect->w; y2 = rect->y;
1250                     x3 = rect->x+rect->w; y3 = rect->y+rect->h;
1251                     x4 = rect->x;         y4 = rect->y+rect->h;
1252                     DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix);
1253                     DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix);
1254                     DFB_TRANSFORM(x3, y3, state->matrix, state->affine_matrix);
1255                     DFB_TRANSFORM(x4, y4, state->matrix, state->affine_matrix);
1256 
1257                     line = (DFBRegion) { x1, y1, x2, y2 };
1258                     if (dfb_clip_line( &state->clip, &line ))
1259                          gDrawLine( state, &line );
1260 
1261                     line = (DFBRegion) { x2, y2, x3, y3 };
1262                     if (dfb_clip_line( &state->clip, &line ))
1263                          gDrawLine( state, &line );
1264 
1265                     line = (DFBRegion) { x3, y3, x4, y4 };
1266                     if (dfb_clip_line( &state->clip, &line ))
1267                          gDrawLine( state, &line );
1268 
1269                     line = (DFBRegion) { x4, y4, x1, y1 };
1270                     if (dfb_clip_line( &state->clip, &line ))
1271                          gDrawLine( state, &line );
1272 
1273                     gRelease( state );
1274                }
1275           }
1276      }
1277 
1278      dfb_state_unlock( state );
1279 }
1280 
dfb_gfxcard_drawlines(DFBRegion * lines,int num_lines,CardState * state)1281 void dfb_gfxcard_drawlines( DFBRegion *lines, int num_lines, CardState *state )
1282 {
1283      int i = 0;
1284 
1285      D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %p )\n", __FUNCTION__, lines, num_lines, state );
1286 
1287      D_ASSERT( card != NULL );
1288      D_ASSERT( card->shared != NULL );
1289      D_MAGIC_ASSERT( state, CardState );
1290      D_ASSERT( lines != NULL );
1291      D_ASSERT( num_lines > 0 );
1292 
1293      /* The state is locked during graphics operations. */
1294      dfb_state_lock( state );
1295 
1296      /* Signal beginning of sequence of operations if not already done. */
1297      dfb_state_start_drawing( state, card );
1298 
1299      if (dfb_gfxcard_state_check( state, DFXL_DRAWLINE ) &&
1300          dfb_gfxcard_state_acquire( state, DFXL_DRAWLINE ))
1301      {
1302           for (; i<num_lines; i++) {
1303                if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
1304                    !D_FLAGS_IS_SET( card->caps.clip, DFXL_DRAWLINE ) &&
1305                    !dfb_clip_line( &state->clip, &lines[i] ))
1306                     continue;
1307 
1308                if (!card->funcs.DrawLine( card->driver_data,
1309                                           card->device_data, &lines[i] ))
1310                     break;
1311           }
1312 
1313           dfb_gfxcard_state_release( state );
1314      }
1315 
1316      if (i < num_lines) {
1317           if (gAcquire( state, DFXL_DRAWLINE )) {
1318                for (; i<num_lines; i++) {
1319                     if (state->render_options & DSRO_MATRIX) {
1320                          DFB_TRANSFORM(lines[i].x1, lines[i].y1, state->matrix, state->affine_matrix);
1321                          DFB_TRANSFORM(lines[i].x2, lines[i].y2, state->matrix, state->affine_matrix);
1322                     }
1323 
1324                     if (dfb_clip_line( &state->clip, &lines[i] ))
1325                          gDrawLine( state, &lines[i] );
1326                }
1327 
1328                gRelease( state );
1329           }
1330      }
1331 
1332      dfb_state_unlock( state );
1333 }
1334 
dfb_gfxcard_fillspans(int y,DFBSpan * spans,int num_spans,CardState * state)1335 void dfb_gfxcard_fillspans( int y, DFBSpan *spans, int num_spans, CardState *state )
1336 {
1337      int i = 0;
1338 
1339      D_DEBUG_AT( Core_GraphicsOps, "%s( %d, %p [%d], %p )\n", __FUNCTION__, y, spans, num_spans, state );
1340 
1341      D_ASSERT( card != NULL );
1342      D_ASSERT( card->shared != NULL );
1343      D_MAGIC_ASSERT( state, CardState );
1344      D_ASSERT( spans != NULL );
1345      D_ASSERT( num_spans > 0 );
1346 
1347      /* The state is locked during graphics operations. */
1348      dfb_state_lock( state );
1349 
1350      /* Signal beginning of sequence of operations if not already done. */
1351      dfb_state_start_drawing( state, card );
1352 
1353      if (dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ) &&
1354          dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE ))
1355      {
1356           for (; i<num_spans; i++) {
1357                DFBRectangle rect = { spans[i].x, y + i, spans[i].w, 1 };
1358 
1359                if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h) {
1360                     if (!dfb_clip_rectangle( &state->clip, &rect ))
1361                          continue;
1362 
1363                     if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h)
1364                          break;
1365                }
1366                else if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
1367                         !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLRECTANGLE ) &&
1368                         !dfb_clip_rectangle( &state->clip, &rect ))
1369                          continue;
1370 
1371                if (!card->funcs.FillRectangle( card->driver_data,
1372                                                card->device_data, &rect ))
1373                     break;
1374           }
1375 
1376           dfb_gfxcard_state_release( state );
1377      }
1378 
1379      if (i < num_spans) {
1380           if (gAcquire( state, DFXL_FILLRECTANGLE )) {
1381                for (; i<num_spans; i++) {
1382                     DFBRectangle rect = { spans[i].x, y + i, spans[i].w, 1 };
1383 
1384                     if (state->render_options & DSRO_MATRIX) {
1385                          if (state->matrix[1] == 0 && state->matrix[3] == 0) {
1386                               int x1, y1, x2, y2;
1387 
1388                               x1 = rect.x;    y1 = rect.y;
1389                               x2 = x1+rect.w; y2 = y1+rect.h;
1390                               DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix);
1391                               DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix);
1392 
1393                               if (x1 < x2) {
1394                                    rect.x = x1;
1395                                    rect.w = x2-x1;
1396                               } else {
1397                                    rect.x = x2;
1398                                    rect.w = x1-x2;
1399                               }
1400                               if (y1 < y2) {
1401                                    rect.y = y1;
1402                                    rect.h = y2-y1;
1403                               }
1404                               else {
1405                                    rect.y = y2;
1406                                    rect.h = y1-y2;
1407                               }
1408 
1409                               if (dfb_clip_rectangle( &state->clip, &rect ))
1410                                    gFillRectangle( state, &rect );
1411                          }
1412                          else {
1413                               DFBTriangle tri;
1414 
1415                               tri.x1 = rect.x;        tri.y1 = rect.y;
1416                               tri.x2 = rect.x+rect.w; tri.y2 = rect.y;
1417                               tri.x3 = rect.x+rect.w; tri.y3 = rect.y+rect.h;
1418                               DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix);
1419                               DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix);
1420                               DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix);
1421 
1422                               dfb_sort_triangle( &tri );
1423                               if (tri.y3 - tri.y1 > 0)
1424                                    fill_tri( &tri, state, false );
1425 
1426                               tri.x1 = rect.x;        tri.y1 = rect.y;
1427                               tri.x2 = rect.x+rect.w; tri.y2 = rect.y+rect.h;
1428                               tri.x3 = rect.x;        tri.y3 = rect.y+rect.h;
1429                               DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix);
1430                               DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix);
1431                               DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix);
1432 
1433                               dfb_sort_triangle( &tri );
1434                               if (tri.y3 - tri.y1 > 0)
1435                                    fill_tri( &tri, state, false );
1436                          }
1437                     }
1438                     else {
1439                          if (dfb_clip_rectangle( &state->clip, &rect ))
1440                               gFillRectangle( state, &rect );
1441                     }
1442                }
1443 
1444                gRelease( state );
1445           }
1446      }
1447 
1448      dfb_state_unlock( state );
1449 }
1450 
1451 
1452 typedef struct {
1453    int xi;
1454    int xf;
1455    int mi;
1456    int mf;
1457    int _2dy;
1458 } DDA;
1459 
1460 #define SETUP_DDA(xs,ys,xe,ye,dda)         \
1461      do {                                  \
1462           int dx = (xe) - (xs);            \
1463           int dy = (ye) - (ys);            \
1464           dda.xi = (xs);                   \
1465           if (dy != 0) {                   \
1466                dda.mi = dx / dy;           \
1467                dda.mf = 2*(dx % dy);       \
1468                dda.xf = -dy;               \
1469                dda._2dy = 2 * dy;          \
1470                if (dda.mf < 0) {           \
1471                     dda.mf += 2 * ABS(dy); \
1472                     dda.mi--;              \
1473                }                           \
1474           }                                \
1475           else {                           \
1476                dda.mi = 0;                 \
1477                dda.mf = 0;                 \
1478                dda.xf = 0;                 \
1479                dda._2dy = 0;               \
1480           }                                \
1481      } while (0)
1482 
1483 
1484 #define INC_DDA(dda)                       \
1485      do {                                  \
1486           dda.xi += dda.mi;                \
1487           dda.xf += dda.mf;                \
1488           if (dda.xf > 0) {                \
1489                dda.xi++;                   \
1490                dda.xf -= dda._2dy;         \
1491           }                                \
1492      } while (0)
1493 
1494 
1495 
1496 /**
1497  *  render a triangle using two parallel DDA's
1498  */
1499 static void
fill_tri(DFBTriangle * tri,CardState * state,bool accelerated)1500 fill_tri( DFBTriangle *tri, CardState *state, bool accelerated )
1501 {
1502      int y, yend;
1503      DDA dda1 = { .xi = 0 }, dda2 = { .xi = 0 };
1504      int clip_x1 = state->clip.x1;
1505      int clip_x2 = state->clip.x2;
1506 
1507      D_MAGIC_ASSERT( state, CardState );
1508 
1509      y = tri->y1;
1510      yend = tri->y3;
1511 
1512      if (yend > state->clip.y2)
1513           yend = state->clip.y2;
1514 
1515      SETUP_DDA(tri->x1, tri->y1, tri->x3, tri->y3, dda1);
1516      SETUP_DDA(tri->x1, tri->y1, tri->x2, tri->y2, dda2);
1517 
1518      while (y <= yend) {
1519           DFBRectangle rect;
1520 
1521           if (y == tri->y2) {
1522                if (tri->y2 == tri->y3)
1523                     return;
1524                SETUP_DDA(tri->x2, tri->y2, tri->x3, tri->y3, dda2);
1525           }
1526 
1527           rect.w = ABS(dda1.xi - dda2.xi);
1528           rect.x = MIN(dda1.xi, dda2.xi);
1529 
1530           if (clip_x2 < rect.x + rect.w)
1531                rect.w = clip_x2 - rect.x + 1;
1532 
1533           if (rect.w > 0) {
1534                if (clip_x1 > rect.x) {
1535                     rect.w -= (clip_x1 - rect.x);
1536                     rect.x = clip_x1;
1537                }
1538                rect.y = y;
1539                rect.h = 1;
1540 
1541                if (rect.w > 0 && rect.y >= state->clip.y1) {
1542                     if (accelerated)
1543                          card->funcs.FillRectangle( card->driver_data,
1544                                                     card->device_data, &rect );
1545                     else
1546                          gFillRectangle( state, &rect );
1547                }
1548           }
1549 
1550           INC_DDA(dda1);
1551           INC_DDA(dda2);
1552 
1553           y++;
1554      }
1555 }
1556 
1557 /**
1558  *  render a trapezoid using two parallel DDA's
1559  */
1560 static void
fill_trap(DFBTrapezoid * trap,CardState * state,bool accelerated)1561 fill_trap( DFBTrapezoid *trap, CardState *state, bool accelerated )
1562 {
1563      int y, yend;
1564      DDA dda1 = { .xi = 0 }, dda2 = { .xi = 0 };
1565      int clip_x1 = state->clip.x1;
1566      int clip_x2 = state->clip.x2;
1567 
1568      D_MAGIC_ASSERT( state, CardState );
1569 
1570      y = trap->y1;
1571      yend = trap->y2;
1572 
1573      if (yend > state->clip.y2)
1574           yend = state->clip.y2;
1575 
1576      /* top left to bottom left */
1577      SETUP_DDA(trap->x1,                trap->y1, trap->x2,                trap->y2, dda1);
1578      /* top right to bottom right */
1579      SETUP_DDA(trap->x1 + trap->w1 - 1, trap->y1, trap->x2 + trap->w2 - 1, trap->y2, dda2);
1580 
1581      while (y <= yend) {
1582           DFBRectangle rect;
1583 
1584           rect.w = ABS(dda1.xi - dda2.xi);
1585           rect.x = MIN(dda1.xi, dda2.xi);
1586 
1587           if (clip_x2 < rect.x + rect.w)
1588                rect.w = clip_x2 - rect.x + 1;
1589 
1590           if (rect.w > 0) {
1591                if (clip_x1 > rect.x) {
1592                     rect.w -= (clip_x1 - rect.x);
1593                     rect.x = clip_x1;
1594                }
1595                rect.y = y;
1596                rect.h = 1;
1597 
1598                if (rect.w > 0 && rect.y >= state->clip.y1) {
1599                     if (accelerated)
1600                          card->funcs.FillRectangle( card->driver_data,
1601                                                     card->device_data, &rect );
1602                     else
1603                          gFillRectangle( state, &rect );
1604                }
1605           }
1606 
1607           INC_DDA(dda1);
1608           INC_DDA(dda2);
1609 
1610           y++;
1611      }
1612 }
1613 
1614 
1615 
dfb_gfxcard_filltriangles(const DFBTriangle * tris,int num,CardState * state)1616 void dfb_gfxcard_filltriangles( const DFBTriangle *tris, int num, CardState *state )
1617 {
1618      bool hw = false;
1619      int  i  = 0;
1620 
1621      D_ASSERT( card != NULL );
1622      D_ASSERT( card->shared != NULL );
1623      D_MAGIC_ASSERT( state, CardState );
1624      D_ASSERT( tris != NULL );
1625      D_ASSERT( num > 0 );
1626 
1627      D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %p )\n", __FUNCTION__, tris, num, state );
1628 
1629      /* The state is locked during graphics operations. */
1630      dfb_state_lock( state );
1631 
1632      /* Signal beginning of sequence of operations if not already done. */
1633      dfb_state_start_drawing( state, card );
1634 
1635      if (dfb_gfxcard_state_check( state, DFXL_FILLTRIANGLE ) &&
1636          dfb_gfxcard_state_acquire( state, DFXL_FILLTRIANGLE ))
1637      {
1638           if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
1639               !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLTRIANGLE ))
1640           {
1641                DFBPoint p[6];
1642                int      n;
1643 
1644                for (; i < num; i++) {
1645                     /* FIXME: DSRO_MATRIX. */
1646                     if (dfb_clip_triangle( &state->clip, &tris[i], p, &n )) {
1647                          DFBTriangle tri;
1648                          int         j;
1649 
1650                          tri.x1 = p[0].x; tri.y1 = p[0].y;
1651                          tri.x2 = p[1].x; tri.y2 = p[1].y;
1652                          tri.x3 = p[2].x; tri.y3 = p[2].y;
1653                          hw = card->funcs.FillTriangle( card->driver_data,
1654                                                         card->device_data, &tri );
1655                          if (!hw)
1656                               break;
1657 
1658                          /* FIXME: return value. */
1659                          for (j = 3; j < n; j++) {
1660                               tri.x1 = p[0].x;   tri.y1 = p[0].y;
1661                               tri.x2 = p[j-1].x; tri.y2 = p[j-1].y;
1662                               tri.x3 = p[j].x;   tri.y3 = p[j].y;
1663                               card->funcs.FillTriangle( card->driver_data,
1664                                                         card->device_data, &tri );
1665                          }
1666                     }
1667                }
1668           }
1669           else {
1670                for (; i < num; i++) {
1671                     DFBTriangle tri = tris[i];
1672 
1673                     hw = card->funcs.FillTriangle( card->driver_data,
1674                                                    card->device_data, &tri );
1675                     if (!hw)
1676                          break;
1677                }
1678 
1679           }
1680 
1681           dfb_gfxcard_state_release( state );
1682      }
1683 
1684      if (!hw && i < num) {
1685           /* otherwise use the spanline rasterizer (fill_tri)
1686              and fill the triangle using a rectangle for each spanline */
1687 
1688           /* try hardware accelerated rectangle filling */
1689           if (!(card->caps.flags & CCF_NOTRIEMU) &&
1690               dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ) &&
1691               dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE ))
1692           {
1693                for (; i < num; i++) {
1694                     DFBTriangle tri = tris[i];
1695 
1696                     dfb_sort_triangle( &tri );
1697 
1698                     if (tri.y3 - tri.y1 > 0)
1699                          fill_tri( &tri, state, true );
1700                }
1701 
1702                dfb_gfxcard_state_release( state );
1703           }
1704           else if (gAcquire( state, DFXL_FILLRECTANGLE )) {
1705                for (; i < num; i++) {
1706                     DFBTriangle tri = tris[i];
1707 
1708                     if (state->render_options & DSRO_MATRIX) {
1709                          DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix);
1710                          DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix);
1711                          DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix);
1712                     }
1713 
1714                     dfb_sort_triangle( &tri );
1715 
1716                     if (tri.y3 - tri.y1 > 0)
1717                          fill_tri( &tri, state, false );
1718                }
1719 
1720                gRelease( state );
1721           }
1722      }
1723 
1724      dfb_state_unlock( state );
1725 }
1726 
dfb_gfxcard_filltrapezoids(const DFBTrapezoid * traps,int num,CardState * state)1727 void dfb_gfxcard_filltrapezoids( const DFBTrapezoid *traps, int num, CardState *state )
1728 {
1729      bool hw = false;
1730      int  i  = 0;
1731 
1732      D_ASSERT( card != NULL );
1733      D_ASSERT( card->shared != NULL );
1734      D_MAGIC_ASSERT( state, CardState );
1735      D_ASSERT( traps != NULL );
1736      D_ASSERT( num > 0 );
1737 
1738      D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %p )\n", __FUNCTION__, traps, num, state );
1739 
1740      /* The state is locked during graphics operations. */
1741      dfb_state_lock( state );
1742      /* Signal beginning of sequence of operations if not already done. */
1743      dfb_state_start_drawing( state, card );
1744 
1745      if (dfb_gfxcard_state_check( state, DFXL_FILLTRAPEZOID ) &&
1746          dfb_gfxcard_state_acquire( state, DFXL_FILLTRAPEZOID ))
1747      {
1748           if (D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) ||
1749               D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLTRAPEZOID ) ||
1750               (state->render_options & DSRO_MATRIX))
1751           {
1752                for (; i < num; i++) {
1753                     DFBTrapezoid trap = traps[i];
1754 
1755                     hw = card->funcs.FillTrapezoid( card->driver_data,
1756                                                     card->device_data, &trap );
1757                     if (!hw)
1758                          break;
1759                }
1760 
1761           }
1762 
1763           dfb_gfxcard_state_release( state );
1764      }
1765      if (!hw && i < num) {
1766           /* otherwise use two triangles */
1767 
1768           if ( dfb_gfxcard_state_check( state, DFXL_FILLTRIANGLE ) &&
1769                dfb_gfxcard_state_acquire( state, DFXL_FILLTRIANGLE ))
1770           {
1771                for (; i < num; i++) {
1772                     bool tri1_failed = true;
1773                     bool tri2_failed = true;
1774 
1775                     DFBTriangle tri1 = { traps[i].x1,                   traps[i].y1,
1776                                          traps[i].x1 + traps[i].w1 - 1, traps[i].y1,
1777                                          traps[i].x2,                   traps[i].y2 };
1778 
1779                     DFBTriangle tri2 = { traps[i].x1 + traps[i].w1 - 1, traps[i].y1,
1780                                          traps[i].x2,                   traps[i].y2,
1781                                          traps[i].x2 + traps[i].w2 - 1, traps[i].y2 };
1782 
1783                     if (D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) ||
1784                         D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLTRIANGLE ) ||
1785                         (state->render_options & DSRO_MATRIX))
1786                     {
1787                          tri1_failed = !card->funcs.FillTriangle( card->driver_data,
1788                                                                   card->device_data, &tri1 );
1789 
1790                          tri2_failed = !card->funcs.FillTriangle( card->driver_data,
1791                                                                   card->device_data, &tri2 );
1792                     }
1793 
1794                     if (tri1_failed || tri2_failed) {
1795                          dfb_gfxcard_state_release( state );
1796 
1797                          if (gAcquire( state, DFXL_FILLTRIANGLE )) {
1798 
1799                               if (state->render_options & DSRO_MATRIX) {
1800                                    /* transform first triangle completely */
1801                                    if (tri1_failed || tri2_failed) {
1802 
1803                                         DFB_TRANSFORM(tri1.x1, tri1.y1, state->matrix, state->affine_matrix);
1804                                         DFB_TRANSFORM(tri1.x2, tri1.y2, state->matrix, state->affine_matrix);
1805                                         DFB_TRANSFORM(tri1.x3, tri1.y3, state->matrix, state->affine_matrix);
1806                                    }
1807 
1808                                    if (tri2_failed) {
1809                                         /* transform last coordinate of first triangle,
1810                                            and assing first ones from first */
1811                                         DFB_TRANSFORM(tri2.x3, tri2.y3, state->matrix, state->affine_matrix);
1812                                         tri2.x1 = tri1.x2;
1813                                         tri2.y1 = tri1.y2;
1814                                         tri2.x2 = tri1.x3;
1815                                         tri2.x2 = tri1.y3;
1816                                    }
1817 
1818                                    /* sort triangles (matrix could have rotated them */
1819                                    dfb_sort_triangle( &tri1 );
1820                                    dfb_sort_triangle( &tri2 );
1821                               }
1822 
1823                               if (tri1_failed && (tri1.y3 - tri1.y1 > 0))
1824                                    fill_tri( &tri1, state, false );
1825 
1826                               if (tri2_failed && (tri2.y3 - tri2.y1 > 0))
1827                                    fill_tri( &tri2, state, false );
1828 
1829                               gRelease( state );
1830                          }
1831                          dfb_gfxcard_state_acquire( state, DFXL_FILLTRIANGLE );
1832                     }
1833                }
1834                dfb_gfxcard_state_release( state );
1835           }
1836 
1837           else if (gAcquire( state, DFXL_FILLTRIANGLE )) {
1838                for (; i < num; i++) {
1839                     DFBTrapezoid trap = traps[i];
1840                     dfb_sort_trapezoid(&trap);
1841 
1842                     if (state->render_options & DSRO_MATRIX) {
1843                          /* split into triangles, for easier rotation */
1844                          DFBTriangle tri1 = { trap.x1,                   traps[i].y1,
1845                                               trap.x1 + traps[i].w1 - 1, traps[i].y1,
1846                                               trap.x2,                   traps[i].y2 };
1847 
1848                          DFBTriangle tri2 = { trap.x1 + traps[i].w1 - 1, traps[i].y1,
1849                                               trap.x2,                   traps[i].y2,
1850                                               trap.x2 + traps[i].w2 - 1, traps[i].y2 };
1851 
1852 
1853                          /* transform first triangle completely */
1854                          DFB_TRANSFORM(tri1.x1, tri1.y1, state->matrix, state->affine_matrix);
1855                          DFB_TRANSFORM(tri1.x2, tri1.y2, state->matrix, state->affine_matrix);
1856                          DFB_TRANSFORM(tri1.x3, tri1.y3, state->matrix, state->affine_matrix);
1857 
1858                          /* transform last coordinate of second triangle, and assign first ones from first */
1859                          tri2.x1 = tri1.x2;
1860                          tri2.y1 = tri1.y2;
1861                          tri2.x2 = tri1.x3;
1862                          tri2.y2 = tri1.y3;
1863                          DFB_TRANSFORM(tri2.x3, tri2.y3, state->matrix, state->affine_matrix);
1864 
1865                          /* sort triangles (matrix could have rotated them */
1866                          dfb_sort_triangle( &tri1 );
1867                          dfb_sort_triangle( &tri2 );
1868 
1869                          if (tri1.y3 - tri1.y1 > 0)
1870                               fill_tri( &tri1, state, false );
1871                          if (tri2.y3 - tri2.y1 > 0)
1872                               fill_tri( &tri2, state, false );
1873 
1874                     }
1875                     else
1876                          fill_trap( &trap, state, false );
1877                }
1878 
1879                gRelease( state );
1880           }
1881 
1882      }
1883      dfb_state_unlock( state );
1884 
1885 }
1886 
1887 
1888 D_UNUSED
1889 static void
DFBVertex_Transform(DFBVertex * v,unsigned int num,s32 matrix[9],bool affine)1890 DFBVertex_Transform( DFBVertex    *v,
1891                      unsigned int  num,
1892                      s32           matrix[9],
1893                      bool          affine )
1894 {
1895      unsigned int i;
1896 
1897      if (affine) {
1898           for (i=0; i<num; i++) {
1899                float _x, _y;
1900 
1901                _x = ((v[i].x) * matrix[0] + (v[i].y) * matrix[1] + matrix[2]) / 0x10000;
1902                _y = ((v[i].x) * matrix[3] + (v[i].y) * matrix[4] + matrix[5]) / 0x10000;
1903 
1904                v[i].x = _x;
1905                v[i].y = _y;
1906           }
1907      }
1908      else {
1909           for (i=0; i<num; i++) {
1910                float _x, _y, _w;
1911 
1912                _x = ((v[i].x) * matrix[0] + (v[i].y) * matrix[1] + matrix[2]);
1913                _y = ((v[i].x) * matrix[3] + (v[i].y) * matrix[4] + matrix[5]);
1914                _w = ((v[i].x) * matrix[6] + (v[i].y) * matrix[7] + matrix[8]);
1915                if (!_w) {
1916                     _x = (_x < 0) ? -0x7fffffff : 0x7fffffff;
1917                     _y = (_y < 0) ? -0x7fffffff : 0x7fffffff;
1918                }
1919                else {
1920                     _x /= _w;
1921                     _y /= _w;
1922                }
1923 
1924                v[i].x = _x;
1925                v[i].y = _y;
1926           }
1927      }
1928 }
1929 
1930 static void
GenefxVertexAffine_Transform(GenefxVertexAffine * v,unsigned int num,s32 matrix[9],bool affine)1931 GenefxVertexAffine_Transform( GenefxVertexAffine *v,
1932                               unsigned int        num,
1933                               s32                 matrix[9],
1934                               bool                affine )
1935 {
1936      unsigned int i;
1937 
1938      if (affine) {
1939           for (i=0; i<num; i++) {
1940                int _x, _y;
1941 
1942                _x = ((v[i].x) * matrix[0] + (v[i].y) * matrix[1] + matrix[2]) / 0x10000;
1943                _y = ((v[i].x) * matrix[3] + (v[i].y) * matrix[4] + matrix[5]) / 0x10000;
1944 
1945                v[i].x = _x;
1946                v[i].y = _y;
1947           }
1948      }
1949      else {
1950           for (i=0; i<num; i++) {
1951                int _x, _y, _w;
1952 
1953                _x = ((v[i].x) * matrix[0] + (v[i].y) * matrix[1] + matrix[2]);
1954                _y = ((v[i].x) * matrix[3] + (v[i].y) * matrix[4] + matrix[5]);
1955                _w = ((v[i].x) * matrix[6] + (v[i].y) * matrix[7] + matrix[8]);
1956                if (!_w) {
1957                     _x = (_x < 0) ? -0x7fffffff : 0x7fffffff;
1958                     _y = (_y < 0) ? -0x7fffffff : 0x7fffffff;
1959                }
1960                else {
1961                     _x /= _w;
1962                     _y /= _w;
1963                }
1964 
1965                v[i].x = _x;
1966                v[i].y = _y;
1967           }
1968      }
1969 }
1970 
1971 
dfb_gfxcard_blit(DFBRectangle * rect,int dx,int dy,CardState * state)1972 void dfb_gfxcard_blit( DFBRectangle *rect, int dx, int dy, CardState *state )
1973 {
1974      bool         hw    = false;
1975      DFBRectangle drect = { dx, dy, rect->w, rect->h };
1976 
1977      DFBSurfaceBlittingFlags blittingflags = state->blittingflags;
1978      dfb_simplify_blittingflags( &blittingflags );
1979 
1980      if (blittingflags & DSBLIT_ROTATE90)
1981           D_UTIL_SWAP( drect.w, drect.h );
1982 
1983      D_DEBUG_AT( Core_GraphicsOps, "%s( %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d, %p )\n",
1984                  __FUNCTION__, DFB_RECTANGLE_VALS(rect), DFB_RECTANGLE_VALS(&drect), state );
1985 
1986      D_ASSERT( card != NULL );
1987      D_ASSERT( card->shared != NULL );
1988      D_MAGIC_ASSERT( state, CardState );
1989      D_ASSERT( state->source != NULL );
1990      D_ASSERT( rect != NULL );
1991      D_ASSERT( rect->x >= 0 );
1992      D_ASSERT( rect->y >= 0 );
1993      D_ASSERT( rect->x < state->source->config.size.w );
1994      D_ASSERT( rect->y < state->source->config.size.h );
1995      D_ASSERT( rect->x + rect->w - 1 < state->source->config.size.w );
1996      D_ASSERT( rect->y + rect->h - 1 < state->source->config.size.h );
1997 
1998      /* The state is locked during graphics operations. */
1999      dfb_state_lock( state );
2000 
2001      /* Signal beginning of sequence of operations if not already done. */
2002      dfb_state_start_drawing( state, card );
2003 
2004      if (!(state->render_options & DSRO_MATRIX) &&
2005          !dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y ))
2006      {
2007           /* no work at all */
2008           dfb_state_unlock( state );
2009           return;
2010      }
2011 
2012      if (dfb_gfxcard_state_check( state, DFXL_BLIT ) &&
2013          dfb_gfxcard_state_acquire( state, DFXL_BLIT ))
2014      {
2015           if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
2016               !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT ))
2017                dfb_clip_blit_flipped_rotated( &state->clip, rect, &drect, blittingflags );
2018 
2019           hw = card->funcs.Blit( card->driver_data, card->device_data, rect, drect.x, drect.y );
2020 
2021           dfb_gfxcard_state_release( state );
2022      }
2023 
2024      if (!hw) {
2025           /* Use software fallback. */
2026           if (!(state->render_options & DSRO_MATRIX)) {
2027                if (gAcquire( state, DFXL_BLIT )) {
2028                     dfb_clip_blit_flipped_rotated( &state->clip, rect, &drect, blittingflags );
2029 
2030                     gBlit( state, rect, drect.x, drect.y );
2031 
2032                     gRelease( state );
2033                }
2034           }
2035           else if (state->matrix[0] == 0x10000 && state->matrix[1] == 0 &&
2036                    state->matrix[3] == 0       && state->matrix[4] == 0x10000)
2037           {
2038                state->render_options &= ~DSRO_MATRIX;
2039                state->modified       |= SMF_RENDER_OPTIONS;
2040 
2041                dfb_gfxcard_blit( rect,
2042                                  dx + ((state->matrix[2] + 0x8000) >> 16),
2043                                  dy + ((state->matrix[5] + 0x8000) >> 16), state );
2044 
2045                state->render_options |= DSRO_MATRIX;
2046                state->modified       |= SMF_RENDER_OPTIONS;
2047           }
2048           else {
2049                if (state->matrix[0] < 0  || state->matrix[1] != 0 ||
2050                    state->matrix[3] != 0 || state->matrix[4] < 0  ||
2051                    state->matrix[6] != 0 || state->matrix[7] != 0)
2052                {
2053                     if (gAcquire( state, DFXL_TEXTRIANGLES )) {
2054                          GenefxVertexAffine v[4];
2055 
2056                          v[0].x = dx;
2057                          v[0].y = dy;
2058                          v[0].s = rect->x * 0x10000;
2059                          v[0].t = rect->y * 0x10000;
2060 
2061                          v[1].x = dx + rect->w - 1;
2062                          v[1].y = dy;
2063                          v[1].s = (rect->x + rect->w - 1) * 0x10000;
2064                          v[1].t = v[0].t;
2065 
2066                          v[2].x = dx + rect->w - 1;
2067                          v[2].y = dy + rect->h - 1;
2068                          v[2].s = v[1].s;
2069                          v[2].t = (rect->y + rect->h - 1) * 0x10000;
2070 
2071                          v[3].x = dx;
2072                          v[3].y = dy + rect->h - 1;
2073                          v[3].s = v[0].s;
2074                          v[3].t = v[2].t;
2075 
2076                          GenefxVertexAffine_Transform( v, 4, state->matrix, state->affine_matrix );
2077 
2078                          Genefx_TextureTrianglesAffine( state, v, 4, DTTF_FAN, &state->clip );
2079 
2080                          gRelease( state );
2081                     }
2082                }
2083                else if (gAcquire( state, DFXL_STRETCHBLIT )) {
2084                     DFBRectangle drect;
2085                     int          x1, y1, x2, y2;
2086 
2087                     x1 = dx;         y1 = dy;
2088                     x2 = dx+rect->w; y2 = dy+rect->h;
2089                     DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix);
2090                     DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix);
2091 
2092                     drect = (DFBRectangle) { x1, y1, x2-x1, y2-y1 };
2093                     if (dfb_clip_blit_precheck( &state->clip,
2094                                                 drect.w, drect.h, drect.x, drect.y ))
2095                          gStretchBlit( state, rect, &drect );
2096 
2097                     gRelease( state );
2098                }
2099           }
2100      }
2101 
2102      dfb_state_unlock( state );
2103 }
2104 
dfb_gfxcard_batchblit(DFBRectangle * rects,DFBPoint * points,int num,CardState * state)2105 void dfb_gfxcard_batchblit( DFBRectangle *rects, DFBPoint *points,
2106                             int num, CardState *state )
2107 {
2108      unsigned int i = 0;
2109 
2110      DFBSurfaceBlittingFlags blittingflags = state->blittingflags;
2111      dfb_simplify_blittingflags( &blittingflags );
2112 
2113      D_DEBUG_AT( Core_GraphicsOps, "%s( %p, %p [%d], %p )\n", __FUNCTION__, rects, points, num, state );
2114 
2115      D_ASSERT( card != NULL );
2116      D_ASSERT( card->shared != NULL );
2117      D_MAGIC_ASSERT( state, CardState );
2118      D_ASSERT( rects != NULL );
2119      D_ASSERT( points != NULL );
2120      D_ASSERT( num > 0 );
2121 
2122      /* The state is locked during graphics operations. */
2123      dfb_state_lock( state );
2124 
2125      /* Signal beginning of sequence of operations if not already done. */
2126      dfb_state_start_drawing( state, card );
2127 
2128      if (dfb_gfxcard_state_check( state, DFXL_BLIT ) &&
2129          dfb_gfxcard_state_acquire( state, DFXL_BLIT ))
2130      {
2131           for (; i<num; i++) {
2132                DFBRectangle drect = { points[i].x, points[i].y, rects[i].w, rects[i].h };
2133 
2134                if (blittingflags & DSBLIT_ROTATE90)
2135                     D_UTIL_SWAP( drect.w, drect.h );
2136 
2137                if ((state->render_options & DSRO_MATRIX) ||
2138                    dfb_clip_blit_precheck( &state->clip,
2139                                            drect.w, drect.h,
2140                                            drect.x, drect.y ))
2141                {
2142                     DFBRectangle srect = rects[i];
2143 
2144                     if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
2145                         !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT ))
2146                          dfb_clip_blit_flipped_rotated( &state->clip, &srect, &drect, blittingflags );
2147 
2148                     if (!card->funcs.Blit( card->driver_data, card->device_data,
2149                                            &srect, drect.x, drect.y ))
2150                          break;
2151                }
2152           }
2153 
2154           dfb_gfxcard_state_release( state );
2155      }
2156 
2157      if (i < num) {
2158           if (state->render_options & DSRO_MATRIX) {
2159                if (state->matrix[0] < 0  || state->matrix[1] != 0 ||
2160                    state->matrix[3] != 0 || state->matrix[4] < 0  ||
2161                    state->matrix[6] != 0 || state->matrix[7] != 0)
2162                {
2163                     if (gAcquire( state, DFXL_TEXTRIANGLES )) {
2164                          for (; i<num; i++) {
2165                               GenefxVertexAffine v[4];
2166 
2167                               v[0].x = points[i].x;
2168                               v[0].y = points[i].y;
2169                               v[0].s = rects[i].x * 0x10000;
2170                               v[0].t = rects[i].y * 0x10000;
2171 
2172                               v[1].x = points[i].x + rects[i].w - 1;
2173                               v[1].y = points[i].y;
2174                               v[1].s = (rects[i].x + rects[i].w - 1) * 0x10000;
2175                               v[1].t = v[0].t;
2176 
2177                               v[2].x = points[i].x + rects[i].w - 1;
2178                               v[2].y = points[i].y + rects[i].h - 1;
2179                               v[2].s = v[1].s;
2180                               v[2].t = (rects[i].y + rects[i].h - 1) * 0x10000;
2181 
2182                               v[3].x = points[i].x;
2183                               v[3].y = points[i].y + rects[i].h - 1;
2184                               v[3].s = v[0].s;
2185                               v[3].t = v[2].t;
2186 
2187                               GenefxVertexAffine_Transform( v, 4, state->matrix, state->affine_matrix );
2188 
2189                               Genefx_TextureTrianglesAffine( state, v, 4, DTTF_FAN, &state->clip );
2190                          }
2191 
2192                          gRelease( state );
2193                     }
2194                }
2195                else if (gAcquire( state, DFXL_STRETCHBLIT )) {
2196                     for (; i<num; i++) {
2197                          DFBRectangle drect;
2198                          int          x1, y1, x2, y2;
2199 
2200                          x1 = points[i].x;   y1 = points[i].y;
2201                          x2 = x1+rects[i].w; y2 = y1+rects[i].h;
2202                          DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix);
2203                          DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix);
2204 
2205                          drect = (DFBRectangle) { x1, y1, x2-x1, y2-y1 };
2206                          if (dfb_clip_blit_precheck( &state->clip,
2207                                                      drect.w, drect.h, drect.x, drect.y ))
2208                               gStretchBlit( state, &rects[i], &drect );
2209                     }
2210 
2211                     gRelease( state );
2212                }
2213           }
2214           else {
2215                if (gAcquire( state, DFXL_BLIT )) {
2216                     for (; i<num; i++) {
2217                          DFBRectangle drect = { points[i].x, points[i].y, rects[i].w, rects[i].h };
2218 
2219                          if (blittingflags & DSBLIT_ROTATE90)
2220                               D_UTIL_SWAP( drect.w, drect.h );
2221 
2222                          if (dfb_clip_blit_precheck( &state->clip,
2223                                                      drect.w, drect.h,
2224                                                      drect.x, drect.y ))
2225                          {
2226                               DFBRectangle srect = rects[i];
2227 
2228                               dfb_clip_blit_flipped_rotated( &state->clip, &srect, &drect, blittingflags );
2229                               gBlit( state, &srect, drect.x, drect.y );
2230                          }
2231                     }
2232 
2233                     gRelease( state );
2234                }
2235           }
2236      }
2237 
2238      dfb_state_unlock( state );
2239 }
2240 
dfb_gfxcard_batchblit2(DFBRectangle * rects,DFBPoint * points,DFBPoint * points2,int num,CardState * state)2241 void dfb_gfxcard_batchblit2( DFBRectangle *rects, DFBPoint *points, DFBPoint *points2,
2242                              int num, CardState *state )
2243 {
2244      int i = 0;
2245 
2246      D_DEBUG_AT( Core_GraphicsOps, "%s( %p, %p, %p [%d], %p )\n", __FUNCTION__, rects, points, points2, num, state );
2247 
2248      D_ASSERT( card != NULL );
2249      D_ASSERT( card->shared != NULL );
2250      D_MAGIC_ASSERT( state, CardState );
2251      D_ASSERT( rects != NULL );
2252      D_ASSERT( points != NULL );
2253      D_ASSERT( points2 != NULL );
2254      D_ASSERT( num > 0 );
2255 
2256      /* The state is locked during graphics operations. */
2257      dfb_state_lock( state );
2258 
2259      /* Signal beginning of sequence of operations if not already done. */
2260      dfb_state_start_drawing( state, card );
2261 
2262      if (dfb_gfxcard_state_check( state, DFXL_BLIT2 ) &&
2263          dfb_gfxcard_state_acquire( state, DFXL_BLIT2 ))
2264      {
2265           for (; i<num; i++) {
2266                if ((state->render_options & DSRO_MATRIX) ||
2267                    dfb_clip_blit_precheck( &state->clip,
2268                                            rects[i].w, rects[i].h,
2269                                            points[i].x, points[i].y ))
2270                {
2271                     int dx = points[i].x;
2272                     int dy = points[i].y;
2273 
2274                     if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
2275                         !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT2 ))
2276                     {
2277                          dfb_clip_blit( &state->clip, &rects[i], &dx, &dy );
2278 
2279                          points2[i].x += dx - points[i].x;
2280                          points2[i].y += dy - points[i].y;
2281                     }
2282 
2283                     if (!card->funcs.Blit2( card->driver_data, card->device_data,
2284                                             &rects[i], dx, dy, points2[i].x, points2[i].y ))
2285                          break;
2286                }
2287           }
2288 
2289           dfb_gfxcard_state_release( state );
2290      }
2291 
2292      if (i < num) {
2293           D_UNIMPLEMENTED();
2294 
2295           for (; i<num; i++) {
2296                D_DEBUG_AT( Core_GraphicsOps, "  -> rects[%d]    %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS( &rects[i] ) );
2297                D_DEBUG_AT( Core_GraphicsOps, "  -> points[%d]   %4d,%4d\n", i, points[i].x, points[i].y );
2298                D_DEBUG_AT( Core_GraphicsOps, "  -> points2[%d]  %4d,%4d\n", i, points2[i].x, points2[i].y );
2299 
2300                if ((state->render_options & DSRO_MATRIX) ||
2301                    dfb_clip_blit_precheck( &state->clip,
2302                                            rects[i].w, rects[i].h,
2303                                            points[i].x, points[i].y ))
2304                {
2305                     int dx = points[i].x;
2306                     int dy = points[i].y;
2307 
2308                     dfb_clip_blit( &state->clip, &rects[i], &dx, &dy );
2309 
2310                     points2[i].x += dx - points[i].x;
2311                     points2[i].y += dy - points[i].y;
2312 
2313                     D_DEBUG_AT( Core_GraphicsOps, "  => rects[%d]    %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS( &rects[i] ) );
2314                     D_DEBUG_AT( Core_GraphicsOps, "  => points[%d]   %4d,%4d\n", i, dx, dy );
2315                     D_DEBUG_AT( Core_GraphicsOps, "  => points2[%d]  %4d,%4d\n", i, points2[i].x, points2[i].y );
2316                }
2317           }
2318      }
2319 
2320      dfb_state_unlock( state );
2321 }
2322 
dfb_gfxcard_tileblit(DFBRectangle * rect,int dx1,int dy1,int dx2,int dy2,CardState * state)2323 void dfb_gfxcard_tileblit( DFBRectangle *rect, int dx1, int dy1, int dx2, int dy2,
2324                            CardState *state )
2325 {
2326      int           x, y;
2327      int           odx;
2328      DFBRectangle  srect;
2329      DFBRegion    *clip;
2330 
2331      D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %d,%d, %p )\n", __FUNCTION__, dx1, dy1, dx2, dy2, state );
2332 
2333      D_ASSERT( card != NULL );
2334      D_ASSERT( card->shared != NULL );
2335      D_MAGIC_ASSERT( state, CardState );
2336      D_ASSERT( rect != NULL );
2337 
2338      /* If called with an invalid rectangle, the algorithm goes into an
2339         infinite loop. This should never happen but it's safer to check. */
2340      D_ASSERT( rect->w >= 1 );
2341      D_ASSERT( rect->h >= 1 );
2342 
2343      /* The state is locked during graphics operations. */
2344      dfb_state_lock( state );
2345 
2346      /* Signal beginning of sequence of operations if not already done. */
2347      dfb_state_start_drawing( state, card );
2348 
2349      clip = &state->clip;
2350 
2351      /* Check if anything is drawn at all. */
2352      if (!(state->render_options & DSRO_MATRIX) &&
2353          !dfb_clip_blit_precheck( clip, dx2-dx1+1, dy2-dy1+1, dx1, dy1 )) {
2354           dfb_state_unlock( state );
2355           return;
2356      }
2357 
2358      /* Remove clipped tiles. */
2359      if (dx1 < clip->x1) {
2360           int outer = clip->x1 - dx1;
2361 
2362           dx1 += outer - (outer % rect->w);
2363      }
2364 
2365      if (dy1 < clip->y1) {
2366           int outer = clip->y1 - dy1;
2367 
2368           dy1 += outer - (outer % rect->h);
2369      }
2370 
2371      if (dx2 > clip->x2) {
2372           int outer = clip->x2 - dx2;
2373 
2374           dx2 -= outer - (outer % rect->w);
2375      }
2376 
2377      if (dy2 > clip->y2) {
2378           int outer = clip->y2 - dy2;
2379 
2380           dy2 -= outer - (outer % rect->h);
2381      }
2382 
2383      odx = dx1;
2384 
2385      if (dfb_gfxcard_state_check( state, DFXL_BLIT ) &&
2386          dfb_gfxcard_state_acquire( state, DFXL_BLIT )) {
2387           bool hw = true;
2388 
2389           for (; dy1 < dy2; dy1 += rect->h) {
2390                for (; dx1 < dx2; dx1 += rect->w) {
2391 
2392                     if (!dfb_clip_blit_precheck( clip, rect->w, rect->h, dx1, dy1 ))
2393                          continue;
2394 
2395                     x = dx1;
2396                     y = dy1;
2397                     srect = *rect;
2398 
2399                     if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
2400                         !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT ))
2401                          dfb_clip_blit( clip, &srect, &x, &y );
2402 
2403                     hw = card->funcs.Blit( card->driver_data,
2404                                            card->device_data, &srect, x, y );
2405                     if (!hw)
2406                          break;
2407                }
2408                if (!hw)
2409                     break;
2410                dx1 = odx;
2411           }
2412 
2413           dfb_gfxcard_state_release( state );
2414      }
2415 
2416      if (dy1 < dy2) {
2417           if (state->render_options & DSRO_MATRIX) {
2418                if (state->matrix[0] < 0  || state->matrix[1] != 0 ||
2419                    state->matrix[3] != 0 || state->matrix[4] < 0  ||
2420                    state->matrix[6] != 0 || state->matrix[7] != 0)
2421                {
2422                     if (gAcquire( state, DFXL_TEXTRIANGLES )) {
2423                          /* Build mesh */
2424                          for (; dy1 < dy2; dy1 += rect->h) {
2425                               for (; dx1 < dx2; dx1 += rect->w) {
2426                                    GenefxVertexAffine v[4];
2427 
2428                                    v[0].x = dx1;
2429                                    v[0].y = dy1;
2430                                    v[0].s = rect->x * 0x10000;
2431                                    v[0].t = rect->y * 0x10000;
2432 
2433                                    v[1].x = dx1 + rect->w - 1;
2434                                    v[1].y = dy1;
2435                                    v[1].s = (rect->x + rect->w - 1) * 0x10000;
2436                                    v[1].t = v[0].t;
2437 
2438                                    v[2].x = dx1 + rect->w - 1;
2439                                    v[2].y = dy1 + rect->h - 1;
2440                                    v[2].s = v[1].s;
2441                                    v[2].t = (rect->y + rect->h - 1) * 0x10000;
2442 
2443                                    v[3].x = dx1;
2444                                    v[3].y = dy1 + rect->h - 1;
2445                                    v[3].s = v[0].s;
2446                                    v[3].t = v[2].t;
2447 
2448                                    GenefxVertexAffine_Transform( v, 4, state->matrix, state->affine_matrix );
2449 
2450                                    Genefx_TextureTrianglesAffine( state, v, 4, DTTF_FAN, &state->clip );
2451                               }
2452 
2453                               dx1 = odx;
2454                          }
2455 
2456                          gRelease( state );
2457                     }
2458                }
2459                else if (gAcquire( state, DFXL_STRETCHBLIT )) {
2460                     for (; dy1 < dy2; dy1 += rect->h) {
2461                          for (; dx1 < dx2; dx1 += rect->w) {
2462                               DFBRectangle drect;
2463                               int          x1, y1, x2, y2;
2464 
2465                               x1 = dx1;         y1 = dy1;
2466                               x2 = dx1+rect->w; y2 = dy1+rect->h;
2467                               DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix);
2468                               DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix);
2469 
2470                               drect = (DFBRectangle) { x1, y1, x2-x1, y2-y1 };
2471                               if (dfb_clip_blit_precheck( &state->clip,
2472                                                           drect.w, drect.h, drect.x, drect.y ))
2473                                    gStretchBlit( state, rect, &drect );
2474                          }
2475                          dx1 = odx;
2476                     }
2477 
2478                     gRelease( state );
2479                }
2480           }
2481           else {
2482                if (gAcquire( state, DFXL_BLIT )) {
2483                     for (; dy1 < dy2; dy1 += rect->h) {
2484                          for (; dx1 < dx2; dx1 += rect->w) {
2485 
2486                               if (!dfb_clip_blit_precheck( clip, rect->w, rect->h, dx1, dy1 ))
2487                                    continue;
2488 
2489                               x = dx1;
2490                               y = dy1;
2491                               srect = *rect;
2492 
2493                               dfb_clip_blit( clip, &srect, &x, &y );
2494 
2495                               gBlit( state, &srect, x, y );
2496                          }
2497                          dx1 = odx;
2498                     }
2499 
2500                     gRelease( state );
2501                }
2502           }
2503      }
2504 
2505      dfb_state_unlock( state );
2506 }
2507 
dfb_gfxcard_stretchblit(DFBRectangle * srect,DFBRectangle * drect,CardState * state)2508 void dfb_gfxcard_stretchblit( DFBRectangle *srect, DFBRectangle *drect,
2509                               CardState *state )
2510 {
2511      bool hw = false;
2512 
2513      DFBSurfaceBlittingFlags blittingflags = state->blittingflags;
2514      dfb_simplify_blittingflags( &blittingflags );
2515 
2516      D_ASSERT( card != NULL );
2517      D_ASSERT( card->shared != NULL );
2518      D_MAGIC_ASSERT( state, CardState );
2519      D_ASSERT( srect != NULL );
2520      D_ASSERT( drect != NULL );
2521 
2522      D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %dx%d -> %d,%d - %dx%d, %p )\n",
2523                  __FUNCTION__, DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect), state );
2524 
2525      if (state->blittingflags & DSBLIT_ROTATE90) {
2526           if (srect->w == drect->h && srect->h == drect->w) {
2527                dfb_gfxcard_blit( srect, drect->x, drect->y, state );
2528                return;
2529           }
2530      }
2531      else {
2532           if (srect->w == drect->w && srect->h == drect->h) {
2533                dfb_gfxcard_blit( srect, drect->x, drect->y, state );
2534                return;
2535           }
2536      }
2537 
2538      /* The state is locked during graphics operations. */
2539      dfb_state_lock( state );
2540 
2541      /* Signal beginning of sequence of operations if not already done. */
2542      dfb_state_start_drawing( state, card );
2543 
2544      if (!(state->render_options & DSRO_MATRIX) &&
2545          !dfb_clip_blit_precheck( &state->clip, drect->w, drect->h,
2546                                   drect->x, drect->y ))
2547      {
2548           dfb_state_unlock( state );
2549           return;
2550      }
2551 
2552      if (dfb_gfxcard_state_check( state, DFXL_STRETCHBLIT ) &&
2553          dfb_gfxcard_state_acquire( state, DFXL_STRETCHBLIT ))
2554      {
2555           if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
2556               !D_FLAGS_IS_SET( card->caps.clip, DFXL_STRETCHBLIT ))
2557                dfb_clip_stretchblit( &state->clip, srect, drect );
2558 
2559           hw = card->funcs.StretchBlit( card->driver_data, card->device_data, srect, drect );
2560 
2561           dfb_gfxcard_state_release( state );
2562      }
2563 
2564      if (!hw) {
2565           if (state->render_options & DSRO_MATRIX) {
2566                int x1, y1, x2, y2;
2567 
2568                if (state->matrix[0] < 0  || state->matrix[1] != 0 ||
2569                    state->matrix[3] != 0 || state->matrix[4] < 0  ||
2570                    state->matrix[6] != 0 || state->matrix[7] != 0)
2571                {
2572                     if (gAcquire( state, DFXL_TEXTRIANGLES )) {
2573                          GenefxVertexAffine v[4];
2574 
2575                          v[0].x = drect->x;
2576                          v[0].y = drect->y;
2577                          v[0].s = srect->x * 0x10000;
2578                          v[0].t = srect->y * 0x10000;
2579 
2580                          v[1].x = drect->x + drect->w - 1;
2581                          v[1].y = drect->y;
2582                          v[1].s = (srect->x + srect->w - 1) * 0x10000;
2583                          v[1].t = v[0].t;
2584 
2585                          v[2].x = drect->x + drect->w - 1;
2586                          v[2].y = drect->y + drect->h - 1;
2587                          v[2].s = v[1].s;
2588                          v[2].t = (srect->y + srect->h - 1) * 0x10000;
2589 
2590                          v[3].x = drect->x;
2591                          v[3].y = drect->y + drect->h - 1;
2592                          v[3].s = v[0].s;
2593                          v[3].t = v[2].t;
2594 
2595                          GenefxVertexAffine_Transform( v, 4, state->matrix, state->affine_matrix );
2596 
2597                          Genefx_TextureTrianglesAffine( state, v, 4, DTTF_FAN, &state->clip );
2598 
2599                          gRelease( state );
2600                     }
2601 
2602                     dfb_state_unlock( state );
2603                     return;
2604                }
2605 
2606                x1 = drect->x;    y1 = drect->y;
2607                x2 = x1+drect->w; y2 = y1+drect->h;
2608                DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix);
2609                DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix);
2610                drect->x = x1;    drect->y = y1;
2611                drect->w = x2-x1; drect->h = y2-y1;
2612 
2613                if (!dfb_clip_blit_precheck( &state->clip,
2614                                             drect->w, drect->h, drect->x, drect->y )) {
2615                     dfb_state_unlock( state );
2616                     return;
2617                }
2618           }
2619 
2620           if (gAcquire( state, DFXL_STRETCHBLIT )) {
2621                /* Clipping is performed in the following function. */
2622                gStretchBlit( state, srect, drect );
2623                gRelease( state );
2624           }
2625      }
2626 
2627      dfb_state_unlock( state );
2628 }
2629 
dfb_gfxcard_texture_triangles(DFBVertex * vertices,int num,DFBTriangleFormation formation,CardState * state)2630 void dfb_gfxcard_texture_triangles( DFBVertex *vertices, int num,
2631                                     DFBTriangleFormation formation,
2632                                     CardState *state )
2633 {
2634      bool hw = false;
2635 
2636      D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %s, %p )\n", __FUNCTION__, vertices, num,
2637                  (formation == DTTF_LIST)  ? "LIST"  :
2638                  (formation == DTTF_STRIP) ? "STRIP" :
2639                  (formation == DTTF_FAN)   ? "FAN"   : "unknown formation", state );
2640 
2641      D_ASSERT( card != NULL );
2642      D_ASSERT( card->shared != NULL );
2643      D_ASSERT( vertices != NULL );
2644      D_ASSERT( num >= 3 );
2645      D_MAGIC_ASSERT( state, CardState );
2646 
2647      /* The state is locked during graphics operations. */
2648      dfb_state_lock( state );
2649 
2650      /* Signal beginning of sequence of operations if not already done. */
2651      dfb_state_start_drawing( state, card );
2652 
2653      if ((D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) || D_FLAGS_IS_SET( card->caps.clip, DFXL_TEXTRIANGLES )) &&
2654          dfb_gfxcard_state_check( state, DFXL_TEXTRIANGLES ) &&
2655          dfb_gfxcard_state_acquire( state, DFXL_TEXTRIANGLES ))
2656      {
2657           hw = card->funcs.TextureTriangles( card->driver_data,
2658                                              card->device_data,
2659                                              vertices, num, formation );
2660 
2661           dfb_gfxcard_state_release( state );
2662      }
2663 
2664      if (!hw) {
2665           if (gAcquire( state, DFXL_TEXTRIANGLES )) {
2666                Genefx_TextureTriangles( state, vertices, num, formation, &state->clip );
2667                gRelease( state );
2668           }
2669      }
2670 
2671      dfb_state_unlock( state );
2672 }
2673 
2674 static void
font_state_prepare(CardState * state,CardState * backup,CoreFont * font,CoreSurface * surface)2675 font_state_prepare( CardState   *state,
2676                     CardState   *backup,
2677                     CoreFont    *font,
2678                     CoreSurface *surface )
2679 {
2680      if (state->blittingflags != DSBLIT_INDEX_TRANSLATION) {
2681           DFBSurfaceBlittingFlags flags = font->blittingflags;
2682 
2683           backup->blittingflags = state->blittingflags;
2684           backup->src_blend     = state->src_blend;
2685           backup->dst_blend     = state->dst_blend;
2686 
2687           /* additional blending? */
2688           if ((state->drawingflags & DSDRAW_BLEND) && (state->color.a != 0xff))
2689                flags |= DSBLIT_BLEND_COLORALPHA;
2690 
2691           if (state->drawingflags & DSDRAW_DST_COLORKEY)
2692                flags |= DSBLIT_DST_COLORKEY;
2693 
2694           if (state->drawingflags & DSDRAW_XOR)
2695                flags |= DSBLIT_XOR;
2696 
2697           if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {
2698                /* Porter/Duff SRC_OVER composition */
2699                if ((DFB_PIXELFORMAT_HAS_ALPHA( surface->config.format ) && (surface->config.caps & DSCAPS_PREMULTIPLIED))
2700                    ||
2701                    (font->surface_caps & DSCAPS_PREMULTIPLIED))
2702                {
2703                     if (font->surface_caps & DSCAPS_PREMULTIPLIED) {
2704                          if (flags & DSBLIT_BLEND_COLORALPHA)
2705                               flags |= DSBLIT_SRC_PREMULTCOLOR;
2706                     }
2707                     else
2708                          flags |= DSBLIT_SRC_PREMULTIPLY;
2709 
2710                     dfb_state_set_src_blend( state, DSBF_ONE );
2711                }
2712                else
2713                     dfb_state_set_src_blend( state, DSBF_SRCALPHA );
2714 
2715                dfb_state_set_dst_blend( state, DSBF_INVSRCALPHA );
2716           }
2717 
2718           dfb_state_set_blitting_flags( state, flags );
2719      }
2720      else {
2721           backup->blittingflags = 0;
2722           backup->src_blend     = 0;
2723           backup->dst_blend     = 0;
2724      }
2725 }
2726 
2727 static void
font_state_restore(CardState * state,CardState * backup)2728 font_state_restore( CardState *state,
2729                     CardState *backup )
2730 {
2731      if (state->blittingflags != DSBLIT_INDEX_TRANSLATION) {
2732           dfb_state_set_blitting_flags( state, backup->blittingflags );
2733           dfb_state_set_src_blend( state, backup->src_blend );
2734           dfb_state_set_dst_blend( state, backup->dst_blend );
2735      }
2736 }
2737 
2738 void
dfb_gfxcard_drawstring(const u8 * text,int bytes,DFBTextEncodingID encoding,int x,int y,CoreFont * font,unsigned int layers,CoreGraphicsStateClient * client)2739 dfb_gfxcard_drawstring( const u8 *text, int bytes,
2740                         DFBTextEncodingID encoding, int x, int y,
2741                         CoreFont *font, unsigned int layers, CoreGraphicsStateClient *client )
2742 {
2743      DFBResult     ret;
2744      unsigned int  prev = 0;
2745      unsigned int  indices[bytes];
2746      int           i, l, num;
2747      int           kern_x;
2748      int           kern_y;
2749      CoreSurface  *surface;
2750      CardState     state_backup;
2751      DFBPoint      points[50];
2752      DFBRectangle  rects[50];
2753      int           num_blits = 0;
2754      int           ox = x;
2755      int           oy = y;
2756      CardState    *state;
2757 
2758      if (encoding == DTEID_UTF8)
2759           D_DEBUG_AT( Core_GraphicsOps, "%s( '%s' [%d], %d,%d, %p, %p )\n",
2760                       __FUNCTION__, text, bytes, x, y, font, client );
2761      else
2762           D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %d, %d,%d, %p, %p )\n",
2763                       __FUNCTION__, text, bytes, encoding, x, y, font, client );
2764 
2765      D_ASSERT( card != NULL );
2766      D_ASSERT( card->shared != NULL );
2767      D_ASSERT( text != NULL );
2768      D_ASSERT( bytes > 0 );
2769      D_ASSERT( font != NULL );
2770 
2771      D_MAGIC_ASSERT( client, CoreGraphicsStateClient );
2772 
2773      state = client->state;
2774      D_MAGIC_ASSERT( state, CardState );
2775 
2776      surface = state->destination;
2777      D_MAGIC_ASSERT( surface, CoreSurface );
2778 
2779      /* simple prechecks */
2780      if (!(state->render_options & DSRO_MATRIX) &&
2781          (x > state->clip.x2 || y > state->clip.y2 ||
2782           y + font->height <= state->clip.y1)) {
2783           return;
2784      }
2785 
2786      /* Decode string to character indices. */
2787      ret = dfb_font_decode_text( font, encoding, text, bytes, indices, &num );
2788      if (ret)
2789           return;
2790 
2791      font_state_prepare( state, &state_backup, font, surface );
2792 
2793      dfb_font_lock( font );
2794 
2795      for (l=layers-1; l>=0; l--) {
2796           x = ox;
2797           y = oy;
2798 
2799           if (layers > 1)
2800                dfb_state_set_color( state, &state->colors[l] );
2801 
2802           /* blit glyphs */
2803           for (i=0; i<num; i++) {
2804                DFBResult      ret;
2805                CoreGlyphData *glyph;
2806                unsigned int   current = indices[i];
2807 
2808                ret = dfb_font_get_glyph_data( font, current, l, &glyph );
2809                if (ret) {
2810                     D_DEBUG_AT( Core_GraphicsOps, "  -> dfb_font_get_glyph_data() failed! [%s]\n", DirectFBErrorString( ret ) );
2811                     prev = current;
2812                     continue;
2813                }
2814 
2815                if (prev && font->GetKerning && font->GetKerning( font, prev, current, &kern_x, &kern_y) == DFB_OK) {
2816                     x += kern_x;
2817                     y += kern_y;
2818                }
2819 
2820                if (glyph->width) {
2821                     if (glyph->surface != state->source || num_blits == D_ARRAY_SIZE(rects)) {
2822                          if (num_blits) {
2823                               CoreGraphicsStateClient_Blit( client, rects, points, num_blits );
2824                               num_blits = 0;
2825                          }
2826 
2827                          if (glyph->surface != state->source)
2828                               dfb_state_set_source( state, glyph->surface );
2829                     }
2830 
2831                     points[num_blits] = (DFBPoint){ x + glyph->left, y + glyph->top };
2832                     rects[num_blits]  = (DFBRectangle){ glyph->start, 0, glyph->width, glyph->height };
2833 
2834                     num_blits++;
2835                }
2836 
2837                x   += glyph->xadvance;
2838                y   += glyph->yadvance;
2839                prev = current;
2840           }
2841 
2842           if (num_blits) {
2843                CoreGraphicsStateClient_Blit( client, rects, points, num_blits );
2844                num_blits = 0;
2845           }
2846      }
2847 
2848      dfb_font_unlock( font );
2849 
2850      font_state_restore( state, &state_backup );
2851 }
2852 
dfb_gfxcard_drawglyph(CoreGlyphData ** glyph,int x,int y,CoreFont * font,unsigned int layers,CoreGraphicsStateClient * client)2853 void dfb_gfxcard_drawglyph( CoreGlyphData **glyph, int x, int y,
2854                             CoreFont *font, unsigned int layers, CoreGraphicsStateClient *client )
2855 {
2856      int          l;
2857      CoreSurface *surface;
2858      CardState    state_backup;
2859      CardState   *state;
2860 
2861      D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d, %u, %p, %p )\n",
2862                  __FUNCTION__, x, y, layers, font, client );
2863 
2864      D_ASSERT( card != NULL );
2865      D_ASSERT( card->shared != NULL );
2866      D_ASSERT( font != NULL );
2867 
2868      D_MAGIC_ASSERT( client, CoreGraphicsStateClient );
2869 
2870      state = client->state;
2871      D_MAGIC_ASSERT( state, CardState );
2872 
2873      surface = state->destination;
2874      D_MAGIC_ASSERT( surface, CoreSurface );
2875 
2876      font_state_prepare( state, &state_backup, font, surface );
2877 
2878      for (l=layers-1; l>=0; l--) {
2879           if (layers > 1)
2880                dfb_state_set_color( state, &state->colors[l] );
2881 
2882           /* blit glyph */
2883           if (glyph[l]->width) {
2884                DFBRectangle rect  = { glyph[l]->start, 0, glyph[l]->width, glyph[l]->height };
2885                DFBPoint     point = { x + glyph[l]->left, y + glyph[l]->top };
2886 
2887                dfb_state_set_source( state, glyph[l]->surface );
2888 
2889                CoreGraphicsStateClient_Blit( client, &rect, &point, 1 );
2890           }
2891      }
2892 
2893      font_state_restore( state, &state_backup );
2894 }
2895 
dfb_gfxcard_drawstring_check_state(CoreFont * font,CardState * state)2896 bool dfb_gfxcard_drawstring_check_state( CoreFont *font, CardState *state )
2897 {
2898      int            i;
2899      bool           result;
2900      CoreSurface   *surface;
2901      CardState      state_backup;
2902      CoreGlyphData *data = NULL;
2903 
2904      D_ASSERT( card != NULL );
2905      D_ASSERT( card->shared != NULL );
2906      D_MAGIC_ASSERT( state, CardState );
2907      D_ASSERT( font != NULL );
2908 
2909      D_DEBUG_AT( Core_GfxState, "%s( %p, %p )\n", __FUNCTION__, font, state );
2910 
2911      surface = state->destination;
2912      D_MAGIC_ASSERT( surface, CoreSurface );
2913 
2914      dfb_font_lock( font );
2915 
2916      for (i=0; i<128; i++) {
2917           if (dfb_font_get_glyph_data (font, i, 0, &data) == DFB_OK)
2918                break;
2919      }
2920 
2921      if (!data) {
2922           D_DEBUG_AT( Core_GfxState, "  -> No font data!\n" );
2923           dfb_font_unlock( font );
2924           return false;
2925      }
2926 
2927      font_state_prepare( state, &state_backup, font, surface );
2928 
2929      /* set the source */
2930      dfb_state_set_source( state, data->surface );
2931 
2932      dfb_state_lock( state );
2933 
2934      /* check for blitting and report */
2935      result = dfb_gfxcard_state_check( state, DFXL_BLIT );
2936 
2937      dfb_state_unlock( state );
2938 
2939      dfb_font_unlock( font );
2940 
2941      font_state_restore( state, &state_backup );
2942 
2943      return result;
2944 }
2945 
dfb_gfxcard_sync(void)2946 DFBResult dfb_gfxcard_sync( void )
2947 {
2948      DFBResult ret;
2949 
2950      D_ASSUME( card != NULL );
2951 
2952      if (!card)
2953           return DFB_OK;
2954 
2955      ret = dfb_gfxcard_lock( GDLF_SYNC );
2956      if (ret)
2957           return ret;
2958 
2959      dfb_gfxcard_unlock();
2960 
2961      return DFB_OK;
2962 }
2963 
dfb_gfxcard_invalidate_state(void)2964 void dfb_gfxcard_invalidate_state( void )
2965 {
2966      D_ASSERT( card != NULL );
2967      D_ASSERT( card->shared != NULL );
2968 
2969      card->shared->state = NULL;
2970 }
2971 
dfb_gfxcard_wait_serial(const CoreGraphicsSerial * serial)2972 DFBResult dfb_gfxcard_wait_serial( const CoreGraphicsSerial *serial )
2973 {
2974      DFBResult ret;
2975 
2976      D_ASSERT( serial != NULL );
2977      D_ASSUME( card != NULL );
2978 
2979      if (!card || dfb_config->software_only)
2980           return DFB_OK;
2981 
2982      D_ASSERT( card->shared != NULL );
2983 
2984      ret = dfb_gfxcard_lock( GDLF_NONE );
2985      if (ret)
2986           return ret;
2987 
2988 /* FIXME_SC_2     if (card->funcs.WaitSerial)
2989           ret = card->funcs.WaitSerial( card->driver_data, card->device_data, serial );
2990      else*/ if (card->funcs.EngineSync)
2991           ret = card->funcs.EngineSync( card->driver_data, card->device_data );
2992 
2993      if (ret) {
2994           if (card->funcs.EngineReset)
2995                card->funcs.EngineReset( card->driver_data, card->device_data );
2996 
2997           card->shared->state = NULL;
2998      }
2999 
3000      dfb_gfxcard_unlock();
3001 
3002      return ret;
3003 }
3004 
dfb_gfxcard_flush_texture_cache(void)3005 void dfb_gfxcard_flush_texture_cache( void )
3006 {
3007      D_ASSUME( card != NULL );
3008 
3009      if (dfb_config->software_only)
3010           return;
3011 
3012      if (card && card->funcs.FlushTextureCache)
3013           card->funcs.FlushTextureCache( card->driver_data, card->device_data );
3014 }
3015 
dfb_gfxcard_flush_read_cache(void)3016 void dfb_gfxcard_flush_read_cache( void )
3017 {
3018      D_ASSUME( card != NULL );
3019 
3020      if (dfb_config->software_only)
3021           return;
3022 
3023      if (card && card->funcs.FlushReadCache)
3024           card->funcs.FlushReadCache( card->driver_data, card->device_data );
3025 }
3026 
dfb_gfxcard_after_set_var(void)3027 void dfb_gfxcard_after_set_var( void )
3028 {
3029      D_ASSUME( card != NULL );
3030 
3031      if (dfb_config->software_only)
3032           return;
3033 
3034      if (card && card->funcs.AfterSetVar)
3035           card->funcs.AfterSetVar( card->driver_data, card->device_data );
3036 }
3037 
dfb_gfxcard_surface_enter(CoreSurfaceBuffer * buffer,DFBSurfaceLockFlags flags)3038 void dfb_gfxcard_surface_enter( CoreSurfaceBuffer *buffer, DFBSurfaceLockFlags flags )
3039 {
3040      D_ASSUME( card != NULL );
3041 
3042      if (dfb_config->software_only)
3043           return;
3044 
3045      if (card && card->funcs.SurfaceEnter)
3046           card->funcs.SurfaceEnter( card->driver_data, card->device_data, buffer, flags );
3047 }
3048 
dfb_gfxcard_surface_leave(CoreSurfaceBuffer * buffer)3049 void dfb_gfxcard_surface_leave( CoreSurfaceBuffer *buffer )
3050 {
3051      D_ASSUME( card != NULL );
3052 
3053      if (dfb_config->software_only)
3054           return;
3055 
3056      if (card && card->funcs.SurfaceLeave)
3057           card->funcs.SurfaceLeave( card->driver_data, card->device_data, buffer );
3058 }
3059 
3060 DFBResult
dfb_gfxcard_adjust_heap_offset(int offset)3061 dfb_gfxcard_adjust_heap_offset( int offset )
3062 {
3063      D_ASSERT( card != NULL );
3064      D_ASSERT( card->shared != NULL );
3065 
3066 //FIXME_SMAN     return dfb_surfacemanager_adjust_heap_offset( card->shared->surface_manager, offset );
3067      return DFB_OK;
3068 }
3069 
3070 void
dfb_gfxcard_get_capabilities(CardCapabilities * ret_caps)3071 dfb_gfxcard_get_capabilities( CardCapabilities *ret_caps )
3072 {
3073      D_ASSERT( card != NULL );
3074 
3075      D_ASSERT( ret_caps != NULL );
3076 
3077      *ret_caps = card->caps;
3078 }
3079 
3080 void
dfb_gfxcard_get_device_info(GraphicsDeviceInfo * ret_info)3081 dfb_gfxcard_get_device_info( GraphicsDeviceInfo *ret_info )
3082 {
3083      D_ASSERT( card != NULL );
3084      D_ASSERT( card->shared != NULL );
3085 
3086      D_ASSERT( ret_info != NULL );
3087 
3088      *ret_info = card->shared->device_info;
3089 }
3090 
3091 void
dfb_gfxcard_get_driver_info(GraphicsDriverInfo * ret_info)3092 dfb_gfxcard_get_driver_info( GraphicsDriverInfo *ret_info )
3093 {
3094      D_ASSERT( card != NULL );
3095      D_ASSERT( card->shared != NULL );
3096 
3097      D_ASSERT( ret_info != NULL );
3098 
3099      *ret_info = card->shared->driver_info;
3100 }
3101 
3102 
3103 int
dfb_gfxcard_reserve_memory(CoreGraphicsDevice * device,unsigned int size)3104 dfb_gfxcard_reserve_memory( CoreGraphicsDevice *device, unsigned int size )
3105 {
3106      DFBGraphicsCoreShared *shared;
3107 
3108      D_ASSERT( device != NULL );
3109      D_ASSERT( device->shared != NULL );
3110 
3111      shared = device->shared;
3112 
3113      if (shared->device_info.limits.surface_byteoffset_alignment) {
3114           size += shared->device_info.limits.surface_byteoffset_alignment - 1;
3115           size -= (size % shared->device_info.limits.surface_byteoffset_alignment);
3116      }
3117      else
3118           D_WARN( "no alignment specified yet?" );
3119 
3120      if (shared->videoram_length < size) {
3121           D_WARN( "not enough video memory (%u < %u)", shared->videoram_length, size );
3122           return -1;
3123      }
3124 
3125      shared->videoram_length -= size;
3126 
3127      return shared->videoram_length;
3128 }
3129 
3130 int
dfb_gfxcard_reserve_auxmemory(CoreGraphicsDevice * device,unsigned int size)3131 dfb_gfxcard_reserve_auxmemory( CoreGraphicsDevice *device, unsigned int size )
3132 {
3133      DFBGraphicsCoreShared *shared;
3134      int                    offset;
3135 
3136      D_ASSERT( device != NULL );
3137      D_ASSERT( device->shared != NULL );
3138 
3139      shared = device->shared;
3140 
3141      /* Reserve memory at the beginning of the aperture
3142       * to prevent overflows on DMA buffers. */
3143 
3144      offset = shared->auxram_offset;
3145 
3146      if (shared->auxram_length < (offset + size))
3147           return -1;
3148 
3149      shared->auxram_offset += size;
3150 
3151      return offset;
3152 }
3153 
3154 unsigned int
dfb_gfxcard_memory_length(void)3155 dfb_gfxcard_memory_length( void )
3156 {
3157      D_ASSERT( card != NULL );
3158      D_ASSERT( card->shared != NULL );
3159 
3160      return card->shared->videoram_length;
3161 }
3162 
3163 unsigned int
dfb_gfxcard_auxmemory_length(void)3164 dfb_gfxcard_auxmemory_length( void )
3165 {
3166      D_ASSERT( card != NULL );
3167      D_ASSERT( card->shared != NULL );
3168 
3169      return card->shared->auxram_length;
3170 }
3171 
3172 volatile void *
dfb_gfxcard_map_mmio(CoreGraphicsDevice * device,unsigned int offset,int length)3173 dfb_gfxcard_map_mmio( CoreGraphicsDevice *device,
3174                       unsigned int        offset,
3175                       int                 length )
3176 {
3177      return dfb_system_map_mmio( offset, length );
3178 }
3179 
3180 void
dfb_gfxcard_unmap_mmio(CoreGraphicsDevice * device,volatile void * addr,int length)3181 dfb_gfxcard_unmap_mmio( CoreGraphicsDevice *device,
3182                         volatile void      *addr,
3183                         int                 length )
3184 {
3185      dfb_system_unmap_mmio( addr, length );
3186 }
3187 
3188 int
dfb_gfxcard_get_accelerator(CoreGraphicsDevice * device)3189 dfb_gfxcard_get_accelerator( CoreGraphicsDevice *device )
3190 {
3191      return dfb_system_get_accelerator();
3192 }
3193 
3194 void
dfb_gfxcard_get_limits(CoreGraphicsDevice * device,CardLimitations * ret_limits)3195 dfb_gfxcard_get_limits( CoreGraphicsDevice *device,
3196                         CardLimitations    *ret_limits )
3197 {
3198      D_ASSERT( device != NULL );
3199      D_ASSERT( ret_limits != NULL );
3200 
3201      if (!device)
3202           device = card;
3203 
3204      *ret_limits = device->limits;
3205 }
3206 
3207 void
dfb_gfxcard_calc_buffer_size(CoreGraphicsDevice * device,CoreSurfaceBuffer * buffer,int * ret_pitch,int * ret_length)3208 dfb_gfxcard_calc_buffer_size( CoreGraphicsDevice *device,
3209                               CoreSurfaceBuffer  *buffer,
3210                               int                *ret_pitch,
3211                               int                *ret_length )
3212 {
3213      int          pitch;
3214      int          length;
3215      CoreSurface *surface;
3216 
3217      D_ASSERT( device != NULL );
3218      D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
3219 
3220      surface = buffer->surface;
3221      D_MAGIC_ASSERT( surface, CoreSurface );
3222 
3223      /* calculate the required length depending on limitations */
3224      pitch = MAX( surface->config.size.w, surface->config.min_size.w );
3225 
3226      if (pitch < device->limits.surface_max_power_of_two_pixelpitch &&
3227          surface->config.size.h < device->limits.surface_max_power_of_two_height)
3228           pitch = 1 << direct_log2( pitch );
3229 
3230      if (device->limits.surface_pixelpitch_alignment > 1) {
3231           pitch += device->limits.surface_pixelpitch_alignment - 1;
3232           pitch -= pitch % device->limits.surface_pixelpitch_alignment;
3233      }
3234 
3235      pitch = DFB_BYTES_PER_LINE( buffer->format, pitch );
3236 
3237      if (pitch < device->limits.surface_max_power_of_two_bytepitch &&
3238          surface->config.size.h < device->limits.surface_max_power_of_two_height)
3239           pitch = 1 << direct_log2( pitch );
3240 
3241      if (device->limits.surface_bytepitch_alignment > 1) {
3242           pitch += device->limits.surface_bytepitch_alignment - 1;
3243           pitch -= pitch % device->limits.surface_bytepitch_alignment;
3244      }
3245 
3246      length = DFB_PLANE_MULTIPLY( buffer->format,
3247                                   MAX( surface->config.size.h, surface->config.min_size.h ) * pitch );
3248 
3249      /* Add extra space for optimized routines which are now allowed to overrun, e.g. prefetching. */
3250      length += 16;
3251 
3252      if (device->limits.surface_byteoffset_alignment > 1) {
3253           length += device->limits.surface_byteoffset_alignment - 1;
3254           length -= length % device->limits.surface_byteoffset_alignment;
3255      }
3256 
3257      if (ret_pitch)
3258           *ret_pitch = pitch;
3259 
3260      if (ret_length)
3261           *ret_length = length;
3262 }
3263 
3264 unsigned long
dfb_gfxcard_memory_physical(CoreGraphicsDevice * device,unsigned int offset)3265 dfb_gfxcard_memory_physical( CoreGraphicsDevice *device,
3266                              unsigned int        offset )
3267 {
3268      return dfb_system_video_memory_physical( offset );
3269 }
3270 
3271 void *
dfb_gfxcard_memory_virtual(CoreGraphicsDevice * device,unsigned int offset)3272 dfb_gfxcard_memory_virtual( CoreGraphicsDevice *device,
3273                             unsigned int        offset )
3274 {
3275      return dfb_system_video_memory_virtual( offset );
3276 }
3277 
3278 unsigned long
dfb_gfxcard_auxmemory_physical(CoreGraphicsDevice * device,unsigned int offset)3279 dfb_gfxcard_auxmemory_physical( CoreGraphicsDevice *device,
3280                                 unsigned int        offset )
3281 {
3282      return dfb_system_aux_memory_physical( offset );
3283 }
3284 
3285 void *
dfb_gfxcard_auxmemory_virtual(CoreGraphicsDevice * device,unsigned int offset)3286 dfb_gfxcard_auxmemory_virtual( CoreGraphicsDevice *device,
3287                                unsigned int        offset )
3288 {
3289      return dfb_system_aux_memory_virtual( offset );
3290 }
3291 
3292 void *
dfb_gfxcard_get_device_data(void)3293 dfb_gfxcard_get_device_data( void )
3294 {
3295      D_ASSERT( card != NULL );
3296      D_ASSERT( card->shared != NULL );
3297 
3298      return card->shared->device_data;
3299 }
3300 
3301 void *
dfb_gfxcard_get_driver_data(void)3302 dfb_gfxcard_get_driver_data( void )
3303 {
3304      D_ASSERT( card != NULL );
3305 
3306      return card->driver_data;
3307 }
3308 
3309 CoreGraphicsDevice *
dfb_gfxcard_get_primary(void)3310 dfb_gfxcard_get_primary( void )
3311 {
3312      return card;
3313 }
3314 
3315 
3316 /** internal **/
3317 
3318 /*
3319  * loads/probes/unloads one driver module after another until a suitable
3320  * driver is found and returns its symlinked functions
3321  */
dfb_gfxcard_find_driver(CoreDFB * core)3322 static void dfb_gfxcard_find_driver( CoreDFB *core )
3323 {
3324      DirectLink          *link;
3325      FusionSHMPoolShared *pool = dfb_core_shmpool( core );
3326 
3327      link = dfb_graphics_drivers.entries;
3328 
3329      while (direct_list_check_link( link )) {
3330 
3331           DirectModuleEntry *module = (DirectModuleEntry*) link;
3332 
3333           link = link->next;
3334 
3335           const GraphicsDriverFuncs *funcs = direct_module_ref( module );
3336 
3337           if (!funcs)
3338                continue;
3339 
3340           if (!card->module && funcs->Probe( card )) {
3341                funcs->GetDriverInfo( card, &card->shared->driver_info );
3342 
3343                card->module       = module;
3344                card->driver_funcs = funcs;
3345 
3346                card->shared->module_name = SHSTRDUP( pool, module->name );
3347           }
3348           else {
3349                /* can result in immediate removal, so "link" must already be on next */
3350                direct_module_unref( module );
3351           }
3352      }
3353 }
3354 
3355 /*
3356  * loads the driver module used by the session
3357  */
dfb_gfxcard_load_driver(void)3358 static void dfb_gfxcard_load_driver( void )
3359 {
3360      DirectLink *link;
3361 
3362      if (!card->shared->module_name)
3363           return;
3364 
3365      direct_list_foreach (link, dfb_graphics_drivers.entries) {
3366           DirectModuleEntry *module = (DirectModuleEntry*) link;
3367 
3368           const GraphicsDriverFuncs *funcs = direct_module_ref( module );
3369 
3370           if (!funcs)
3371                continue;
3372 
3373           if (!card->module &&
3374               !strcmp( module->name, card->shared->module_name ))
3375           {
3376                card->module       = module;
3377                card->driver_funcs = funcs;
3378           }
3379           else
3380                direct_module_unref( module );
3381      }
3382 }
3383 
3384