src/video/directfb/SDL_DirectFB_window.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 03 Jan 2018 10:03:25 -0800
changeset 11811 5d94cb6b24d3
parent 11093 b6f52c4d56c6
child 12503 806492103856
permissions -rw-r--r--
Updated copyright for 2018
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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 
    25 #include "SDL_DirectFB_video.h"
    26 #include "SDL_DirectFB_modes.h"
    27 #include "SDL_DirectFB_window.h"
    28 #include "SDL_DirectFB_shape.h"
    29 
    30 #if SDL_DIRECTFB_OPENGL
    31 #include "SDL_DirectFB_opengl.h"
    32 #endif
    33 
    34 #include "SDL_syswm.h"
    35 
    36 #include "../SDL_pixels_c.h"
    37 
    38 int
    39 DirectFB_CreateWindow(_THIS, SDL_Window * window)
    40 {
    41     SDL_DFB_DEVICEDATA(_this);
    42     SDL_DFB_DISPLAYDATA(window);
    43     DFB_WindowData *windata = NULL;
    44     DFBWindowOptions wopts;
    45     DFBWindowDescription desc;
    46     int x, y;
    47     int bshaped = 0;
    48 
    49     SDL_DFB_ALLOC_CLEAR(window->driverdata, sizeof(DFB_WindowData));
    50     SDL_memset(&desc, 0, sizeof(DFBWindowDescription));
    51     windata = (DFB_WindowData *) window->driverdata;
    52 
    53     windata->is_managed = devdata->has_own_wm;
    54 #if 1
    55     SDL_DFB_CHECKERR(devdata->dfb->SetCooperativeLevel(devdata->dfb,
    56                                                        DFSCL_NORMAL));
    57     SDL_DFB_CHECKERR(dispdata->layer->SetCooperativeLevel(dispdata->layer,
    58                                                           DLSCL_ADMINISTRATIVE));
    59 #endif
    60     /* FIXME ... ughh, ugly */
    61     if (window->x == -1000 && window->y == -1000)
    62         bshaped = 1;
    63 
    64     /* Fill the window description. */
    65     x = window->x;
    66     y = window->y;
    67 
    68     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
    69 
    70     /* Create Window */
    71     desc.caps = 0;
    72     desc.flags =
    73         DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY | DWDESC_SURFACE_CAPS;
    74 
    75     if (bshaped) {
    76         desc.flags |= DWDESC_CAPS;
    77         desc.caps |= DWCAPS_ALPHACHANNEL;
    78     }
    79     else
    80     {
    81         desc.flags |= DWDESC_PIXELFORMAT;
    82     }
    83 
    84     if (!(window->flags & SDL_WINDOW_BORDERLESS))
    85         desc.caps |= DWCAPS_NODECORATION;
    86 
    87     desc.posx = x;
    88     desc.posy = y;
    89     desc.width = windata->size.w;
    90     desc.height = windata->size.h;
    91     desc.pixelformat = dispdata->pixelformat;
    92     desc.surface_caps = DSCAPS_PREMULTIPLIED;
    93 #if DIRECTFB_MAJOR_VERSION == 1 && DIRECTFB_MINOR_VERSION >= 6
    94     if (window->flags & SDL_WINDOW_OPENGL) {
    95         desc.surface_caps |= DSCAPS_GL;
    96     }
    97 #endif
    98 
    99     /* Create the window. */
   100     SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
   101                                                    &windata->dfbwin));
   102 
   103     /* Set Options */
   104     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   105 
   106     /* explicit rescaling of surface */
   107     wopts |= DWOP_SCALE;
   108     if (window->flags & SDL_WINDOW_RESIZABLE) {
   109         wopts &= ~DWOP_KEEP_SIZE;
   110     }
   111     else {
   112         wopts |= DWOP_KEEP_SIZE;
   113     }
   114 
   115     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   116         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
   117         SDL_DFB_CHECK(windata->dfbwin->SetStackingClass(windata->dfbwin, DWSC_UPPER));
   118     }
   119 
   120     if (bshaped) {
   121         wopts |= DWOP_SHAPED | DWOP_ALPHACHANNEL;
   122         wopts &= ~DWOP_OPAQUE_REGION;
   123     }
   124 
   125     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   126 
   127     /* See what we got */
   128     SDL_DFB_CHECK(DirectFB_WM_GetClientSize
   129                      (_this, window, &window->w, &window->h));
   130 
   131     /* Get the window's surface. */
   132     SDL_DFB_CHECKERR(windata->dfbwin->GetSurface(windata->dfbwin,
   133                                                  &windata->window_surface));
   134 
   135     /* And get a subsurface for rendering */
   136     SDL_DFB_CHECKERR(windata->window_surface->
   137                      GetSubSurface(windata->window_surface, &windata->client,
   138                                    &windata->surface));
   139 
   140     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0xFF));
   141 
   142     /* Create Eventbuffer */
   143 
   144     SDL_DFB_CHECKERR(windata->dfbwin->CreateEventBuffer(windata->dfbwin,
   145                                                         &windata->
   146                                                         eventbuffer));
   147     SDL_DFB_CHECKERR(windata->dfbwin->
   148                      EnableEvents(windata->dfbwin, DWET_ALL));
   149 
   150     /* Create a font */
   151     /* FIXME: once during Video_Init */
   152     windata->font = NULL;
   153 
   154     /* Make it the top most window. */
   155     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   156 
   157     /* remember parent */
   158     /* windata->sdlwin = window; */
   159 
   160     /* Add to list ... */
   161 
   162     windata->next = devdata->firstwin;
   163     windata->opacity = 0xFF;
   164     devdata->firstwin = window;
   165 
   166     /* Draw Frame */
   167     DirectFB_WM_RedrawLayout(_this, window);
   168 
   169     return 0;
   170   error:
   171     SDL_DFB_RELEASE(windata->surface);
   172     SDL_DFB_RELEASE(windata->dfbwin);
   173     return -1;
   174 }
   175 
   176 int
   177 DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   178 {
   179     return SDL_Unsupported();
   180 }
   181 
   182 void
   183 DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
   184 {
   185     SDL_DFB_WINDOWDATA(window);
   186 
   187     if (windata->is_managed) {
   188         windata->wm_needs_redraw = 1;
   189         DirectFB_WM_RedrawLayout(_this, window);
   190     } else {
   191         SDL_Unsupported();
   192     }
   193 }
   194 
   195 void
   196 DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   197 {
   198     SDL_DFB_DEVICEDATA(_this);
   199     SDL_DFB_WINDOWDATA(window);
   200     SDL_Surface *surface = NULL;
   201 
   202     if (icon) {
   203         SDL_PixelFormat format;
   204         DFBSurfaceDescription dsc;
   205         Uint32 *dest;
   206         Uint32 *p;
   207         int pitch, i;
   208 
   209         /* Convert the icon to ARGB for modern window managers */
   210         SDL_InitFormat(&format, SDL_PIXELFORMAT_ARGB8888);
   211         surface = SDL_ConvertSurface(icon, &format, 0);
   212         if (!surface) {
   213             return;
   214         }
   215         dsc.flags =
   216             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   217         dsc.caps = DSCAPS_VIDEOONLY;
   218         dsc.width = surface->w;
   219         dsc.height = surface->h;
   220         dsc.pixelformat = DSPF_ARGB;
   221 
   222         SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   223                                                      &windata->icon));
   224 
   225         SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
   226                                              (void *) &dest, &pitch));
   227 
   228         p = surface->pixels;
   229         for (i = 0; i < surface->h; i++)
   230             memcpy((char *) dest + i * pitch,
   231                    (char *) p + i * surface->pitch, 4 * surface->w);
   232 
   233         SDL_DFB_CHECK(windata->icon->Unlock(windata->icon));
   234         SDL_FreeSurface(surface);
   235     } else {
   236         SDL_DFB_RELEASE(windata->icon);
   237     }
   238     return;
   239   error:
   240     SDL_FreeSurface(surface);
   241     SDL_DFB_RELEASE(windata->icon);
   242     return;
   243 }
   244 
   245 void
   246 DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
   247 {
   248     SDL_DFB_WINDOWDATA(window);
   249     int x, y;
   250 
   251     x = window->x;
   252     y = window->y;
   253 
   254     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   255     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, x, y));
   256 }
   257 
   258 void
   259 DirectFB_SetWindowSize(_THIS, SDL_Window * window)
   260 {
   261     SDL_DFB_WINDOWDATA(window);
   262 
   263     if(SDL_IsShapedWindow(window))
   264         DirectFB_ResizeWindowShape(window);
   265 
   266     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   267         int cw;
   268         int ch;
   269 
   270         /* Make sure all events are disabled for this operation ! */
   271         SDL_DFB_CHECKERR(windata->dfbwin->DisableEvents(windata->dfbwin,
   272                                                         DWET_ALL));
   273         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
   274 
   275         if (cw != window->w || ch != window->h) {
   276 
   277             DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   278             SDL_DFB_CHECKERR(windata->dfbwin->Resize(windata->dfbwin,
   279                                                      windata->size.w,
   280                                                      windata->size.h));
   281         }
   282 
   283         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   284                      (_this, window, &window->w, &window->h));
   285         DirectFB_AdjustWindowSurface(window);
   286 
   287         SDL_DFB_CHECKERR(windata->dfbwin->EnableEvents(windata->dfbwin,
   288                                                        DWET_ALL));
   289 
   290     }
   291     return;
   292   error:
   293     SDL_DFB_CHECK(windata->dfbwin->EnableEvents(windata->dfbwin, DWET_ALL));
   294     return;
   295 }
   296 
   297 void
   298 DirectFB_ShowWindow(_THIS, SDL_Window * window)
   299 {
   300     SDL_DFB_WINDOWDATA(window);
   301 
   302     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, windata->opacity));
   303 
   304 }
   305 
   306 void
   307 DirectFB_HideWindow(_THIS, SDL_Window * window)
   308 {
   309     SDL_DFB_WINDOWDATA(window);
   310 
   311     SDL_DFB_CHECK(windata->dfbwin->GetOpacity(windata->dfbwin, &windata->opacity));
   312     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0));
   313 }
   314 
   315 void
   316 DirectFB_RaiseWindow(_THIS, SDL_Window * window)
   317 {
   318     SDL_DFB_WINDOWDATA(window);
   319 
   320     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   321     SDL_DFB_CHECK(windata->dfbwin->RequestFocus(windata->dfbwin));
   322 }
   323 
   324 void
   325 DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
   326 {
   327     SDL_DFB_WINDOWDATA(window);
   328     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   329     DFBWindowOptions wopts;
   330 
   331     SDL_DFB_CHECK(windata->dfbwin->GetPosition(windata->dfbwin,
   332                                  &windata->restore.x, &windata->restore.y));
   333     SDL_DFB_CHECK(windata->dfbwin->GetSize(windata->dfbwin, &windata->restore.w,
   334                              &windata->restore.h));
   335 
   336     DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
   337 
   338     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, 0, 0));
   339     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin,
   340                             display->current_mode.w, display->current_mode.h));
   341 
   342     /* Set Options */
   343     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   344     wopts |= DWOP_KEEP_SIZE | DWOP_KEEP_POSITION;
   345     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   346 }
   347 
   348 void
   349 DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
   350 {
   351     /* FIXME: Size to 32x32 ? */
   352 
   353     SDL_Unsupported();
   354 }
   355 
   356 void
   357 DirectFB_RestoreWindow(_THIS, SDL_Window * window)
   358 {
   359     SDL_DFB_WINDOWDATA(window);
   360     DFBWindowOptions wopts;
   361 
   362     /* Set Options */
   363     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   364     wopts &= ~(DWOP_KEEP_SIZE | DWOP_KEEP_POSITION);
   365     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   366 
   367     /* Window layout */
   368     DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED),
   369         windata->restore.w, windata->restore.h);
   370     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin, windata->restore.w,
   371                             windata->restore.h));
   372     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, windata->restore.x,
   373                             windata->restore.y));
   374 
   375     if (!(window->flags & SDL_WINDOW_RESIZABLE))
   376         wopts |= DWOP_KEEP_SIZE;
   377 
   378     if (window->flags & SDL_WINDOW_FULLSCREEN)
   379         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_SIZE;
   380     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   381 
   382 
   383 }
   384 
   385 void
   386 DirectFB_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
   387 {
   388     SDL_DFB_DEVICEDATA(_this);
   389     SDL_DFB_WINDOWDATA(window);
   390     DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
   391 
   392     if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
   393         if (gwindata != NULL)
   394         {
   395             SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
   396             SDL_DFB_CHECK(gwindata->dfbwin->UngrabKeyboard(gwindata->dfbwin));
   397         }
   398         SDL_DFB_CHECK(windata->dfbwin->GrabPointer(windata->dfbwin));
   399         SDL_DFB_CHECK(windata->dfbwin->GrabKeyboard(windata->dfbwin));
   400         devdata->grabbed_window = window;
   401     } else {
   402         SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   403         SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   404         devdata->grabbed_window = NULL;
   405     }
   406 }
   407 
   408 void
   409 DirectFB_DestroyWindow(_THIS, SDL_Window * window)
   410 {
   411     SDL_DFB_DEVICEDATA(_this);
   412     SDL_DFB_WINDOWDATA(window);
   413     DFB_WindowData *p;
   414 
   415     /* Some cleanups */
   416     SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   417     SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   418 
   419 #if SDL_DIRECTFB_OPENGL
   420     DirectFB_GL_DestroyWindowContexts(_this, window);
   421 #endif
   422 
   423     if (window->shaper)
   424     {
   425         SDL_ShapeData *data = window->shaper->driverdata;
   426         SDL_DFB_CHECK(data->surface->ReleaseSource(data->surface));
   427         SDL_DFB_RELEASE(data->surface);
   428         SDL_DFB_FREE(data);
   429         SDL_DFB_FREE(window->shaper);
   430     }
   431 
   432     SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, NULL));
   433     SDL_DFB_CHECK(windata->surface->ReleaseSource(windata->surface));
   434     SDL_DFB_CHECK(windata->window_surface->ReleaseSource(windata->window_surface));
   435     SDL_DFB_RELEASE(windata->icon);
   436     SDL_DFB_RELEASE(windata->font);
   437     SDL_DFB_RELEASE(windata->eventbuffer);
   438     SDL_DFB_RELEASE(windata->surface);
   439     SDL_DFB_RELEASE(windata->window_surface);
   440 
   441     SDL_DFB_RELEASE(windata->dfbwin);
   442 
   443     /* Remove from list ... */
   444 
   445     p = devdata->firstwin->driverdata;
   446 
   447     while (p && p->next != window)
   448         p = (p->next ? p->next->driverdata : NULL);
   449     if (p)
   450         p->next = windata->next;
   451     else
   452         devdata->firstwin = windata->next;
   453     SDL_free(windata);
   454     return;
   455 }
   456 
   457 SDL_bool
   458 DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
   459                          struct SDL_SysWMinfo * info)
   460 {
   461     const Uint32 version = ((((Uint32) info->version.major) * 1000000) +
   462                             (((Uint32) info->version.minor) * 10000) +
   463                             (((Uint32) info->version.patch)));
   464 
   465     SDL_DFB_DEVICEDATA(_this);
   466     SDL_DFB_WINDOWDATA(window);
   467 
   468     /* Before 2.0.6, it was possible to build an SDL with DirectFB support
   469        (SDL_SysWMinfo will be large enough to hold DirectFB info), but build
   470        your app against SDL headers that didn't have DirectFB support
   471        (SDL_SysWMinfo could be smaller than DirectFB needs. This would lead
   472        to an app properly using SDL_GetWindowWMInfo() but we'd accidentally
   473        overflow memory on the stack or heap. To protect against this, we've
   474        padded out the struct unconditionally in the headers and DirectFB will
   475        just return an error for older apps using this function. Those apps
   476        will need to be recompiled against newer headers or not use DirectFB,
   477        maybe by forcing SDL_VIDEODRIVER=x11. */
   478     if (version < 2000006) {
   479         info->subsystem = SDL_SYSWM_UNKNOWN;
   480         SDL_SetError("Version must be 2.0.6 or newer");
   481         return SDL_FALSE;
   482     }
   483 
   484     if (info->version.major == SDL_MAJOR_VERSION &&
   485         info->version.minor == SDL_MINOR_VERSION) {
   486         info->subsystem = SDL_SYSWM_DIRECTFB;
   487         info->info.dfb.dfb = devdata->dfb;
   488         info->info.dfb.window = windata->dfbwin;
   489         info->info.dfb.surface = windata->surface;
   490         return SDL_TRUE;
   491     } else {
   492         SDL_SetError("Application not compiled with SDL %d.%d",
   493                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   494         return SDL_FALSE;
   495     }
   496 }
   497 
   498 void
   499 DirectFB_AdjustWindowSurface(SDL_Window * window)
   500 {
   501     SDL_DFB_WINDOWDATA(window);
   502     int adjust = windata->wm_needs_redraw;
   503     int cw, ch;
   504 
   505     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   506 
   507     SDL_DFB_CHECKERR(windata->
   508                      window_surface->GetSize(windata->window_surface, &cw,
   509                                              &ch));
   510     if (cw != windata->size.w || ch != windata->size.h) {
   511         adjust = 1;
   512     }
   513 
   514     if (adjust) {
   515 #if SDL_DIRECTFB_OPENGL
   516         DirectFB_GL_FreeWindowContexts(SDL_GetVideoDevice(), window);
   517 #endif
   518 
   519 #if (DFB_VERSION_ATLEAST(1,2,1))
   520         SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   521                                                         windata->size.w,
   522                                                         windata->size.h));
   523         SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
   524                                                           windata->
   525                                                           window_surface,
   526                                                           &windata->client));
   527 #else
   528         DFBWindowOptions opts;
   529 
   530         SDL_DFB_CHECKERR(windata->dfbwin->GetOptions(windata->dfbwin, &opts));
   531         /* recreate subsurface */
   532         SDL_DFB_RELEASE(windata->surface);
   533 
   534         if (opts & DWOP_SCALE)
   535             SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   536                                                             windata->size.w,
   537                                                             windata->size.h));
   538         SDL_DFB_CHECKERR(windata->window_surface->
   539                          GetSubSurface(windata->window_surface,
   540                                        &windata->client, &windata->surface));
   541 #endif
   542         DirectFB_WM_RedrawLayout(SDL_GetVideoDevice(), window);
   543 
   544 #if SDL_DIRECTFB_OPENGL
   545         DirectFB_GL_ReAllocWindowContexts(SDL_GetVideoDevice(), window);
   546 #endif
   547    }
   548   error:
   549     return;
   550 }
   551 
   552 int
   553 DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
   554 {
   555     const Uint8 alpha = (Uint8) ((unsigned int) (opacity * 255.0f));
   556     SDL_DFB_WINDOWDATA(window);
   557     SDL_DFB_CHECKERR(windata->dfbwin->SetOpacity(windata->dfbwin, alpha));
   558     windata->opacity = alpha;
   559     return 0;
   560 
   561 error:
   562     return -1;
   563 }
   564 
   565 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */