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