1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22
23 #if SDL_VIDEO_DRIVER_DIRECTFB
24 #include "SDL_DirectFB_window.h"
25 #include "SDL_DirectFB_modes.h"
26
27 #include "SDL_syswm.h"
28 #include "SDL_DirectFB_shape.h"
29
30 #include "../SDL_sysvideo.h"
31 #include "../../render/SDL_sysrender.h"
32
33 #ifndef DFB_VERSION_ATLEAST
34
35 #define DFB_VERSIONNUM(X, Y, Z) \
36 ((X)*1000 + (Y)*100 + (Z))
37
38 #define DFB_COMPILEDVERSION \
39 DFB_VERSIONNUM(DIRECTFB_MAJOR_VERSION, DIRECTFB_MINOR_VERSION, DIRECTFB_MICRO_VERSION)
40
41 #define DFB_VERSION_ATLEAST(X, Y, Z) \
42 (DFB_COMPILEDVERSION >= DFB_VERSIONNUM(X, Y, Z))
43
44 #define SDL_DFB_CHECK(x) x
45
46 #endif
47
48 /* the following is not yet tested ... */
49 #define USE_DISPLAY_PALETTE (0)
50
51
52 #define SDL_DFB_RENDERERDATA(rend) DirectFB_RenderData *renddata = ((rend) ? (DirectFB_RenderData *) (rend)->driverdata : NULL)
53
54
55 /* DirectFB renderer implementation */
56
57 static SDL_Renderer *DirectFB_CreateRenderer(SDL_Window * window,
58 Uint32 flags);
59 static void DirectFB_ActivateRenderer(SDL_Renderer * renderer);
60 static int DirectFB_CreateTexture(SDL_Renderer * renderer,
61 SDL_Texture * texture);
62 static int DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
63 SDL_Texture * texture,
64 void **pixels, int *pitch);
65 static int DirectFB_SetTexturePalette(SDL_Renderer * renderer,
66 SDL_Texture * texture,
67 const SDL_Color * colors,
68 int firstcolor, int ncolors);
69 static int DirectFB_GetTexturePalette(SDL_Renderer * renderer,
70 SDL_Texture * texture,
71 SDL_Color * colors,
72 int firstcolor, int ncolors);
73 static int DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer,
74 SDL_Texture * texture);
75 static int DirectFB_SetTextureColorMod(SDL_Renderer * renderer,
76 SDL_Texture * texture);
77 static int DirectFB_SetTextureBlendMode(SDL_Renderer * renderer,
78 SDL_Texture * texture);
79 static int DirectFB_SetTextureScaleMode(SDL_Renderer * renderer,
80 SDL_Texture * texture);
81 static int DirectFB_UpdateTexture(SDL_Renderer * renderer,
82 SDL_Texture * texture,
83 const SDL_Rect * rect,
84 const void *pixels, int pitch);
85 static int DirectFB_LockTexture(SDL_Renderer * renderer,
86 SDL_Texture * texture,
87 const SDL_Rect * rect,
88 void **pixels, int *pitch);
89 static void DirectFB_UnlockTexture(SDL_Renderer * renderer,
90 SDL_Texture * texture);
91 static void DirectFB_DirtyTexture(SDL_Renderer * renderer,
92 SDL_Texture * texture, int numrects,
93 const SDL_Rect * rects);
94 static int DirectFB_SetDrawBlendMode(SDL_Renderer * renderer);
95 static int DirectFB_RenderDrawPoints(SDL_Renderer * renderer,
96 const SDL_FPoint * points, int count);
97 static int DirectFB_RenderDrawLines(SDL_Renderer * renderer,
98 const SDL_FPoint * points, int count);
99 static int DirectFB_RenderDrawRects(SDL_Renderer * renderer,
100 const SDL_Rect ** rects, int count);
101 static int DirectFB_RenderFillRects(SDL_Renderer * renderer,
102 const SDL_FRect * rects, int count);
103 static int DirectFB_RenderCopy(SDL_Renderer * renderer,
104 SDL_Texture * texture,
105 const SDL_Rect * srcrect,
106 const SDL_FRect * dstrect);
107 static void DirectFB_RenderPresent(SDL_Renderer * renderer);
108 static void DirectFB_DestroyTexture(SDL_Renderer * renderer,
109 SDL_Texture * texture);
110 static void DirectFB_DestroyRenderer(SDL_Renderer * renderer);
111 static int DirectFB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
112 Uint32 format, void * pixels, int pitch);
113 static int DirectFB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
114 Uint32 format, const void * pixels, int pitch);
115 static int DirectFB_UpdateViewport(SDL_Renderer * renderer);
116 static int DirectFB_UpdateClipRect(SDL_Renderer * renderer);
117 static int DirectFB_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
118
119 static int PrepareDraw(SDL_Renderer * renderer);
120
121
122 #define SDL_DFB_WINDOWSURFACE(win) IDirectFBSurface *destsurf = ((DFB_WindowData *) ((win)->driverdata))->surface;
123
124 SDL_RenderDriver DirectFB_RenderDriver = {
125 DirectFB_CreateRenderer,
126 {
127 "directfb",
128 (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
129 /* (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
130 SDL_TEXTUREMODULATE_ALPHA),
131 (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND |
132 SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
133 (SDL_SCALEMODE_NONE | SDL_SCALEMODE_FAST |
134 SDL_SCALEMODE_SLOW | SDL_SCALEMODE_BEST), */
135 0,
136 {
137 /* formats filled in later */
138 },
139 0,
140 0}
141 };
142
143 typedef struct
144 {
145 SDL_Window *window;
146 DFBSurfaceFlipFlags flipflags;
147 int size_changed;
148 int lastBlendMode;
149 DFBSurfaceBlittingFlags blitFlags;
150 DFBSurfaceDrawingFlags drawFlags;
151 IDirectFBSurface* target;
152 } DirectFB_RenderData;
153
154 typedef struct
155 {
156 IDirectFBSurface *surface;
157 Uint32 format;
158 void *pixels;
159 int pitch;
160 IDirectFBPalette *palette;
161 int isDirty;
162
163 SDL_VideoDisplay *display; /* only for yuv textures */
164
165 #if (DFB_VERSION_ATLEAST(1,2,0))
166 DFBSurfaceRenderOptions render_options;
167 #endif
168 } DirectFB_TextureData;
169
170 static SDL_INLINE void
SDLtoDFBRect(const SDL_Rect * sr,DFBRectangle * dr)171 SDLtoDFBRect(const SDL_Rect * sr, DFBRectangle * dr)
172 {
173 dr->x = sr->x;
174 dr->y = sr->y;
175 dr->h = sr->h;
176 dr->w = sr->w;
177 }
178 static SDL_INLINE void
SDLtoDFBRect_Float(const SDL_FRect * sr,DFBRectangle * dr)179 SDLtoDFBRect_Float(const SDL_FRect * sr, DFBRectangle * dr)
180 {
181 dr->x = sr->x;
182 dr->y = sr->y;
183 dr->h = sr->h;
184 dr->w = sr->w;
185 }
186
187
188 static int
TextureHasAlpha(DirectFB_TextureData * data)189 TextureHasAlpha(DirectFB_TextureData * data)
190 {
191 /* Drawing primitive ? */
192 if (!data)
193 return 0;
194
195 return (DFB_PIXELFORMAT_HAS_ALPHA(DirectFB_SDLToDFBPixelFormat(data->format)) ? 1 : 0);
196 #if 0
197 switch (data->format) {
198 case SDL_PIXELFORMAT_INDEX4LSB:
199 case SDL_PIXELFORMAT_INDEX4MSB:
200 case SDL_PIXELFORMAT_ARGB4444:
201 case SDL_PIXELFORMAT_ARGB1555:
202 case SDL_PIXELFORMAT_ARGB8888:
203 case SDL_PIXELFORMAT_RGBA8888:
204 case SDL_PIXELFORMAT_ABGR8888:
205 case SDL_PIXELFORMAT_BGRA8888:
206 case SDL_PIXELFORMAT_ARGB2101010:
207 return 1;
208 default:
209 return 0;
210 }
211 #endif
212 }
213
get_dfb_surface(SDL_Window * window)214 static SDL_INLINE IDirectFBSurface *get_dfb_surface(SDL_Window *window)
215 {
216 SDL_SysWMinfo wm_info;
217 SDL_memset(&wm_info, 0, sizeof(SDL_SysWMinfo));
218
219 SDL_VERSION(&wm_info.version);
220 SDL_GetWindowWMInfo(window, &wm_info);
221
222 return wm_info.info.dfb.surface;
223 }
224
get_dfb_window(SDL_Window * window)225 static SDL_INLINE IDirectFBWindow *get_dfb_window(SDL_Window *window)
226 {
227 SDL_SysWMinfo wm_info;
228 SDL_memset(&wm_info, 0, sizeof(SDL_SysWMinfo));
229
230 SDL_VERSION(&wm_info.version);
231 SDL_GetWindowWMInfo(window, &wm_info);
232
233 return wm_info.info.dfb.window;
234 }
235
236 static void
SetBlendMode(DirectFB_RenderData * data,int blendMode,DirectFB_TextureData * source)237 SetBlendMode(DirectFB_RenderData * data, int blendMode,
238 DirectFB_TextureData * source)
239 {
240 IDirectFBSurface *destsurf = data->target;
241
242 /* FIXME: check for format change */
243 if (1 || data->lastBlendMode != blendMode) {
244 switch (blendMode) {
245 case SDL_BLENDMODE_NONE:
246 /**< No blending */
247 data->blitFlags = DSBLIT_NOFX;
248 data->drawFlags = DSDRAW_NOFX;
249 SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ONE));
250 SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ZERO));
251 break;
252 #if 0
253 case SDL_BLENDMODE_MASK:
254 data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
255 data->drawFlags = DSDRAW_BLEND;
256 SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
257 SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_INVSRCALPHA));
258 break;
259 #endif
260 case SDL_BLENDMODE_BLEND:
261 data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
262 data->drawFlags = DSDRAW_BLEND;
263 SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
264 SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_INVSRCALPHA));
265 break;
266 case SDL_BLENDMODE_ADD:
267 data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
268 data->drawFlags = DSDRAW_BLEND;
269 /* FIXME: SRCALPHA kills performance on radeon ...
270 * It will be cheaper to copy the surface to a temporary surface and premultiply
271 */
272 if (source && TextureHasAlpha(source))
273 SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
274 else
275 SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ONE));
276 SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ONE));
277 break;
278 case SDL_BLENDMODE_MOD:
279 data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
280 data->drawFlags = DSDRAW_BLEND;
281 SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ZERO));
282 SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_SRCCOLOR));
283
284 break;
285 }
286 data->lastBlendMode = blendMode;
287 }
288 }
289
290 static int
DisplayPaletteChanged(void * userdata,SDL_Palette * palette)291 DisplayPaletteChanged(void *userdata, SDL_Palette * palette)
292 {
293 #if USE_DISPLAY_PALETTE
294 DirectFB_RenderData *data = (DirectFB_RenderData *) userdata;
295 SDL_DFB_WINDOWSURFACE(data->window);
296 IDirectFBPalette *surfpal;
297
298 int i;
299 int ncolors;
300 DFBColor entries[256];
301
302 SDL_DFB_CHECKERR(destsurf->GetPalette(destsurf, &surfpal));
303
304 /* FIXME: number of colors */
305 ncolors = (palette->ncolors < 256 ? palette->ncolors : 256);
306
307 for (i = 0; i < ncolors; ++i) {
308 entries[i].r = palette->colors[i].r;
309 entries[i].g = palette->colors[i].g;
310 entries[i].b = palette->colors[i].b;
311 entries[i].a = palette->colors[i].a;
312 }
313 SDL_DFB_CHECKERR(surfpal->SetEntries(surfpal, entries, ncolors, 0));
314 return 0;
315 error:
316 #else
317 SDL_Unsupported();
318 #endif
319 return -1;
320 }
321
322 static void
DirectFB_WindowEvent(SDL_Renderer * renderer,const SDL_WindowEvent * event)323 DirectFB_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
324 {
325 SDL_DFB_RENDERERDATA(renderer);
326
327 if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
328 /* Rebind the context to the window area and update matrices */
329 /* SDL_CurrentContext = NULL; */
330 /* data->updateSize = SDL_TRUE; */
331 renddata->size_changed = SDL_TRUE;
332 }
333 }
334
335 int
DirectFB_RenderClear(SDL_Renderer * renderer)336 DirectFB_RenderClear(SDL_Renderer * renderer)
337 {
338 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
339 IDirectFBSurface *destsurf = data->target;
340
341 DirectFB_ActivateRenderer(renderer);
342
343 PrepareDraw(renderer);
344
345 destsurf->Clear(destsurf, renderer->r, renderer->g, renderer->b, renderer->a);
346
347
348 return 0;
349 }
350
351 SDL_Renderer *
DirectFB_CreateRenderer(SDL_Window * window,Uint32 flags)352 DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags)
353 {
354 IDirectFBSurface *winsurf = get_dfb_surface(window);
355 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
356 SDL_Renderer *renderer = NULL;
357 DirectFB_RenderData *data = NULL;
358 DFBSurfaceCapabilities scaps;
359
360 SDL_DFB_ALLOC_CLEAR(renderer, sizeof(*renderer));
361 SDL_DFB_ALLOC_CLEAR(data, sizeof(*data));
362
363 renderer->WindowEvent = DirectFB_WindowEvent;
364 renderer->CreateTexture = DirectFB_CreateTexture;
365 renderer->SetTextureAlphaMod = DirectFB_SetTextureAlphaMod;
366 renderer->SetTextureColorMod = DirectFB_SetTextureColorMod;
367 renderer->SetTextureBlendMode = DirectFB_SetTextureBlendMode;
368 renderer->UpdateTexture = DirectFB_UpdateTexture;
369 renderer->LockTexture = DirectFB_LockTexture;
370 renderer->RenderClear = DirectFB_RenderClear;
371 renderer->UnlockTexture = DirectFB_UnlockTexture;
372 renderer->RenderDrawPoints = DirectFB_RenderDrawPoints;
373 renderer->RenderDrawLines = DirectFB_RenderDrawLines;
374 /* SetDrawColor - no needed */
375 renderer->RenderFillRects = DirectFB_RenderFillRects;
376
377 renderer->RenderCopy = DirectFB_RenderCopy;
378 renderer->RenderPresent = DirectFB_RenderPresent;
379
380 /* FIXME: Yet to be tested */
381 renderer->RenderReadPixels = DirectFB_RenderReadPixels;
382 /* renderer->RenderWritePixels = DirectFB_RenderWritePixels; */
383
384 renderer->DestroyTexture = DirectFB_DestroyTexture;
385 renderer->DestroyRenderer = DirectFB_DestroyRenderer;
386 renderer->UpdateViewport = DirectFB_UpdateViewport;
387 renderer->UpdateClipRect = DirectFB_UpdateClipRect;
388 renderer->SetRenderTarget = DirectFB_SetRenderTarget;
389
390 #if 0
391 renderer->QueryTexturePixels = DirectFB_QueryTexturePixels;
392 renderer->SetTexturePalette = DirectFB_SetTexturePalette;
393 renderer->GetTexturePalette = DirectFB_GetTexturePalette;
394 renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode;
395 renderer->DirtyTexture = DirectFB_DirtyTexture;
396 renderer->SetDrawBlendMode = DirectFB_SetDrawBlendMode;
397 renderer->RenderDrawRects = DirectFB_RenderDrawRects;
398 #endif
399
400 renderer->info = DirectFB_RenderDriver.info;
401 renderer->window = window; /* SDL window */
402 renderer->driverdata = data;
403
404 renderer->info.flags =
405 SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
406
407 data->window = window;
408 data->target = winsurf;
409
410 data->flipflags = DSFLIP_PIPELINE | DSFLIP_BLIT;
411
412 if (flags & SDL_RENDERER_PRESENTVSYNC) {
413 data->flipflags |= DSFLIP_WAITFORSYNC | DSFLIP_ONSYNC;
414 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
415 } else
416 data->flipflags |= DSFLIP_ONSYNC;
417
418 SDL_DFB_CHECKERR(winsurf->GetCapabilities(winsurf, &scaps));
419
420 #if 0
421 if (scaps & DSCAPS_DOUBLE)
422 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
423 else if (scaps & DSCAPS_TRIPLE)
424 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
425 else
426 renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
427 #endif
428
429 DirectFB_SetSupportedPixelFormats(&renderer->info);
430
431 #if 0
432 /* Set up a palette watch on the display palette */
433 if (display-> palette) {
434 SDL_AddPaletteWatch(display->palette, DisplayPaletteChanged, data);
435 }
436 #endif
437
438 return renderer;
439
440 error:
441 SDL_DFB_FREE(renderer);
442 SDL_DFB_FREE(data);
443 return NULL;
444 }
445
446 static void
DirectFB_ActivateRenderer(SDL_Renderer * renderer)447 DirectFB_ActivateRenderer(SDL_Renderer * renderer)
448 {
449 SDL_DFB_RENDERERDATA(renderer);
450 SDL_Window *window = renderer->window;
451 SDL_DFB_WINDOWDATA(window);
452
453 if (renddata->size_changed /* || windata->wm_needs_redraw */) {
454 renddata->size_changed = SDL_FALSE;
455 }
456 }
457
458
459 static int
DirectFB_AcquireVidLayer(SDL_Renderer * renderer,SDL_Texture * texture)460 DirectFB_AcquireVidLayer(SDL_Renderer * renderer, SDL_Texture * texture)
461 {
462 SDL_Window *window = renderer->window;
463 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
464 SDL_DFB_DEVICEDATA(display->device);
465 DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
466 DirectFB_TextureData *data = texture->driverdata;
467 DFBDisplayLayerConfig layconf;
468 DFBResult ret;
469
470 if (devdata->use_yuv_direct && (dispdata->vidID >= 0)
471 && (!dispdata->vidIDinuse)
472 && SDL_ISPIXELFORMAT_FOURCC(data->format)) {
473 layconf.flags =
474 DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
475 DLCONF_SURFACE_CAPS;
476 layconf.width = texture->w;
477 layconf.height = texture->h;
478 layconf.pixelformat = DirectFB_SDLToDFBPixelFormat(data->format);
479 layconf.surface_caps = DSCAPS_VIDEOONLY | DSCAPS_DOUBLE;
480
481 SDL_DFB_CHECKERR(devdata->dfb->GetDisplayLayer(devdata->dfb,
482 dispdata->vidID,
483 &dispdata->vidlayer));
484 SDL_DFB_CHECKERR(dispdata->
485 vidlayer->SetCooperativeLevel(dispdata->vidlayer,
486 DLSCL_EXCLUSIVE));
487
488 if (devdata->use_yuv_underlays) {
489 ret = dispdata->vidlayer->SetLevel(dispdata->vidlayer, -1);
490 if (ret != DFB_OK)
491 SDL_DFB_DEBUG("Underlay Setlevel not supported\n");
492 }
493 SDL_DFB_CHECKERR(dispdata->
494 vidlayer->SetConfiguration(dispdata->vidlayer,
495 &layconf));
496 SDL_DFB_CHECKERR(dispdata->
497 vidlayer->GetSurface(dispdata->vidlayer,
498 &data->surface));
499 dispdata->vidIDinuse = 1;
500 data->display = display;
501 return 0;
502 }
503 return 1;
504 error:
505 if (dispdata->vidlayer) {
506 SDL_DFB_RELEASE(data->surface);
507 SDL_DFB_CHECKERR(dispdata->
508 vidlayer->SetCooperativeLevel(dispdata->vidlayer,
509 DLSCL_ADMINISTRATIVE));
510 SDL_DFB_RELEASE(dispdata->vidlayer);
511 }
512 return 1;
513 }
514
515 static int
DirectFB_CreateTexture(SDL_Renderer * renderer,SDL_Texture * texture)516 DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
517 {
518 SDL_Window *window = renderer->window;
519 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
520 SDL_DFB_DEVICEDATA(display->device);
521 DirectFB_TextureData *data;
522 DFBSurfaceDescription dsc;
523 DFBSurfacePixelFormat pixelformat;
524
525 DirectFB_ActivateRenderer(renderer);
526
527 SDL_DFB_ALLOC_CLEAR(data, sizeof(*data));
528 texture->driverdata = data;
529
530 /* find the right pixelformat */
531 pixelformat = DirectFB_SDLToDFBPixelFormat(texture->format);
532 if (pixelformat == DSPF_UNKNOWN) {
533 SDL_SetError("Unknown pixel format %d\n", data->format);
534 goto error;
535 }
536
537 data->format = texture->format;
538 data->pitch = texture->w * DFB_BYTES_PER_PIXEL(pixelformat);
539
540 if (DirectFB_AcquireVidLayer(renderer, texture) != 0) {
541 /* fill surface description */
542 dsc.flags =
543 DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
544 dsc.width = texture->w;
545 dsc.height = texture->h;
546 if(texture->format == SDL_PIXELFORMAT_YV12 ||
547 texture->format == SDL_PIXELFORMAT_IYUV) {
548 /* dfb has problems with odd sizes -make them even internally */
549 dsc.width += (dsc.width % 2);
550 dsc.height += (dsc.height % 2);
551 }
552 /* <1.2 Never use DSCAPS_VIDEOONLY here. It kills performance
553 * No DSCAPS_SYSTEMONLY either - let dfb decide
554 * 1.2: DSCAPS_SYSTEMONLY boosts performance by factor ~8
555 * Depends on other settings as well. Let dfb decide.
556 */
557 dsc.caps = DSCAPS_PREMULTIPLIED;
558 #if 0
559 if (texture->access == SDL_TEXTUREACCESS_STREAMING)
560 dsc.caps |= DSCAPS_SYSTEMONLY;
561 else
562 dsc.caps |= DSCAPS_VIDEOONLY;
563 #endif
564
565 dsc.pixelformat = pixelformat;
566 data->pixels = NULL;
567
568 /* Create the surface */
569 SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
570 &data->surface));
571 if (SDL_ISPIXELFORMAT_INDEXED(data->format)
572 && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
573 #if 1
574 SDL_DFB_CHECKERR(data->surface->GetPalette(data->surface, &data->palette));
575 #else
576 /* DFB has issues with blitting LUT8 surfaces.
577 * Creating a new palette does not help.
578 */
579 DFBPaletteDescription pal_desc;
580 pal_desc.flags = DPDESC_SIZE; /* | DPDESC_ENTRIES */
581 pal_desc.size = 256;
582 SDL_DFB_CHECKERR(devdata->dfb->CreatePalette(devdata->dfb, &pal_desc,&data->palette));
583 SDL_DFB_CHECKERR(data->surface->SetPalette(data->surface, data->palette));
584 #endif
585 }
586
587 }
588 #if (DFB_VERSION_ATLEAST(1,2,0))
589 data->render_options = DSRO_NONE;
590 #endif
591 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
592 /* 3 plane YUVs return 1 bpp, but we need more space for other planes */
593 if(texture->format == SDL_PIXELFORMAT_YV12 ||
594 texture->format == SDL_PIXELFORMAT_IYUV) {
595 SDL_DFB_ALLOC_CLEAR(data->pixels, (texture->h * data->pitch + ((texture->h + texture->h % 2) * (data->pitch + data->pitch % 2) * 2) / 4));
596 } else {
597 SDL_DFB_ALLOC_CLEAR(data->pixels, texture->h * data->pitch);
598 }
599 }
600
601 return 0;
602
603 error:
604 SDL_DFB_RELEASE(data->palette);
605 SDL_DFB_RELEASE(data->surface);
606 SDL_DFB_FREE(texture->driverdata);
607 return -1;
608 }
609
610 static int
DirectFB_QueryTexturePixels(SDL_Renderer * renderer,SDL_Texture * texture,void ** pixels,int * pitch)611 DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
612 SDL_Texture * texture, void **pixels, int *pitch)
613 {
614 DirectFB_TextureData *texturedata =
615 (DirectFB_TextureData *) texture->driverdata;
616
617 if (texturedata->display) {
618 return -1;
619 } else {
620 *pixels = texturedata->pixels;
621 *pitch = texturedata->pitch;
622 }
623 return 0;
624 }
625
626 static int
DirectFB_SetTexturePalette(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Color * colors,int firstcolor,int ncolors)627 DirectFB_SetTexturePalette(SDL_Renderer * renderer,
628 SDL_Texture * texture,
629 const SDL_Color * colors, int firstcolor,
630 int ncolors)
631 {
632 DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
633 if (SDL_ISPIXELFORMAT_INDEXED(data->format)
634 && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
635 DFBColor entries[256];
636 int i;
637
638 if (ncolors > 256)
639 ncolors = 256;
640
641 for (i = 0; i < ncolors; ++i) {
642 entries[i].r = colors[i].r;
643 entries[i].g = colors[i].g;
644 entries[i].b = colors[i].b;
645 entries[i].a = 0xff;
646 }
647 SDL_DFB_CHECKERR(data->
648 palette->SetEntries(data->palette, entries, ncolors, firstcolor));
649 return 0;
650 } else {
651 return SDL_SetError("YUV textures don't have a palette");
652 }
653 error:
654 return -1;
655 }
656
657 static int
DirectFB_GetTexturePalette(SDL_Renderer * renderer,SDL_Texture * texture,SDL_Color * colors,int firstcolor,int ncolors)658 DirectFB_GetTexturePalette(SDL_Renderer * renderer,
659 SDL_Texture * texture, SDL_Color * colors,
660 int firstcolor, int ncolors)
661 {
662 DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
663
664 if (SDL_ISPIXELFORMAT_INDEXED(data->format)
665 && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
666 DFBColor entries[256];
667 int i;
668
669 SDL_DFB_CHECKERR(data->
670 palette->GetEntries(data->palette, entries, ncolors,
671 firstcolor));
672
673 for (i = 0; i < ncolors; ++i) {
674 colors[i].r = entries[i].r;
675 colors[i].g = entries[i].g;
676 colors[i].b = entries[i].b;
677 colors[i].a = SDL_ALPHA_OPAQUE;
678 }
679 return 0;
680 } else {
681 return SDL_SetError("YUV textures don't have a palette");
682 }
683 error:
684 return -1;
685 }
686
687 static int
DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer,SDL_Texture * texture)688 DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
689 {
690 return 0;
691 }
692
693 static int
DirectFB_SetTextureColorMod(SDL_Renderer * renderer,SDL_Texture * texture)694 DirectFB_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
695 {
696 return 0;
697 }
698
699 static int
DirectFB_SetTextureBlendMode(SDL_Renderer * renderer,SDL_Texture * texture)700 DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
701 {
702 switch (texture->blendMode) {
703 case SDL_BLENDMODE_NONE:
704 /* case SDL_BLENDMODE_MASK: */
705 case SDL_BLENDMODE_BLEND:
706 case SDL_BLENDMODE_ADD:
707 case SDL_BLENDMODE_MOD:
708 return 0;
709 default:
710 texture->blendMode = SDL_BLENDMODE_NONE;
711 return SDL_Unsupported();
712 }
713 }
714
715 static int
DirectFB_SetDrawBlendMode(SDL_Renderer * renderer)716 DirectFB_SetDrawBlendMode(SDL_Renderer * renderer)
717 {
718 switch (renderer->blendMode) {
719 case SDL_BLENDMODE_NONE:
720 /* case SDL_BLENDMODE_MASK: */
721 case SDL_BLENDMODE_BLEND:
722 case SDL_BLENDMODE_ADD:
723 case SDL_BLENDMODE_MOD:
724 return 0;
725 default:
726 renderer->blendMode = SDL_BLENDMODE_NONE;
727 return SDL_Unsupported();
728 }
729 }
730
731 #if 0
732 static int
733 DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
734 {
735 #if (DFB_VERSION_ATLEAST(1,2,0))
736
737 DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
738
739 switch (texture->scaleMode) {
740 case SDL_SCALEMODE_NONE:
741 case SDL_SCALEMODE_FAST:
742 data->render_options = DSRO_NONE;
743 break;
744 case SDL_SCALEMODE_SLOW:
745 data->render_options = DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE;
746 break;
747 case SDL_SCALEMODE_BEST:
748 data->render_options =
749 DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE | DSRO_ANTIALIAS;
750 break;
751 default:
752 data->render_options = DSRO_NONE;
753 texture->scaleMode = SDL_SCALEMODE_NONE;
754 return SDL_Unsupported();
755 }
756 #endif
757 return 0;
758 }
759 #endif
760
761 static int
DirectFB_UpdateTexture(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * rect,const void * pixels,int pitch)762 DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
763 const SDL_Rect * rect, const void *pixels, int pitch)
764 {
765 DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
766 Uint8 *dpixels;
767 int dpitch;
768 Uint8 *src, *dst;
769 int row;
770 size_t length;
771 int bpp = DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format));
772 /* FIXME: SDL_BYTESPERPIXEL(texture->format) broken for yuv yv12 3 planes */
773
774 DirectFB_ActivateRenderer(renderer);
775
776 if ((texture->format == SDL_PIXELFORMAT_YV12) ||
777 (texture->format == SDL_PIXELFORMAT_IYUV)) {
778 bpp = 1;
779 }
780
781 SDL_DFB_CHECKERR(data->surface->Lock(data->surface,
782 DSLF_WRITE | DSLF_READ,
783 ((void **) &dpixels), &dpitch));
784 src = (Uint8 *) pixels;
785 dst = (Uint8 *) dpixels + rect->y * dpitch + rect->x * bpp;
786 length = rect->w * bpp;
787 for (row = 0; row < rect->h; ++row) {
788 SDL_memcpy(dst, src, length);
789 src += pitch;
790 dst += dpitch;
791 }
792 /* copy other planes for 3 plane formats */
793 if ((texture->format == SDL_PIXELFORMAT_YV12) ||
794 (texture->format == SDL_PIXELFORMAT_IYUV)) {
795 src = (Uint8 *) pixels + texture->h * pitch;
796 dst = (Uint8 *) dpixels + texture->h * dpitch + rect->y * dpitch / 4 + rect->x * bpp / 2;
797 for (row = 0; row < rect->h / 2 + (rect->h & 1); ++row) {
798 SDL_memcpy(dst, src, length / 2);
799 src += pitch / 2;
800 dst += dpitch / 2;
801 }
802 src = (Uint8 *) pixels + texture->h * pitch + texture->h * pitch / 4;
803 dst = (Uint8 *) dpixels + texture->h * dpitch + texture->h * dpitch / 4 + rect->y * dpitch / 4 + rect->x * bpp / 2;
804 for (row = 0; row < rect->h / 2 + (rect->h & 1); ++row) {
805 SDL_memcpy(dst, src, length / 2);
806 src += pitch / 2;
807 dst += dpitch / 2;
808 }
809 }
810 SDL_DFB_CHECKERR(data->surface->Unlock(data->surface));
811 data->isDirty = 0;
812 return 0;
813 error:
814 return 1;
815
816 }
817
818 static int
DirectFB_LockTexture(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * rect,void ** pixels,int * pitch)819 DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
820 const SDL_Rect * rect, void **pixels, int *pitch)
821 {
822 DirectFB_TextureData *texturedata =
823 (DirectFB_TextureData *) texture->driverdata;
824
825 DirectFB_ActivateRenderer(renderer);
826
827 #if 0
828 if (markDirty) {
829 SDL_AddDirtyRect(&texturedata->dirty, rect);
830 }
831 #endif
832
833 if (texturedata->display) {
834 void *fdata;
835 int fpitch;
836
837 SDL_DFB_CHECKERR(texturedata->surface->Lock(texturedata->surface,
838 DSLF_WRITE | DSLF_READ,
839 &fdata, &fpitch));
840 *pitch = fpitch;
841 *pixels = fdata;
842 } else {
843 *pixels =
844 (void *) ((Uint8 *) texturedata->pixels +
845 rect->y * texturedata->pitch +
846 rect->x * DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format)));
847 *pitch = texturedata->pitch;
848 texturedata->isDirty = 1;
849 }
850 return 0;
851
852 error:
853 return -1;
854 }
855
856 static void
DirectFB_UnlockTexture(SDL_Renderer * renderer,SDL_Texture * texture)857 DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
858 {
859 DirectFB_TextureData *texturedata =
860 (DirectFB_TextureData *) texture->driverdata;
861
862 DirectFB_ActivateRenderer(renderer);
863
864 if (texturedata->display) {
865 SDL_DFB_CHECK(texturedata->surface->Unlock(texturedata->surface));
866 texturedata->pixels = NULL;
867 }
868 }
869
870 #if 0
871 static void
872 DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
873 int numrects, const SDL_Rect * rects)
874 {
875 DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
876 int i;
877
878 for (i = 0; i < numrects; ++i) {
879 SDL_AddDirtyRect(&data->dirty, &rects[i]);
880 }
881 }
882 #endif
883
DirectFB_SetRenderTarget(SDL_Renderer * renderer,SDL_Texture * texture)884 static int DirectFB_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
885 {
886 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
887 DirectFB_TextureData *tex_data = NULL;
888
889 DirectFB_ActivateRenderer(renderer);
890 if (texture) {
891 tex_data = (DirectFB_TextureData *) texture->driverdata;
892 data->target = tex_data->surface;
893 } else {
894 data->target = get_dfb_surface(data->window);
895 }
896 data->lastBlendMode = 0;
897 return 0;
898 }
899
900
901 static int
PrepareDraw(SDL_Renderer * renderer)902 PrepareDraw(SDL_Renderer * renderer)
903 {
904 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
905 IDirectFBSurface *destsurf = data->target;
906
907 Uint8 r, g, b, a;
908
909 r = renderer->r;
910 g = renderer->g;
911 b = renderer->b;
912 a = renderer->a;
913
914 SetBlendMode(data, renderer->blendMode, NULL);
915 SDL_DFB_CHECKERR(destsurf->SetDrawingFlags(destsurf, data->drawFlags));
916
917 switch (renderer->blendMode) {
918 case SDL_BLENDMODE_NONE:
919 /* case SDL_BLENDMODE_MASK: */
920 case SDL_BLENDMODE_BLEND:
921 break;
922 case SDL_BLENDMODE_ADD:
923 case SDL_BLENDMODE_MOD:
924 r = ((int) r * (int) a) / 255;
925 g = ((int) g * (int) a) / 255;
926 b = ((int) b * (int) a) / 255;
927 a = 255;
928 break;
929 }
930
931 SDL_DFB_CHECKERR(destsurf->SetColor(destsurf, r, g, b, a));
932 return 0;
933 error:
934 return -1;
935 }
936
DirectFB_RenderDrawPoints(SDL_Renderer * renderer,const SDL_FPoint * points,int count)937 static int DirectFB_RenderDrawPoints(SDL_Renderer * renderer,
938 const SDL_FPoint * points, int count)
939 {
940 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
941 IDirectFBSurface *destsurf = data->target;
942 DFBRegion clip_region;
943 int i;
944
945 DirectFB_ActivateRenderer(renderer);
946
947 PrepareDraw(renderer);
948 destsurf->GetClip(destsurf, &clip_region);
949 for (i=0; i < count; i++) {
950 int x = points[i].x + clip_region.x1;
951 int y = points[i].y + clip_region.y1;
952 SDL_DFB_CHECKERR(destsurf->DrawLine(destsurf, x, y, x, y));
953 }
954 return 0;
955 error:
956 return -1;
957 }
958
DirectFB_RenderDrawLines(SDL_Renderer * renderer,const SDL_FPoint * points,int count)959 static int DirectFB_RenderDrawLines(SDL_Renderer * renderer,
960 const SDL_FPoint * points, int count)
961 {
962 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
963 IDirectFBSurface *destsurf = data->target;
964 DFBRegion clip_region;
965 int i;
966
967 DirectFB_ActivateRenderer(renderer);
968
969 PrepareDraw(renderer);
970 /* Use antialiasing when available */
971 #if (DFB_VERSION_ATLEAST(1,2,0))
972 SDL_DFB_CHECKERR(destsurf->SetRenderOptions(destsurf, DSRO_ANTIALIAS));
973 #endif
974
975 destsurf->GetClip(destsurf, &clip_region);
976 for (i=0; i < count - 1; i++) {
977 int x1 = points[i].x + clip_region.x1;
978 int y1 = points[i].y + clip_region.y1;
979 int x2 = points[i + 1].x + clip_region.x1;
980 int y2 = points[i + 1].y + clip_region.y1;
981 SDL_DFB_CHECKERR(destsurf->DrawLine(destsurf, x1, y1, x2, y2));
982 }
983
984 return 0;
985 error:
986 return -1;
987 }
988
989 static int
DirectFB_RenderDrawRects(SDL_Renderer * renderer,const SDL_Rect ** rects,int count)990 DirectFB_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
991 {
992 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
993 IDirectFBSurface *destsurf = data->target;
994 DFBRegion clip_region;
995 int i;
996
997 DirectFB_ActivateRenderer(renderer);
998
999 PrepareDraw(renderer);
1000
1001 destsurf->GetClip(destsurf, &clip_region);
1002 for (i=0; i<count; i++) {
1003 SDL_Rect dst = {rects[i]->x, rects[i]->y, rects[i]->w, rects[i]->h};
1004 dst.x += clip_region.x1;
1005 dst.y += clip_region.y1;
1006 SDL_DFB_CHECKERR(destsurf->DrawRectangle(destsurf, dst.x, dst.y,
1007 dst.w, dst.h));
1008 }
1009
1010 return 0;
1011 error:
1012 return -1;
1013 }
1014
1015 static int
DirectFB_RenderFillRects(SDL_Renderer * renderer,const SDL_FRect * rects,int count)1016 DirectFB_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
1017 {
1018 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
1019 IDirectFBSurface *destsurf = data->target;
1020 DFBRegion clip_region;
1021 int i;
1022
1023 DirectFB_ActivateRenderer(renderer);
1024
1025 PrepareDraw(renderer);
1026
1027 destsurf->GetClip(destsurf, &clip_region);
1028 for (i=0; i<count; i++) {
1029 SDL_Rect dst = {rects[i].x, rects[i].y, rects[i].w, rects[i].h};
1030 dst.x += clip_region.x1;
1031 dst.y += clip_region.y1;
1032 SDL_DFB_CHECKERR(destsurf->FillRectangle(destsurf, dst.x, dst.y,
1033 dst.w, dst.h));
1034 }
1035
1036 return 0;
1037 error:
1038 return -1;
1039 }
1040
1041 static int
DirectFB_RenderCopy(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * srcrect,const SDL_FRect * dstrect)1042 DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1043 const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1044 {
1045 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
1046 IDirectFBSurface *destsurf = data->target;
1047 DirectFB_TextureData *texturedata =
1048 (DirectFB_TextureData *) texture->driverdata;
1049 Uint8 alpha, r, g, b;
1050 DFBRegion clip_region;
1051 DFBRectangle sr, dr;
1052
1053 DirectFB_ActivateRenderer(renderer);
1054
1055 SDLtoDFBRect(srcrect, &sr);
1056 SDLtoDFBRect_Float(dstrect, &dr);
1057
1058 destsurf->GetClip(destsurf, &clip_region);
1059 dr.x += clip_region.x1;
1060 dr.y += clip_region.y1;
1061
1062 if (texturedata->display) {
1063 int px, py;
1064 SDL_Window *window = renderer->window;
1065 IDirectFBWindow *dfbwin = get_dfb_window(window);
1066 SDL_DFB_WINDOWDATA(window);
1067 SDL_VideoDisplay *display = texturedata->display;
1068 DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
1069
1070 SDL_DFB_CHECKERR(dispdata->
1071 vidlayer->SetSourceRectangle(dispdata->vidlayer,
1072 sr.x, sr.y, sr.w, sr.h));
1073 dfbwin->GetPosition(dfbwin, &px, &py);
1074 px += windata->client.x;
1075 py += windata->client.y;
1076 SDL_DFB_CHECKERR(dispdata->
1077 vidlayer->SetScreenRectangle(dispdata->vidlayer,
1078 px + dr.x,
1079 py + dr.y,
1080 dr.w,
1081 dr.h));
1082 } else {
1083 DFBSurfaceBlittingFlags flags = 0;
1084
1085 #if 0
1086 if (texturedata->dirty.list) {
1087 SDL_DirtyRect *dirty;
1088 void *pixels;
1089 int bpp = DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format));
1090 int pitch = texturedata->pitch;
1091
1092 for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
1093 SDL_Rect *rect = &dirty->rect;
1094 pixels =
1095 (void *) ((Uint8 *) texturedata->pixels +
1096 rect->y * pitch + rect->x * bpp);
1097 DirectFB_UpdateTexture(renderer, texture, rect,
1098 pixels,
1099 texturedata->pitch);
1100 }
1101 SDL_ClearDirtyRects(&texturedata->dirty);
1102 }
1103 #endif
1104 if (texturedata->isDirty)
1105 {
1106 SDL_Rect rect;
1107
1108 rect.x = 0;
1109 rect.y = 0;
1110 rect.w = texture->w;
1111 rect.h = texture->h;
1112
1113 DirectFB_UpdateTexture(renderer, texture, &rect, texturedata->pixels, texturedata->pitch);
1114 }
1115
1116 alpha = r = g = b = 0xff;
1117 if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA){
1118 alpha = texture->a;
1119 flags |= DSBLIT_BLEND_COLORALPHA;
1120 }
1121
1122 if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
1123 r = texture->r;
1124 g = texture->g;
1125 b = texture->b;
1126 flags |= DSBLIT_COLORIZE;
1127 }
1128 SDL_DFB_CHECKERR(destsurf->
1129 SetColor(destsurf, r, g, b, alpha));
1130
1131 /* ???? flags |= DSBLIT_SRC_PREMULTCOLOR; */
1132
1133 SetBlendMode(data, texture->blendMode, texturedata);
1134
1135 SDL_DFB_CHECKERR(destsurf->SetBlittingFlags(destsurf,
1136 data->blitFlags | flags));
1137
1138 #if (DFB_VERSION_ATLEAST(1,2,0))
1139 SDL_DFB_CHECKERR(destsurf->SetRenderOptions(destsurf,
1140 texturedata->
1141 render_options));
1142 #endif
1143
1144 if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
1145 SDL_DFB_CHECKERR(destsurf->Blit(destsurf,
1146 texturedata->surface,
1147 &sr, dr.x, dr.y));
1148 } else {
1149 SDL_DFB_CHECKERR(destsurf->StretchBlit(destsurf,
1150 texturedata->surface,
1151 &sr, &dr));
1152 }
1153 }
1154 return 0;
1155 error:
1156 return -1;
1157 }
1158
1159 static void
DirectFB_RenderPresent(SDL_Renderer * renderer)1160 DirectFB_RenderPresent(SDL_Renderer * renderer)
1161 {
1162 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
1163 SDL_Window *window = renderer->window;
1164 SDL_DFB_WINDOWDATA(window);
1165 SDL_ShapeData *shape_data = (window->shaper ? window->shaper->driverdata : NULL);
1166
1167 DirectFB_ActivateRenderer(renderer);
1168
1169 if (shape_data && shape_data->surface) {
1170 /* saturate the window surface alpha channel */
1171 SDL_DFB_CHECK(windata->window_surface->SetSrcBlendFunction(windata->window_surface, DSBF_ONE));
1172 SDL_DFB_CHECK(windata->window_surface->SetDstBlendFunction(windata->window_surface, DSBF_ONE));
1173 SDL_DFB_CHECK(windata->window_surface->SetDrawingFlags(windata->window_surface, DSDRAW_BLEND));
1174 SDL_DFB_CHECK(windata->window_surface->SetColor(windata->window_surface, 0, 0, 0, 0xff));
1175 SDL_DFB_CHECK(windata->window_surface->FillRectangle(windata->window_surface, 0,0, windata->size.w, windata->size.h));
1176
1177 /* blit the mask */
1178 SDL_DFB_CHECK(windata->surface->SetSrcBlendFunction(windata->surface, DSBF_DESTCOLOR));
1179 SDL_DFB_CHECK(windata->surface->SetDstBlendFunction(windata->surface, DSBF_ZERO));
1180 SDL_DFB_CHECK(windata->surface->SetBlittingFlags(windata->surface, DSBLIT_BLEND_ALPHACHANNEL));
1181 #if (DFB_VERSION_ATLEAST(1,2,0))
1182 SDL_DFB_CHECK(windata->surface->SetRenderOptions(windata->surface, DSRO_NONE));
1183 #endif
1184 SDL_DFB_CHECK(windata->surface->Blit(windata->surface, shape_data->surface, NULL, 0, 0));
1185 }
1186
1187 /* Send the data to the display */
1188 SDL_DFB_CHECK(windata->window_surface->Flip(windata->window_surface, NULL,
1189 data->flipflags));
1190 }
1191
1192 static void
DirectFB_DestroyTexture(SDL_Renderer * renderer,SDL_Texture * texture)1193 DirectFB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1194 {
1195 DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
1196
1197 DirectFB_ActivateRenderer(renderer);
1198
1199 if (!data) {
1200 return;
1201 }
1202 SDL_DFB_RELEASE(data->palette);
1203 SDL_DFB_RELEASE(data->surface);
1204 if (data->display) {
1205 DFB_DisplayData *dispdata =
1206 (DFB_DisplayData *) data->display->driverdata;
1207 dispdata->vidIDinuse = 0;
1208 /* FIXME: Shouldn't we reset the cooperative level */
1209 SDL_DFB_CHECK(dispdata->vidlayer->SetCooperativeLevel(dispdata->vidlayer,
1210 DLSCL_ADMINISTRATIVE));
1211 SDL_DFB_RELEASE(dispdata->vidlayer);
1212 }
1213 SDL_DFB_FREE(data->pixels);
1214 SDL_free(data);
1215 texture->driverdata = NULL;
1216 }
1217
1218 static void
DirectFB_DestroyRenderer(SDL_Renderer * renderer)1219 DirectFB_DestroyRenderer(SDL_Renderer * renderer)
1220 {
1221 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
1222 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(data->window);
1223 #if 0
1224 if (display->palette) {
1225 SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged, data);
1226 }
1227 #endif
1228
1229 SDL_free(data);
1230 SDL_free(renderer);
1231 }
1232
1233 static int
DirectFB_UpdateViewport(SDL_Renderer * renderer)1234 DirectFB_UpdateViewport(SDL_Renderer * renderer)
1235 {
1236 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
1237 IDirectFBSurface *winsurf = data->target;
1238 DFBRegion dreg;
1239
1240 dreg.x1 = renderer->viewport.x;
1241 dreg.y1 = renderer->viewport.y;
1242 dreg.x2 = dreg.x1 + renderer->viewport.w - 1;
1243 dreg.y2 = dreg.y1 + renderer->viewport.h - 1;
1244
1245 winsurf->SetClip(winsurf, &dreg);
1246 return 0;
1247 }
1248
1249 static int
DirectFB_UpdateClipRect(SDL_Renderer * renderer)1250 DirectFB_UpdateClipRect(SDL_Renderer * renderer)
1251 {
1252 const SDL_Rect *rect = &renderer->clip_rect;
1253 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
1254 IDirectFBSurface *destsurf = get_dfb_surface(data->window);
1255 DFBRegion region;
1256
1257 if (!SDL_RectEmpty(rect)) {
1258 region.x1 = rect->x;
1259 region.x2 = rect->x + rect->w;
1260 region.y1 = rect->y;
1261 region.y2 = rect->y + rect->h;
1262 SDL_DFB_CHECKERR(destsurf->SetClip(destsurf, ®ion));
1263 } else {
1264 SDL_DFB_CHECKERR(destsurf->SetClip(destsurf, NULL));
1265 }
1266 return 0;
1267 error:
1268 return -1;
1269 }
1270
1271 static int
DirectFB_RenderReadPixels(SDL_Renderer * renderer,const SDL_Rect * rect,Uint32 format,void * pixels,int pitch)1272 DirectFB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1273 Uint32 format, void * pixels, int pitch)
1274 {
1275 Uint32 sdl_format;
1276 void * laypixels;
1277 int laypitch;
1278 DFBSurfacePixelFormat dfb_format;
1279 DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
1280 IDirectFBSurface *winsurf = data->target;
1281
1282 DirectFB_ActivateRenderer(renderer);
1283
1284 winsurf->GetPixelFormat(winsurf, &dfb_format);
1285 sdl_format = DirectFB_DFBToSDLPixelFormat(dfb_format);
1286 winsurf->Lock(winsurf, DSLF_READ, (void **) &laypixels, &laypitch);
1287
1288 laypixels += (rect->y * laypitch + rect->x * SDL_BYTESPERPIXEL(sdl_format) );
1289 SDL_ConvertPixels(rect->w, rect->h,
1290 sdl_format, laypixels, laypitch,
1291 format, pixels, pitch);
1292
1293 winsurf->Unlock(winsurf);
1294
1295 return 0;
1296 }
1297
1298 #if 0
1299 static int
1300 DirectFB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1301 Uint32 format, const void * pixels, int pitch)
1302 {
1303 SDL_Window *window = renderer->window;
1304 SDL_DFB_WINDOWDATA(window);
1305 Uint32 sdl_format;
1306 void * laypixels;
1307 int laypitch;
1308 DFBSurfacePixelFormat dfb_format;
1309
1310 SDL_DFB_CHECK(windata->surface->GetPixelFormat(windata->surface, &dfb_format));
1311 sdl_format = DirectFB_DFBToSDLPixelFormat(dfb_format);
1312
1313 SDL_DFB_CHECK(windata->surface->Lock(windata->surface, DSLF_WRITE, (void **) &laypixels, &laypitch));
1314
1315 laypixels += (rect->y * laypitch + rect->x * SDL_BYTESPERPIXEL(sdl_format) );
1316 SDL_ConvertPixels(rect->w, rect->h,
1317 format, pixels, pitch,
1318 sdl_format, laypixels, laypitch);
1319
1320 SDL_DFB_CHECK(windata->surface->Unlock(windata->surface));
1321
1322 return 0;
1323 }
1324 #endif
1325
1326 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */
1327
1328 /* vi: set ts=4 sw=4 expandtab: */
1329