src/video/directfb/SDL_DirectFB_render.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 26 Nov 2008 21:59:35 +0000
changeset 2791 8133d1d278da
parent 2737 140a7edcf2bd
child 2859 99210400e8b9
permissions -rw-r--r--
Date: Wed, 26 Nov 2008 19:50:31 +0100
From: Couriersud
Subject: LPGL and closed-source license / Re: [Bug 607] Texture palette not up

Permission granted to release code under both LPGL and closed-source
commercial license.

Please find attached a minor patch fixing vsync handling in the directfb
driver and containing a small update to README.directfb
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21     
    22     SDL1.3 implementation by couriersud@arcor.de
    23     
    24 */
    25 #include "SDL_config.h"
    26 
    27 #include "SDL_DirectFB_video.h"
    28 #include "SDL_DirectFB_render.h"
    29 #include "../SDL_rect_c.h"
    30 #include "../SDL_yuv_sw_c.h"
    31 
    32 /* the following is not yet tested ... */
    33 #define USE_DISPLAY_PALETTE			(0)
    34 
    35 /* GDI renderer implementation */
    36 
    37 static SDL_Renderer *DirectFB_CreateRenderer(SDL_Window * window,
    38                                              Uint32 flags);
    39 static int DirectFB_DisplayModeChanged(SDL_Renderer * renderer);
    40 static int DirectFB_ActivateRenderer(SDL_Renderer * renderer);
    41 static int DirectFB_CreateTexture(SDL_Renderer * renderer,
    42                                   SDL_Texture * texture);
    43 static int DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
    44                                        SDL_Texture * texture, void **pixels,
    45                                        int *pitch);
    46 static int DirectFB_SetTexturePalette(SDL_Renderer * renderer,
    47                                       SDL_Texture * texture,
    48                                       const SDL_Color * colors,
    49                                       int firstcolor, int ncolors);
    50 static int DirectFB_GetTexturePalette(SDL_Renderer * renderer,
    51                                       SDL_Texture * texture,
    52                                       SDL_Color * colors, int firstcolor,
    53                                       int ncolors);
    54 static int DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer,
    55                                        SDL_Texture * texture);
    56 static int DirectFB_SetTextureColorMod(SDL_Renderer * renderer,
    57                                        SDL_Texture * texture);
    58 static int DirectFB_SetTextureBlendMode(SDL_Renderer * renderer,
    59                                         SDL_Texture * texture);
    60 static int DirectFB_SetTextureScaleMode(SDL_Renderer * renderer,
    61                                         SDL_Texture * texture);
    62 static int DirectFB_UpdateTexture(SDL_Renderer * renderer,
    63                                   SDL_Texture * texture,
    64                                   const SDL_Rect * rect, const void *pixels,
    65                                   int pitch);
    66 static int DirectFB_LockTexture(SDL_Renderer * renderer,
    67                                 SDL_Texture * texture, const SDL_Rect * rect,
    68                                 int markDirty, void **pixels, int *pitch);
    69 static void DirectFB_UnlockTexture(SDL_Renderer * renderer,
    70                                    SDL_Texture * texture);
    71 static void DirectFB_DirtyTexture(SDL_Renderer * renderer,
    72                                   SDL_Texture * texture, int numrects,
    73                                   const SDL_Rect * rects);
    74 static int DirectFB_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g,
    75                                Uint8 b, Uint8 a, const SDL_Rect * rect);
    76 static int DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    77                                const SDL_Rect * srcrect,
    78                                const SDL_Rect * dstrect);
    79 static void DirectFB_RenderPresent(SDL_Renderer * renderer);
    80 static void DirectFB_DestroyTexture(SDL_Renderer * renderer,
    81                                     SDL_Texture * texture);
    82 static void DirectFB_DestroyRenderer(SDL_Renderer * renderer);
    83 
    84 SDL_RenderDriver DirectFB_RenderDriver = {
    85     DirectFB_CreateRenderer,
    86     {
    87      "directfb",
    88      (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
    89       SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
    90       SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_PRESENTDISCARD |
    91       SDL_RENDERER_ACCELERATED),
    92      (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
    93       SDL_TEXTUREMODULATE_ALPHA),
    94      (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK |
    95       SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD |
    96       SDL_TEXTUREBLENDMODE_MOD),
    97      (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
    98       SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST),
    99      14,
   100      {
   101       SDL_PIXELFORMAT_INDEX4LSB,
   102       SDL_PIXELFORMAT_INDEX8,
   103       SDL_PIXELFORMAT_RGB332,
   104       SDL_PIXELFORMAT_RGB555,
   105       SDL_PIXELFORMAT_RGB565,
   106       SDL_PIXELFORMAT_RGB888,
   107       SDL_PIXELFORMAT_ARGB8888,
   108       SDL_PIXELFORMAT_ARGB4444,
   109       SDL_PIXELFORMAT_ARGB1555,
   110       SDL_PIXELFORMAT_RGB24,
   111       SDL_PIXELFORMAT_YV12,
   112       SDL_PIXELFORMAT_IYUV,
   113       SDL_PIXELFORMAT_YUY2,
   114       SDL_PIXELFORMAT_UYVY},
   115      0,
   116      0}
   117 };
   118 
   119 typedef struct
   120 {
   121     IDirectFBSurface *surface;
   122     DFBSurfaceFlipFlags flipflags;
   123     int isyuvdirect;
   124     int size_changed;
   125 } DirectFB_RenderData;
   126 
   127 typedef struct
   128 {
   129     IDirectFBSurface *surface;
   130     Uint32 format;
   131     void *pixels;
   132     int pitch;
   133     IDirectFBPalette *palette;
   134     SDL_VideoDisplay *display;
   135     SDL_DirtyRectList dirty;
   136 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   137     DFBSurfaceRenderOptions render_options;
   138 #endif
   139 } DirectFB_TextureData;
   140 
   141 static __inline__ void
   142 SDLtoDFBRect(const SDL_Rect * sr, DFBRectangle * dr)
   143 {
   144     dr->x = sr->x;
   145     dr->y = sr->y;
   146     dr->h = sr->h;
   147     dr->w = sr->w;
   148 }
   149 
   150 void
   151 DirectFB_AddRenderDriver(_THIS)
   152 {
   153     int i;
   154     for (i = 0; i < _this->num_displays; i++)
   155         SDL_AddRenderDriver(i, &DirectFB_RenderDriver);
   156 }
   157 
   158 static int
   159 DisplayPaletteChanged(void *userdata, SDL_Palette * palette)
   160 {
   161 #if USE_DISPLAY_PALETTE
   162     DirectFB_RenderData *data = (DirectFB_RenderData *) userdata;
   163     IDirectFBPalette *surfpal;
   164 
   165     int ret;
   166     int i;
   167     int ncolors;
   168     DFBColor entries[256];
   169 
   170     SDL_DFB_CHECKERR(data->surface->GetPalette(data->surface, &surfpal));
   171 
   172     /* FIXME: number of colors */
   173     ncolors = (palette->ncolors < 256 ? palette->ncolors : 256);
   174 
   175     for (i = 0; i < ncolors; ++i) {
   176         entries[i].r = palette->colors[i].r;
   177         entries[i].g = palette->colors[i].g;
   178         entries[i].b = palette->colors[i].b;
   179         entries[i].a = palette->colors[i].unused;
   180     }
   181     SDL_DFB_CHECKERR(surfpal->SetEntries(surfpal, entries, ncolors, 0));
   182     return 0;
   183   error:
   184 #endif
   185     return -1;
   186 }
   187 
   188 
   189 SDL_Renderer *
   190 DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags)
   191 {
   192     SDL_DFB_WINDOWDATA(window);
   193     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   194     SDL_Renderer *renderer = NULL;
   195     DirectFB_RenderData *data = NULL;
   196     DFBResult ret;
   197     DFBSurfaceCapabilities scaps;
   198     char *p;
   199 
   200     SDL_DFB_CALLOC(renderer, 1, sizeof(*renderer));
   201     SDL_DFB_CALLOC(data, 1, sizeof(*data));
   202 
   203     renderer->DisplayModeChanged = DirectFB_DisplayModeChanged;
   204     renderer->ActivateRenderer = DirectFB_ActivateRenderer;
   205     renderer->CreateTexture = DirectFB_CreateTexture;
   206     renderer->QueryTexturePixels = DirectFB_QueryTexturePixels;
   207     renderer->SetTexturePalette = DirectFB_SetTexturePalette;
   208     renderer->GetTexturePalette = DirectFB_GetTexturePalette;
   209     renderer->SetTextureAlphaMod = DirectFB_SetTextureAlphaMod;
   210     renderer->SetTextureColorMod = DirectFB_SetTextureColorMod;
   211     renderer->SetTextureBlendMode = DirectFB_SetTextureBlendMode;
   212     renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode;
   213     renderer->UpdateTexture = DirectFB_UpdateTexture;
   214     renderer->LockTexture = DirectFB_LockTexture;
   215     renderer->UnlockTexture = DirectFB_UnlockTexture;
   216     renderer->DirtyTexture = DirectFB_DirtyTexture;
   217     renderer->RenderFill = DirectFB_RenderFill;
   218     renderer->RenderCopy = DirectFB_RenderCopy;
   219     renderer->RenderPresent = DirectFB_RenderPresent;
   220     renderer->DestroyTexture = DirectFB_DestroyTexture;
   221     renderer->DestroyRenderer = DirectFB_DestroyRenderer;
   222     renderer->info = DirectFB_RenderDriver.info;
   223     renderer->window = window->id;      /* SDL window id */
   224     renderer->driverdata = data;
   225 
   226     renderer->info.flags =
   227         SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTDISCARD;
   228 
   229     data->surface = windata->surface;
   230     data->surface->AddRef(data->surface);
   231 
   232     data->flipflags = DSFLIP_PIPELINE | DSFLIP_BLIT;
   233 
   234     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   235         data->flipflags |= DSFLIP_WAITFORSYNC;
   236         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   237     } else
   238         data->flipflags |= DSFLIP_ONSYNC;
   239 
   240     SDL_DFB_CHECKERR(data->surface->GetCapabilities(data->surface, &scaps));
   241     if (scaps & DSCAPS_DOUBLE)
   242         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
   243     else if (scaps & DSCAPS_TRIPLE)
   244         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
   245     else
   246         renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
   247 
   248     data->isyuvdirect = 0;      /* default is off! */
   249     p = getenv(DFBENV_USE_YUV_DIRECT);
   250     if (p)
   251         data->isyuvdirect = atoi(p);
   252 
   253     /* Set up a palette watch on the display palette */
   254     if (display->palette) {
   255         SDL_AddPaletteWatch(display->palette, DisplayPaletteChanged, data);
   256     }
   257 
   258     return renderer;
   259 
   260   error:
   261     SDL_DFB_FREE(renderer);
   262     SDL_DFB_FREE(data);
   263     return NULL;
   264 }
   265 
   266 static DFBSurfacePixelFormat
   267 SDLToDFBPixelFormat(Uint32 format)
   268 {
   269     switch (format) {
   270     case SDL_PIXELFORMAT_INDEX4LSB:
   271         return DSPF_ALUT44;
   272     case SDL_PIXELFORMAT_INDEX8:
   273         return DSPF_LUT8;
   274     case SDL_PIXELFORMAT_RGB332:
   275         return DSPF_RGB332;
   276     case SDL_PIXELFORMAT_RGB555:
   277         return DSPF_ARGB1555;
   278     case SDL_PIXELFORMAT_ARGB4444:
   279         return DSPF_ARGB4444;
   280     case SDL_PIXELFORMAT_ARGB1555:
   281         return DSPF_ARGB1555;
   282     case SDL_PIXELFORMAT_RGB565:
   283         return DSPF_RGB16;
   284     case SDL_PIXELFORMAT_RGB24:
   285         return DSPF_RGB24;
   286     case SDL_PIXELFORMAT_RGB888:
   287         return DSPF_RGB32;
   288     case SDL_PIXELFORMAT_ARGB8888:
   289         return DSPF_ARGB;
   290     case SDL_PIXELFORMAT_YV12:
   291         return DSPF_YV12;       /* Planar mode: Y + V + U  (3 planes) */
   292     case SDL_PIXELFORMAT_IYUV:
   293         return DSPF_I420;       /* Planar mode: Y + U + V  (3 planes) */
   294     case SDL_PIXELFORMAT_YUY2:
   295         return DSPF_YUY2;       /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
   296     case SDL_PIXELFORMAT_UYVY:
   297         return DSPF_UYVY;       /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
   298     case SDL_PIXELFORMAT_YVYU:
   299         return DSPF_UNKNOWN;    /* Packed mode: Y0+V0+Y1+U0 (1 plane) */
   300     case SDL_PIXELFORMAT_INDEX1LSB:
   301         return DSPF_UNKNOWN;
   302     case SDL_PIXELFORMAT_INDEX1MSB:
   303         return DSPF_UNKNOWN;
   304     case SDL_PIXELFORMAT_INDEX4MSB:
   305         return DSPF_UNKNOWN;
   306     case SDL_PIXELFORMAT_RGB444:
   307         return DSPF_UNKNOWN;
   308     case SDL_PIXELFORMAT_BGR24:
   309         return DSPF_UNKNOWN;
   310     case SDL_PIXELFORMAT_BGR888:
   311         return DSPF_UNKNOWN;
   312     case SDL_PIXELFORMAT_RGBA8888:
   313         return DSPF_UNKNOWN;
   314     case SDL_PIXELFORMAT_ABGR8888:
   315         return DSPF_UNKNOWN;
   316     case SDL_PIXELFORMAT_BGRA8888:
   317         return DSPF_UNKNOWN;
   318     case SDL_PIXELFORMAT_ARGB2101010:
   319         return DSPF_UNKNOWN;
   320     default:
   321         return DSPF_UNKNOWN;
   322     }
   323 }
   324 
   325 static int
   326 DirectFB_ActivateRenderer(SDL_Renderer * renderer)
   327 {
   328     SDL_DFB_RENDERERDATA(renderer);
   329     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   330     SDL_DFB_WINDOWDATA(window);
   331 
   332     if (renddata->size_changed) {
   333         int cw, ch;
   334         int ret;
   335 
   336         SDL_DFB_CHECKERR(windata->surface->
   337                          GetSize(windata->surface, &cw, &ch));
   338         if (cw != window->w || ch != window->h)
   339             SDL_DFB_CHECKERR(windata->window->
   340                              ResizeSurface(windata->window, window->w,
   341                                            window->h));
   342     }
   343     return 0;
   344   error:
   345     return -1;
   346 }
   347 
   348 static int
   349 DirectFB_DisplayModeChanged(SDL_Renderer * renderer)
   350 {
   351     SDL_DFB_RENDERERDATA(renderer);
   352 
   353     renddata->size_changed = SDL_TRUE;
   354     return 0;
   355 }
   356 
   357 static int
   358 DirectFB_AcquireVidLayer(SDL_Renderer * renderer, SDL_Texture * texture)
   359 {
   360     SDL_DFB_RENDERERDATA(renderer);
   361     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   362     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   363     SDL_DFB_DEVICEDATA(display->device);
   364     DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   365     DirectFB_TextureData *data = texture->driverdata;
   366     DFBDisplayLayerConfig layconf;
   367     int ret;
   368 
   369     if (renddata->isyuvdirect && (dispdata->vidID >= 0)
   370         && (!dispdata->vidIDinuse)
   371         && SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   372         layconf.flags =
   373             DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
   374             DLCONF_SURFACE_CAPS;
   375         layconf.width = texture->w;
   376         layconf.height = texture->h;
   377         layconf.pixelformat = SDLToDFBPixelFormat(data->format);
   378         layconf.surface_caps = DSCAPS_VIDEOONLY | DSCAPS_DOUBLE;
   379 
   380         SDL_DFB_CHECKERR(devdata->dfb->
   381                          GetDisplayLayer(devdata->dfb, dispdata->vidID,
   382                                          &dispdata->vidlayer));
   383         SDL_DFB_CHECKERR(dispdata->vidlayer->
   384                          SetCooperativeLevel(dispdata->vidlayer,
   385                                              DLSCL_EXCLUSIVE));
   386 
   387         if (devdata->use_yuv_underlays) {
   388             ret = dispdata->vidlayer->SetLevel(dispdata->vidlayer, -1);
   389             if (ret != DFB_OK)
   390                 SDL_DFB_DEBUG("Underlay Setlevel not supported\n");
   391         }
   392         SDL_DFB_CHECKERR(dispdata->vidlayer->
   393                          SetConfiguration(dispdata->vidlayer, &layconf));
   394         SDL_DFB_CHECKERR(dispdata->vidlayer->
   395                          GetSurface(dispdata->vidlayer, &data->surface));
   396         dispdata->vidIDinuse = 1;
   397         data->display = display;
   398         return 0;
   399     }
   400     return 1;
   401   error:
   402     if (dispdata->vidlayer) {
   403         SDL_DFB_RELEASE(data->surface);
   404         SDL_DFB_CHECKERR(dispdata->vidlayer->
   405                          SetCooperativeLevel(dispdata->vidlayer,
   406                                              DLSCL_ADMINISTRATIVE));
   407         SDL_DFB_RELEASE(dispdata->vidlayer);
   408     }
   409     return 1;
   410 }
   411 
   412 static int
   413 DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   414 {
   415     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   416     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   417     SDL_DFB_DEVICEDATA(display->device);
   418     DirectFB_TextureData *data;
   419     DFBResult ret;
   420     DFBSurfaceDescription dsc;
   421 
   422     SDL_DFB_CALLOC(data, 1, sizeof(*data));
   423     texture->driverdata = data;
   424 
   425     data->format = texture->format;
   426     data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
   427 
   428     if (DirectFB_AcquireVidLayer(renderer, texture) != 0) {
   429         /* fill surface description */
   430         dsc.flags =
   431             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   432         dsc.width = texture->w;
   433         dsc.height = texture->h;
   434         /* <1.2 Never use DSCAPS_VIDEOONLY here. It kills performance
   435          * No DSCAPS_SYSTEMONLY either - let dfb decide
   436          * 1.2: DSCAPS_SYSTEMONLY boosts performance by factor ~8
   437          * Depends on other settings as well. Let dfb decide.
   438          */
   439         dsc.caps = DSCAPS_PREMULTIPLIED;
   440 #if 0
   441         if (texture->access == SDL_TEXTUREACCESS_STREAMING)
   442             dsc.caps |= DSCAPS_SYSTEMONLY;
   443         else
   444             dsc.caps |= DSCAPS_VIDEOONLY;
   445 #endif
   446 
   447         /* find the right pixelformat */
   448 
   449         dsc.pixelformat = SDLToDFBPixelFormat(data->format);
   450         if (dsc.pixelformat == DSPF_UNKNOWN) {
   451             SDL_SetError("Unknown pixel format %d\n", data->format);
   452             goto error;
   453         }
   454 
   455         data->pixels = NULL;
   456 
   457         /* Create the surface */
   458         SDL_DFB_CHECKERR(devdata->dfb->
   459                          CreateSurface(devdata->dfb, &dsc, &data->surface));
   460         if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   461             && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   462             SDL_DFB_CHECKERR(data->surface->
   463                              GetPalette(data->surface, &data->palette));
   464         }
   465 
   466     }
   467 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   468     data->render_options = DSRO_NONE;
   469 #endif
   470 
   471     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   472         data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
   473         SDL_DFB_CALLOC(data->pixels, 1, texture->h * data->pitch);
   474     }
   475 
   476     return 0;
   477 
   478   error:
   479     SDL_DFB_RELEASE(data->palette);
   480     SDL_DFB_RELEASE(data->surface);
   481     SDL_DFB_FREE(texture->driverdata);
   482     return -1;
   483 }
   484 
   485 static int
   486 DirectFB_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   487                             void **pixels, int *pitch)
   488 {
   489     DirectFB_TextureData *texturedata =
   490         (DirectFB_TextureData *) texture->driverdata;
   491 
   492     if (texturedata->display) {
   493         return -1;
   494     } else {
   495         *pixels = texturedata->pixels;
   496         *pitch = texturedata->pitch;
   497     }
   498     return 0;
   499 }
   500 
   501 static int
   502 DirectFB_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   503                            const SDL_Color * colors, int firstcolor,
   504                            int ncolors)
   505 {
   506     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   507     DFBResult ret;
   508 
   509     if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   510         && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   511         DFBColor entries[256];
   512         int i;
   513 
   514         for (i = 0; i < ncolors; ++i) {
   515             entries[i].r = colors[i].r;
   516             entries[i].g = colors[i].g;
   517             entries[i].b = colors[i].b;
   518             entries[i].a = 0xFF;
   519         }
   520         SDL_DFB_CHECKERR(data->palette->
   521                          SetEntries(data->palette, entries, ncolors,
   522                                     firstcolor));
   523         return 0;
   524     } else {
   525         SDL_SetError("YUV textures don't have a palette");
   526         return -1;
   527     }
   528   error:
   529     return -1;
   530 }
   531 
   532 static int
   533 DirectFB_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   534                            SDL_Color * colors, int firstcolor, int ncolors)
   535 {
   536     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   537     DFBResult ret;
   538 
   539     if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   540         && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   541         DFBColor entries[256];
   542         int i;
   543 
   544         SDL_DFB_CHECKERR(data->palette->
   545                          GetEntries(data->palette, entries, ncolors,
   546                                     firstcolor));
   547 
   548         for (i = 0; i < ncolors; ++i) {
   549             colors[i].r = entries[i].r;
   550             colors[i].g = entries[i].g;
   551             colors[i].b = entries[i].b;
   552             colors->unused = SDL_ALPHA_OPAQUE;
   553         }
   554         return 0;
   555     } else {
   556         SDL_SetError("YUV textures don't have a palette");
   557         return -1;
   558     }
   559   error:
   560     return -1;
   561 }
   562 
   563 static int
   564 DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   565 {
   566     return 0;
   567 }
   568 
   569 static int
   570 DirectFB_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   571 {
   572     return 0;
   573 }
   574 
   575 static int
   576 DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   577 {
   578     switch (texture->blendMode) {
   579     case SDL_TEXTUREBLENDMODE_NONE:
   580     case SDL_TEXTUREBLENDMODE_MASK:
   581     case SDL_TEXTUREBLENDMODE_BLEND:
   582     case SDL_TEXTUREBLENDMODE_ADD:
   583     case SDL_TEXTUREBLENDMODE_MOD:
   584         return 0;
   585     default:
   586         SDL_Unsupported();
   587         texture->blendMode = SDL_TEXTUREBLENDMODE_NONE;
   588         return -1;
   589     }
   590 }
   591 
   592 static int
   593 DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   594 {
   595 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   596 
   597     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   598 
   599     switch (texture->scaleMode) {
   600     case SDL_TEXTURESCALEMODE_NONE:
   601     case SDL_TEXTURESCALEMODE_FAST:
   602         data->render_options = DSRO_NONE;
   603         break;
   604     case SDL_TEXTURESCALEMODE_SLOW:
   605         data->render_options = DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE;
   606         break;
   607     case SDL_TEXTURESCALEMODE_BEST:
   608         data->render_options =
   609             DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE | DSRO_ANTIALIAS;
   610         break;
   611     default:
   612         SDL_Unsupported();
   613         data->render_options = DSRO_NONE;
   614         texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
   615         return -1;
   616     }
   617 #endif
   618     return 0;
   619 }
   620 
   621 static int
   622 DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   623                        const SDL_Rect * rect, const void *pixels, int pitch)
   624 {
   625     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   626     DFBResult ret;
   627     Uint8 *dpixels;
   628     int dpitch;
   629     Uint8 *src, *dst;
   630     int row;
   631     size_t length;
   632 
   633     SDL_DFB_CHECKERR(data->surface->Lock(data->surface,
   634                                          DSLF_WRITE | DSLF_READ,
   635                                          ((void **) &dpixels), &dpitch));
   636     src = (Uint8 *) pixels;
   637     dst =
   638         (Uint8 *) dpixels + rect->y * dpitch +
   639         rect->x * SDL_BYTESPERPIXEL(texture->format);
   640     length = rect->w * SDL_BYTESPERPIXEL(texture->format);
   641     for (row = 0; row < rect->h; ++row) {
   642         SDL_memcpy(dst, src, length);
   643         src += pitch;
   644         dst += dpitch;
   645     }
   646     SDL_DFB_CHECKERR(data->surface->Unlock(data->surface));
   647     return 0;
   648   error:
   649     return 1;
   650 
   651 }
   652 
   653 static int
   654 DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   655                      const SDL_Rect * rect, int markDirty, void **pixels,
   656                      int *pitch)
   657 {
   658     DirectFB_TextureData *texturedata =
   659         (DirectFB_TextureData *) texture->driverdata;
   660     DFBResult ret;
   661 
   662     if (markDirty) {
   663         SDL_AddDirtyRect(&texturedata->dirty, rect);
   664     }
   665 
   666     if (texturedata->display) {
   667         void *fdata;
   668         int fpitch;
   669 
   670         SDL_DFB_CHECKERR(texturedata->surface->Lock(texturedata->surface,
   671                                                     DSLF_WRITE | DSLF_READ,
   672                                                     &fdata, &fpitch));
   673         *pitch = fpitch;
   674         *pixels = fdata;
   675     } else {
   676         *pixels =
   677             (void *) ((Uint8 *) texturedata->pixels +
   678                       rect->y * texturedata->pitch +
   679                       rect->x * SDL_BYTESPERPIXEL(texture->format));
   680         *pitch = texturedata->pitch;
   681     }
   682     return 0;
   683 
   684   error:
   685     return -1;
   686 }
   687 
   688 static void
   689 DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   690 {
   691     DirectFB_TextureData *texturedata =
   692         (DirectFB_TextureData *) texture->driverdata;
   693 
   694     if (texturedata->display) {
   695         texturedata->surface->Unlock(texturedata->surface);
   696         texturedata->pixels = NULL;
   697     }
   698 }
   699 
   700 static void
   701 DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   702                       int numrects, const SDL_Rect * rects)
   703 {
   704     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   705     int i;
   706 
   707     for (i = 0; i < numrects; ++i) {
   708         SDL_AddDirtyRect(&data->dirty, &rects[i]);
   709     }
   710 }
   711 
   712 static int
   713 DirectFB_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
   714                     Uint8 a, const SDL_Rect * rect)
   715 {
   716     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   717     DFBResult ret;
   718 
   719     SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, r, g, b, a));
   720     SDL_DFB_CHECKERR(data->surface->
   721                      FillRectangle(data->surface, rect->x, rect->y, rect->w,
   722                                    rect->h));
   723 
   724     return 0;
   725   error:
   726     return -1;
   727 }
   728 
   729 static int
   730 DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   731                     const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   732 {
   733     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   734     DirectFB_TextureData *texturedata =
   735         (DirectFB_TextureData *) texture->driverdata;
   736     DFBResult ret;
   737 
   738     if (texturedata->display) {
   739         int px, py;
   740         SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   741         SDL_DFB_WINDOWDATA(window);
   742         SDL_VideoDisplay *display = texturedata->display;
   743         DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   744 
   745         SDL_DFB_CHECKERR(dispdata->vidlayer->
   746                          SetSourceRectangle(dispdata->vidlayer, srcrect->x,
   747                                             srcrect->y, srcrect->w,
   748                                             srcrect->h));
   749         windata->window->GetPosition(windata->window, &px, &py);
   750         SDL_DFB_CHECKERR(dispdata->vidlayer->
   751                          SetScreenRectangle(dispdata->vidlayer,
   752                                             px + dstrect->x, py + dstrect->y,
   753                                             dstrect->w, dstrect->h));
   754     } else {
   755         DFBRectangle sr, dr;
   756         DFBSurfaceBlittingFlags flags = 0;
   757 
   758         if (texturedata->dirty.list) {
   759             SDL_DirtyRect *dirty;
   760             void *pixels;
   761             int bpp = SDL_BYTESPERPIXEL(texture->format);
   762             int pitch = texturedata->pitch;
   763 
   764             for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
   765                 SDL_Rect *rect = &dirty->rect;
   766                 pixels =
   767                     (void *) ((Uint8 *) texturedata->pixels +
   768                               rect->y * pitch + rect->x * bpp);
   769                 DirectFB_UpdateTexture(renderer, texture, rect,
   770                                        texturedata->pixels,
   771                                        texturedata->pitch);
   772             }
   773             SDL_ClearDirtyRects(&texturedata->dirty);
   774         }
   775 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   776         SDL_DFB_CHECKERR(data->surface->SetRenderOptions(data->surface,
   777                                                          texturedata->
   778                                                          render_options));
   779 #endif
   780 
   781         SDLtoDFBRect(srcrect, &sr);
   782         SDLtoDFBRect(dstrect, &dr);
   783 
   784         if (texture->
   785             modMode & (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA))
   786         {
   787             Uint8 alpha = 0xFF;
   788             if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
   789                 alpha = texture->a;
   790                 flags |= DSBLIT_SRC_PREMULTCOLOR;
   791                 SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
   792                                                          0xFF, 0xFF, alpha));
   793             }
   794             if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
   795                 SDL_DFB_CHECKERR(data->surface->
   796                                  SetColor(data->surface, texture->r,
   797                                           texture->g, texture->b, alpha));
   798                 /* Only works together .... */
   799                 flags |= DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR;
   800             }
   801         }
   802 
   803         switch (texture->blendMode) {
   804         case SDL_TEXTUREBLENDMODE_NONE:
   805                                        /**< No blending */
   806             flags |= DSBLIT_NOFX;
   807             data->surface->SetSrcBlendFunction(data->surface, DSBF_ONE);
   808             data->surface->SetDstBlendFunction(data->surface, DSBF_ZERO);
   809             break;
   810         case SDL_TEXTUREBLENDMODE_MASK:
   811             flags |= DSBLIT_BLEND_ALPHACHANNEL;
   812             data->surface->SetSrcBlendFunction(data->surface, DSBF_SRCALPHA);
   813             data->surface->SetDstBlendFunction(data->surface,
   814                                                DSBF_INVSRCALPHA);
   815             break;
   816         case SDL_TEXTUREBLENDMODE_BLEND:
   817             flags |= DSBLIT_BLEND_ALPHACHANNEL;
   818             data->surface->SetSrcBlendFunction(data->surface, DSBF_SRCALPHA);
   819             data->surface->SetDstBlendFunction(data->surface,
   820                                                DSBF_INVSRCALPHA);
   821             break;
   822         case SDL_TEXTUREBLENDMODE_ADD:
   823             flags |= DSBLIT_BLEND_ALPHACHANNEL;
   824             data->surface->SetSrcBlendFunction(data->surface, DSBF_SRCALPHA);
   825             data->surface->SetDstBlendFunction(data->surface, DSBF_ONE);
   826             break;
   827         case SDL_TEXTUREBLENDMODE_MOD:
   828             flags |= DSBLIT_BLEND_ALPHACHANNEL;
   829             data->surface->SetSrcBlendFunction(data->surface, DSBF_DESTCOLOR);
   830             data->surface->SetDstBlendFunction(data->surface, DSBF_ZERO);
   831             break;
   832         }
   833 
   834         SDL_DFB_CHECKERR(data->surface->
   835                          SetBlittingFlags(data->surface, flags));
   836 
   837         if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
   838             SDL_DFB_CHECKERR(data->surface->
   839                              Blit(data->surface, texturedata->surface,
   840                                   &sr, dr.x, dr.y));
   841         } else {
   842             SDL_DFB_CHECKERR(data->surface->
   843                              StretchBlit(data->surface, texturedata->surface,
   844                                          &sr, &dr));
   845         }
   846     }
   847     return 0;
   848   error:
   849     return -1;
   850 }
   851 
   852 static void
   853 DirectFB_RenderPresent(SDL_Renderer * renderer)
   854 {
   855     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   856     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   857 
   858     DFBRectangle sr;
   859     DFBResult ret;
   860 
   861     sr.x = 0;
   862     sr.y = 0;
   863     sr.w = window->w;
   864     sr.h = window->h;
   865 
   866     /* Send the data to the display */
   867     SDL_DFB_CHECKERR(data->surface->
   868                      Flip(data->surface, NULL, data->flipflags));
   869 
   870     return;
   871   error:
   872     return;
   873 }
   874 
   875 static void
   876 DirectFB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   877 {
   878     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   879 
   880     if (!data) {
   881         return;
   882     }
   883     SDL_DFB_RELEASE(data->palette);
   884     SDL_DFB_RELEASE(data->surface);
   885     if (data->display) {
   886         DFB_DisplayData *dispdata =
   887             (DFB_DisplayData *) data->display->driverdata;
   888         dispdata->vidIDinuse = 0;
   889         dispdata->vidlayer->SetCooperativeLevel(dispdata->vidlayer,
   890                                                 DLSCL_ADMINISTRATIVE);
   891         SDL_DFB_RELEASE(dispdata->vidlayer);
   892     }
   893     SDL_FreeDirtyRects(&data->dirty);
   894     SDL_DFB_FREE(data->pixels);
   895     SDL_free(data);
   896     texture->driverdata = NULL;
   897 }
   898 
   899 static void
   900 DirectFB_DestroyRenderer(SDL_Renderer * renderer)
   901 {
   902     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   903 
   904     if (data) {
   905         SDL_DFB_RELEASE(data->surface);
   906         SDL_free(data);
   907     }
   908     SDL_free(renderer);
   909 }
   910 
   911 /* vi: set ts=4 sw=4 expandtab: */