1 /*
2 (c) Copyright 2001-2009 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 <string.h>
32
33 #include <pthread.h>
34
35 #include <fusion/fusion.h>
36 #include <fusion/reactor.h>
37
38 #include <directfb.h>
39
40 #include <core/core.h>
41 #include <core/coretypes.h>
42
43 #include <core/palette.h>
44 #include <core/state.h>
45 #include <core/surface.h>
46
47 #include <direct/mem.h>
48 #include <direct/memcpy.h>
49 #include <direct/util.h>
50
51 #include <misc/conf.h>
52
53
54 static inline void
validate_clip(CardState * state,int xmax,int ymax,bool warn)55 validate_clip( CardState *state,
56 int xmax,
57 int ymax,
58 bool warn )
59 {
60 D_MAGIC_ASSERT( state, CardState );
61 DFB_REGION_ASSERT( &state->clip );
62
63 D_ASSERT( xmax >= 0 );
64 D_ASSERT( ymax >= 0 );
65 D_ASSERT( state->clip.x1 <= state->clip.x2 );
66 D_ASSERT( state->clip.y1 <= state->clip.y2 );
67
68 if (state->clip.x1 <= xmax &&
69 state->clip.y1 <= ymax &&
70 state->clip.x2 <= xmax &&
71 state->clip.y2 <= ymax)
72 return;
73
74 if (warn)
75 D_WARN( "Clip %d,%d-%dx%d invalid, adjusting to fit %dx%d",
76 DFB_RECTANGLE_VALS_FROM_REGION( &state->clip ), xmax+1, ymax+1 );
77
78 if (state->clip.x1 > xmax)
79 state->clip.x1 = xmax;
80
81 if (state->clip.y1 > ymax)
82 state->clip.y1 = ymax;
83
84 if (state->clip.x2 > xmax)
85 state->clip.x2 = xmax;
86
87 if (state->clip.y2 > ymax)
88 state->clip.y2 = ymax;
89
90 state->modified |= SMF_CLIP;
91 }
92
93 int
dfb_state_init(CardState * state,CoreDFB * core)94 dfb_state_init( CardState *state, CoreDFB *core )
95 {
96 D_ASSERT( state != NULL );
97
98 memset( state, 0, sizeof(CardState) );
99
100 state->core = core;
101 state->fusion_id = fusion_id( dfb_core_world(core) );
102 state->modified = SMF_ALL;
103 state->src_blend = DSBF_SRCALPHA;
104 state->dst_blend = DSBF_INVSRCALPHA;
105 state->render_options = dfb_config->render_options;
106
107 state->matrix[0] = 0x10000;
108 state->matrix[1] = 0x00000;
109 state->matrix[2] = 0x00000;
110 state->matrix[3] = 0x00000;
111 state->matrix[4] = 0x10000;
112 state->matrix[5] = 0x00000;
113 state->matrix[6] = 0x00000;
114 state->matrix[7] = 0x00000;
115 state->matrix[8] = 0x10000;
116 state->affine_matrix = DFB_TRUE;
117
118 state->from = CSBR_FRONT;
119 state->to = CSBR_BACK;
120
121 direct_util_recursive_pthread_mutex_init( &state->lock );
122
123 direct_serial_init( &state->dst_serial );
124 direct_serial_init( &state->src_serial );
125 direct_serial_init( &state->src_mask_serial );
126 direct_serial_init( &state->src2_serial );
127
128 D_MAGIC_SET( state, CardState );
129
130 return 0;
131 }
132
133 void
dfb_state_destroy(CardState * state)134 dfb_state_destroy( CardState *state )
135 {
136 D_MAGIC_ASSERT( state, CardState );
137
138 D_ASSUME( !(state->flags & CSF_DRAWING) );
139
140 D_ASSERT( state->destination == NULL );
141 D_ASSERT( state->source == NULL );
142 D_ASSERT( state->source2 == NULL );
143 D_ASSERT( state->source_mask == NULL );
144
145 D_MAGIC_CLEAR( state );
146
147 direct_serial_deinit( &state->dst_serial );
148 direct_serial_deinit( &state->src_serial );
149 direct_serial_deinit( &state->src_mask_serial );
150 direct_serial_deinit( &state->src2_serial );
151
152 if (state->gfxs) {
153 GenefxState *gfxs = state->gfxs;
154
155 if (gfxs->ABstart)
156 D_FREE( gfxs->ABstart );
157
158 D_FREE( gfxs );
159 }
160
161 if (state->num_translation) {
162 D_ASSERT( state->index_translation != NULL );
163
164 D_FREE( state->index_translation );
165 }
166 else
167 D_ASSERT( state->index_translation == NULL );
168
169 pthread_mutex_destroy( &state->lock );
170 }
171
172 DFBResult
dfb_state_set_destination(CardState * state,CoreSurface * destination)173 dfb_state_set_destination( CardState *state, CoreSurface *destination )
174 {
175 D_MAGIC_ASSERT( state, CardState );
176
177 dfb_state_lock( state );
178
179 D_ASSUME( !(state->flags & CSF_DRAWING) );
180
181 if (state->destination != destination) {
182 if (destination) {
183 if (dfb_surface_ref( destination )) {
184 D_WARN( "could not ref() destination" );
185 dfb_state_unlock( state );
186 return DFB_DEAD;
187 }
188
189 validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, false );
190 }
191
192 if (state->destination) {
193 D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_DESTINATION ) );
194 dfb_surface_unref( state->destination );
195 }
196
197 state->destination = destination;
198 state->modified |= SMF_DESTINATION;
199
200 if (destination) {
201 direct_serial_copy( &state->dst_serial, &destination->serial );
202
203 D_FLAGS_SET( state->flags, CSF_DESTINATION );
204 }
205 else
206 D_FLAGS_CLEAR( state->flags, CSF_DESTINATION );
207 }
208
209 dfb_state_unlock( state );
210
211 return DFB_OK;
212 }
213
214 DFBResult
dfb_state_set_source(CardState * state,CoreSurface * source)215 dfb_state_set_source( CardState *state, CoreSurface *source )
216 {
217 D_MAGIC_ASSERT( state, CardState );
218
219 dfb_state_lock( state );
220
221 if (state->source != source) {
222 if (source && dfb_surface_ref( source )) {
223 D_WARN( "could not ref() source" );
224 dfb_state_unlock( state );
225 return DFB_DEAD;
226 }
227
228 if (state->source) {
229 D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE ) );
230 dfb_surface_unref( state->source );
231 }
232
233 state->source = source;
234 state->modified |= SMF_SOURCE;
235
236 if (source) {
237 direct_serial_copy( &state->src_serial, &source->serial );
238
239 D_FLAGS_SET( state->flags, CSF_SOURCE );
240 }
241 else
242 D_FLAGS_CLEAR( state->flags, CSF_SOURCE );
243 }
244
245 dfb_state_unlock( state );
246
247 return DFB_OK;
248 }
249
250 DFBResult
dfb_state_set_source2(CardState * state,CoreSurface * source2)251 dfb_state_set_source2( CardState *state, CoreSurface *source2 )
252 {
253 D_MAGIC_ASSERT( state, CardState );
254
255 dfb_state_lock( state );
256
257 if (state->source2 != source2) {
258 if (source2 && dfb_surface_ref( source2 )) {
259 D_WARN( "could not ref() source2" );
260 dfb_state_unlock( state );
261 return DFB_DEAD;
262 }
263
264 if (state->source2) {
265 D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE2 ) );
266 dfb_surface_unref( state->source2 );
267 }
268
269 state->source2 = source2;
270 state->modified |= SMF_SOURCE2;
271
272 if (source2) {
273 direct_serial_copy( &state->src2_serial, &source2->serial );
274
275 D_FLAGS_SET( state->flags, CSF_SOURCE2 );
276 }
277 else
278 D_FLAGS_CLEAR( state->flags, CSF_SOURCE2 );
279 }
280
281 dfb_state_unlock( state );
282
283 return DFB_OK;
284 }
285
286 DFBResult
dfb_state_set_source_mask(CardState * state,CoreSurface * source_mask)287 dfb_state_set_source_mask( CardState *state, CoreSurface *source_mask )
288 {
289 D_MAGIC_ASSERT( state, CardState );
290
291 dfb_state_lock( state );
292
293 if (state->source_mask != source_mask) {
294 if (source_mask && dfb_surface_ref( source_mask )) {
295 D_WARN( "could not ref() source mask" );
296 dfb_state_unlock( state );
297 return DFB_DEAD;
298 }
299
300 if (state->source_mask) {
301 D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK ) );
302 dfb_surface_unref( state->source_mask );
303 }
304
305 state->source_mask = source_mask;
306 state->modified |= SMF_SOURCE_MASK;
307
308 if (source_mask) {
309 direct_serial_copy( &state->src_mask_serial, &source_mask->serial );
310
311 D_FLAGS_SET( state->flags, CSF_SOURCE_MASK );
312 }
313 else
314 D_FLAGS_CLEAR( state->flags, CSF_SOURCE_MASK );
315 }
316
317 dfb_state_unlock( state );
318
319 return DFB_OK;
320 }
321
322 void
dfb_state_update(CardState * state,bool update_sources)323 dfb_state_update( CardState *state, bool update_sources )
324 {
325 CoreSurface *destination;
326
327 D_MAGIC_ASSERT( state, CardState );
328 DFB_REGION_ASSERT( &state->clip );
329
330 destination = state->destination;
331
332 if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) {
333
334 D_ASSERT( destination != NULL );
335
336 if (direct_serial_update( &state->dst_serial, &destination->serial )) {
337 validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );
338
339 state->modified |= SMF_DESTINATION;
340 }
341 }
342 else if (destination)
343 validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );
344
345 if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE )) {
346 CoreSurface *source = state->source;
347
348 D_ASSERT( source != NULL );
349
350 if (direct_serial_update( &state->src_serial, &source->serial ))
351 state->modified |= SMF_SOURCE;
352 }
353
354 if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK )) {
355 CoreSurface *source_mask = state->source_mask;
356
357 D_ASSERT( source_mask != NULL );
358
359 if (direct_serial_update( &state->src_mask_serial, &source_mask->serial ))
360 state->modified |= SMF_SOURCE_MASK;
361 }
362
363 if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE2 )) {
364 CoreSurface *source2 = state->source2;
365
366 D_ASSERT( source2 != NULL );
367
368 if (direct_serial_update( &state->src2_serial, &source2->serial ))
369 state->modified |= SMF_SOURCE2;
370 }
371 }
372
373 DFBResult
dfb_state_set_index_translation(CardState * state,const int * indices,int num_indices)374 dfb_state_set_index_translation( CardState *state,
375 const int *indices,
376 int num_indices )
377 {
378 D_MAGIC_ASSERT( state, CardState );
379
380 D_ASSERT( indices != NULL || num_indices == 0 );
381
382 dfb_state_lock( state );
383
384 if (state->num_translation != num_indices) {
385 int *new_trans = D_REALLOC( state->index_translation,
386 num_indices * sizeof(int) );
387
388 D_ASSERT( num_indices || new_trans == NULL );
389
390 if (num_indices && !new_trans) {
391 dfb_state_unlock( state );
392 return D_OOM();
393 }
394
395 state->index_translation = new_trans;
396 state->num_translation = num_indices;
397 }
398
399 if (num_indices)
400 direct_memcpy( state->index_translation, indices, num_indices * sizeof(int) );
401
402 state->modified |= SMF_INDEX_TRANSLATION;
403
404 dfb_state_unlock( state );
405
406 return DFB_OK;
407 }
408
409 void
dfb_state_set_matrix(CardState * state,const s32 * matrix)410 dfb_state_set_matrix( CardState *state,
411 const s32 *matrix )
412 {
413 D_MAGIC_ASSERT( state, CardState );
414
415 D_ASSERT( matrix != NULL );
416
417 if (memcmp( state->matrix, matrix, sizeof(state->matrix) )) {
418 direct_memcpy( state->matrix, matrix, sizeof(state->matrix) );
419
420 state->affine_matrix = (matrix[6] == 0x00000 &&
421 matrix[7] == 0x00000 &&
422 matrix[8] == 0x10000);
423
424 state->modified |= SMF_MATRIX;
425 }
426 }
427
428 void
dfb_state_set_color_or_index(CardState * state,const DFBColor * color,int index)429 dfb_state_set_color_or_index( CardState *state,
430 const DFBColor *color,
431 int index )
432 {
433 CoreSurface *destination;
434 CorePalette *palette = NULL;
435
436 D_MAGIC_ASSERT( state, CardState );
437 D_ASSERT( color != NULL );
438
439 destination = state->destination;
440 if (destination)
441 palette = destination->palette;
442
443 if (index < 0) {
444 D_ASSERT( color != NULL );
445
446 if (palette)
447 dfb_state_set_color_index( state, dfb_palette_search( palette,
448 color->r, color->g,
449 color->b, color->a ) );
450
451 dfb_state_set_color( state, color );
452 }
453 else {
454 dfb_state_set_color_index( state, index );
455
456 if (palette) {
457 D_ASSERT( palette->num_entries > 0 );
458 D_ASSUME( palette->num_entries > index );
459
460 dfb_state_set_color( state, &palette->entries[index % palette->num_entries] );
461 }
462 }
463 }
464
465