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, &region));
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