src/video/SDL_renderer_gl.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 19 Jul 2006 08:46:57 +0000
changeset 1919 00816063b9c9
parent 1918 092bd3a019c5
child 1920 8a162bfdc838
permissions -rw-r--r--
Fixed to compile while the OpenGL renderer is under construction
     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 #include "SDL_config.h"
    23 
    24 #if SDL_VIDEO_OPENGL
    25 #if 0
    26 #include "SDL_win32video.h"
    27 
    28 /* OpenGL renderer implementation */
    29 
    30 static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
    31 static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    32 static int GL_SetTexturePalette(SDL_Renderer * renderer,
    33                                 SDL_Texture * texture,
    34                                 const SDL_Color * colors, int firstcolor,
    35                                 int ncolors);
    36 static int GL_GetTexturePalette(SDL_Renderer * renderer,
    37                                 SDL_Texture * texture, SDL_Color * colors,
    38                                 int firstcolor, int ncolors);
    39 static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    40                             const SDL_Rect * rect, const void *pixels,
    41                             int pitch);
    42 static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    43                           const SDL_Rect * rect, int markDirty,
    44                           void **pixels, int *pitch);
    45 static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    46 static void GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    47                             int numrects, const SDL_Rect * rects);
    48 static int GL_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
    49                          Uint32 color);
    50 static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    51                          const SDL_Rect * srcrect, const SDL_Rect * dstrect,
    52                          int blendMode, int scaleMode);
    53 static void GL_RenderPresent(SDL_Renderer * renderer);
    54 static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    55 static void GL_DestroyRenderer(SDL_Renderer * renderer);
    56 
    57 
    58 SDL_RenderDriver GL_RenderDriver = {
    59     GL_CreateRenderer,
    60     {
    61      "opengl",
    62      (SDL_Renderer_PresentDiscard | SDL_Renderer_PresentVSync |
    63       SDL_Renderer_Accelerated),
    64      (SDL_TextureBlendMode_None | SDL_TextureBlendMode_Mask |
    65       SDL_TextureBlendMode_Blend | SDL_TextureBlendMode_Add |
    66       SDL_TextureBlendMode_Mod),
    67      (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast |
    68       SDL_TextureScaleMode_Best),
    69      12,
    70      {
    71       SDL_PixelFormat_Index8,
    72       SDL_PixelFormat_RGB332,
    73       SDL_PixelFormat_RGB444,
    74       SDL_PixelFormat_RGB555,
    75       SDL_PixelFormat_ARGB4444,
    76       SDL_PixelFormat_ARGB1555,
    77       SDL_PixelFormat_RGB565,
    78       SDL_PixelFormat_RGB888,
    79       SDL_PixelFormat_ARGB8888,
    80       SDL_PixelFormat_ARGB2101010,
    81       SDL_PixelFormat_UYVY,
    82       SDL_PixelFormat_YUY2},
    83      0,
    84      0}
    85 };
    86 
    87 typedef struct
    88 {
    89     SDL_GLContext context;
    90     SDL_bool beginScene;
    91 } GL_RenderData;
    92 
    93 typedef struct
    94 {
    95     GLuint texture;
    96     GLfloat texw;
    97     GLfloat texh;
    98     void *pixels;
    99     int pitch;
   100 } GL_TextureData;
   101 
   102 static GLFORMAT
   103 PixelFormatToOpenGL(Uint32 format,)
   104 {
   105     switch (format) {
   106     case SDL_PixelFormat_Index8:
   107         return GLFMT_P8;
   108     case SDL_PixelFormat_RGB332:
   109         return GLFMT_R3G3B2;
   110     case SDL_PixelFormat_RGB444:
   111         return GLFMT_X4R4G4B4;
   112     case SDL_PixelFormat_RGB555:
   113         return GLFMT_X1R5G5B5;
   114     case SDL_PixelFormat_ARGB4444:
   115         return GLFMT_A4R4G4B4;
   116     case SDL_PixelFormat_ARGB1555:
   117         return GLFMT_A1R5G5B5;
   118     case SDL_PixelFormat_RGB565:
   119         return GLFMT_R5G6B5;
   120     case SDL_PixelFormat_RGB888:
   121         return GLFMT_X8R8G8B8;
   122     case SDL_PixelFormat_ARGB8888:
   123         return GLFMT_A8R8G8B8;
   124     case SDL_PixelFormat_ARGB2101010:
   125         return GLFMT_A2R10G10B10;
   126     case SDL_PixelFormat_UYVY:
   127         return GLFMT_UYVY;
   128     case SDL_PixelFormat_YUY2:
   129         return GLFMT_YUY2;
   130     default:
   131         return GLFMT_UNKNOWN;
   132     }
   133 }
   134 
   135 void
   136 GL_AddRenderDriver(_THIS)
   137 {
   138     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   139 
   140     if (data->d3d) {
   141         SDL_AddRenderDriver(0, &GL_RenderDriver);
   142     }
   143 }
   144 
   145 SDL_Renderer *
   146 GL_CreateRenderer(SDL_Window * window, Uint32 flags)
   147 {
   148     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   149     SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
   150     SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
   151     SDL_Renderer *renderer;
   152     GL_RenderData *data;
   153     HRESULT result;
   154     GLPRESENT_PARAMETERS pparams;
   155     IDirect3DSwapChain9 *chain;
   156 
   157     if (!(window->flags & SDL_WINDOW_OPENGL)) {
   158         SDL_SetError
   159             ("The OpenGL renderer can only be used on OpenGL windows");
   160         return NULL;
   161     }
   162 
   163     renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer));
   164     if (!renderer) {
   165         SDL_OutOfMemory();
   166         return NULL;
   167     }
   168     SDL_zerop(renderer);
   169 
   170     data = (GL_RenderData *) SDL_malloc(sizeof(*data));
   171     if (!data) {
   172         GL_DestroyRenderer(renderer);
   173         SDL_OutOfMemory();
   174         return NULL;
   175     }
   176     SDL_zerop(data);
   177 
   178     renderer->CreateTexture = GL_CreateTexture;
   179     renderer->SetTexturePalette = GL_SetTexturePalette;
   180     renderer->GetTexturePalette = GL_GetTexturePalette;
   181     renderer->UpdateTexture = GL_UpdateTexture;
   182     renderer->LockTexture = GL_LockTexture;
   183     renderer->UnlockTexture = GL_UnlockTexture;
   184     renderer->DirtyTexture = GL_DirtyTexture;
   185     renderer->RenderFill = GL_RenderFill;
   186     renderer->RenderCopy = GL_RenderCopy;
   187     renderer->RenderPresent = GL_RenderPresent;
   188     renderer->DestroyTexture = GL_DestroyTexture;
   189     renderer->DestroyRenderer = GL_DestroyRenderer;
   190     renderer->info = GL_RenderDriver.info;
   191     renderer->window = window->id;
   192     renderer->driverdata = data;
   193 
   194     renderer->info.flags =
   195         (SDL_Renderer_PresentDiscard | SDL_Renderer_Accelerated);
   196 
   197     data->context = SDL_GL_CreateContext(window->id);
   198     if (!data->context) {
   199         GL_DestroyRenderer(renderer);
   200         return NULL;
   201     }
   202     if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
   203         GL_DestroyRenderer(renderer);
   204         return NULL;
   205     }
   206     data->beginScene = SDL_TRUE;
   207 
   208     if (flags & SDL_Renderer_PresentVSync) {
   209         SDL_GL_SetSwapInterval(1);
   210     } else {
   211         SDL_GL_SetSwapInterval(0);
   212     }
   213     if (SDL_GL_GetSwapInterval() > 0) {
   214         renderer->info.flags |= SDL_Renderer_PresentVSync;
   215     }
   216 
   217     /* Set up parameters for rendering */
   218     glDisable(GL_DEPTH_TEST);
   219     glDisable(GL_CULL_FACE);
   220     glEnable(GL_TEXTURE_2D);
   221     glMatrixMode(GL_PROJECTION);
   222     glLoadIdentity();
   223     glMatrixMode(GL_MODELVIEW);
   224     glLoadIdentity();
   225     glViewport(0, 0, window->w, window->h);
   226     glOrtho(0.0, (GLdouble) window->w, (GLdouble) window->h, 0.0, 0.0, 1.0);
   227     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
   228 
   229     return renderer;
   230 }
   231 
   232 /* Quick utility function for texture creation */
   233 static int
   234 power_of_two(int input)
   235 {
   236     int value = 1;
   237 
   238     while (value < input) {
   239         value <<= 1;
   240     }
   241     return value;
   242 }
   243 
   244 static int
   245 GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   246 {
   247     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   248     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   249     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   250     GL_TextureData *data;
   251     GLPOOL pool;
   252     HRESULT result;
   253 
   254     data = (GL_TextureData *) SDL_malloc(sizeof(*data));
   255     if (!data) {
   256         SDL_OutOfMemory();
   257         return -1;
   258     }
   259     SDL_zerop(data);
   260 
   261     texture->driverdata = data;
   262 
   263     if (texture->access == SDL_TextureAccess_Local) {
   264         pool = GLPOOL_MANAGED;
   265     } else {
   266         pool = GLPOOL_DEFAULT;
   267     }
   268     result =
   269         IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
   270                                        texture->h, 1, 0,
   271                                        PixelFormatToGLFMT(texture->format),
   272                                        pool, &data->texture, NULL);
   273     if (FAILED(result)) {
   274         SDL_free(data);
   275         GL_SetError("CreateTexture()", result);
   276         return -1;
   277     }
   278 
   279     return 0;
   280 }
   281 
   282 static int
   283 GL_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   284                      const SDL_Color * colors, int firstcolor, int ncolors)
   285 {
   286     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   287     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   288 
   289     return 0;
   290 }
   291 
   292 static int
   293 GL_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   294                      SDL_Color * colors, int firstcolor, int ncolors)
   295 {
   296     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   297 
   298     return 0;
   299 }
   300 
   301 static int
   302 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   303                  const SDL_Rect * rect, const void *pixels, int pitch)
   304 {
   305     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   306     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   307     IDirect3DTexture9 *temp;
   308     RECT d3drect;
   309     GLLOCKED_RECT locked;
   310     const Uint8 *src;
   311     Uint8 *dst;
   312     int row, length;
   313     HRESULT result;
   314 
   315     result =
   316         IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
   317                                        texture->h, 1, 0,
   318                                        PixelFormatToGLFMT(texture->format),
   319                                        GLPOOL_SYSTEMMEM, &temp, NULL);
   320     if (FAILED(result)) {
   321         GL_SetError("CreateTexture()", result);
   322         return -1;
   323     }
   324 
   325     d3drect.left = rect->x;
   326     d3drect.right = rect->x + rect->w;
   327     d3drect.top = rect->y;
   328     d3drect.bottom = rect->y + rect->h;
   329 
   330     result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
   331     if (FAILED(result)) {
   332         IDirect3DTexture9_Release(temp);
   333         GL_SetError("LockRect()", result);
   334         return -1;
   335     }
   336 
   337     src = pixels;
   338     dst = locked.pBits;
   339     length = rect->w * SDL_BYTESPERPIXEL(texture->format);
   340     for (row = 0; row < rect->h; ++row) {
   341         SDL_memcpy(dst, src, length);
   342         src += pitch;
   343         dst += locked.Pitch;
   344     }
   345     IDirect3DTexture9_UnlockRect(temp, 0);
   346 
   347     result =
   348         IDirect3DDevice9_UpdateTexture(renderdata->device,
   349                                        (IDirect3DBaseTexture9 *) temp,
   350                                        (IDirect3DBaseTexture9 *) data->
   351                                        texture);
   352     IDirect3DTexture9_Release(temp);
   353     if (FAILED(result)) {
   354         GL_SetError("UpdateTexture()", result);
   355         return -1;
   356     }
   357     return 0;
   358 }
   359 
   360 static int
   361 GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   362                const SDL_Rect * rect, int markDirty, void **pixels,
   363                int *pitch)
   364 {
   365     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   366     RECT d3drect;
   367     GLLOCKED_RECT locked;
   368     HRESULT result;
   369 
   370     if (texture->access != SDL_TextureAccess_Local) {
   371         SDL_SetError("Can't lock remote video memory");
   372         return -1;
   373     }
   374 
   375     d3drect.left = rect->x;
   376     d3drect.right = rect->x + rect->w;
   377     d3drect.top = rect->y;
   378     d3drect.bottom = rect->y + rect->h;
   379 
   380     result =
   381         IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
   382                                    markDirty ? 0 : GLLOCK_NO_DIRTY_UPDATE);
   383     if (FAILED(result)) {
   384         GL_SetError("LockRect()", result);
   385         return -1;
   386     }
   387     *pixels = locked.pBits;
   388     *pitch = locked.Pitch;
   389     return 0;
   390 }
   391 
   392 static void
   393 GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   394 {
   395     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   396 
   397     IDirect3DTexture9_UnlockRect(data->texture, 0);
   398 }
   399 
   400 static void
   401 GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
   402                 const SDL_Rect * rects)
   403 {
   404     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   405     RECT d3drect;
   406     int i;
   407 
   408     for (i = 0; i < numrects; ++i) {
   409         const SDL_Rect *rect = &rects[i];
   410 
   411         d3drect.left = rect->x;
   412         d3drect.right = rect->x + rect->w;
   413         d3drect.top = rect->y;
   414         d3drect.bottom = rect->y + rect->h;
   415 
   416         IDirect3DTexture9_AddDirtyRect(data->texture, &d3drect);
   417     }
   418 }
   419 
   420 static int
   421 GL_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 color)
   422 {
   423     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   424     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   425     GLclampf r, g, b, a;
   426 
   427     a = ((GLclampf) ((color >> 24) & 0xFF)) / 255.0f;
   428     r = ((GLclampf) ((color >> 16) & 0xFF)) / 255.0f;
   429     g = ((GLclampf) ((color >> 8) & 0xFF)) / 255.0f;
   430     b = ((GLclampf) (color & 0xFF)) / 255.0f;
   431 
   432     glClearColor(r, g, b, a);
   433     glViewport(rect->x, window->h - rect->y, rect->w, rect->h);
   434     glClear(GL_COLOR_BUFFER_BIT);
   435     glViewport(0, 0, window->w, window->h);
   436     return 0;
   437 }
   438 
   439 static int
   440 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   441               const SDL_Rect * srcrect, const SDL_Rect * dstrect,
   442               int blendMode, int scaleMode)
   443 {
   444     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   445     GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
   446     int minx, miny, maxx, maxy;
   447     GLfloat minu, maxu, minv, maxv;
   448 
   449     minx = dstrect->x;
   450     miny = dstrect->y;
   451     maxx = dstrect->x + dstrect->w;
   452     maxy = dstrect->y + dstrect->h;
   453 
   454     minu = (GLfloat) srcrect->x / texture->w;
   455     maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
   456     minv = (GLfloat) srcrect->y / texture->h;
   457     maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
   458 
   459     glBindTexture(GL_TEXTURE_2D, texturedata->texture);
   460 
   461     switch (blendMode) {
   462     case SDL_TextureBlendMode_None:
   463         glDisable(GL_BLEND);
   464         break;
   465     case SDL_TextureBlendMode_Mask:
   466     case SDL_TextureBlendMode_Blend:
   467         glEnable(GL_BLEND);
   468         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   469         break;
   470     case SDL_TextureBlendMode_Add:
   471         glEnable(GL_BLEND);
   472         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
   473         break;
   474     case SDL_TextureBlendMode_Mod:
   475         glEnable(GL_BLEND);
   476         glBlendFunc(GL_ZERO, GL_SRC_COLOR);
   477         break;
   478     }
   479 
   480     switch (scaleMode) {
   481     case SDL_TextureScaleMode_None:
   482     case SDL_TextureScaleMode_Fast:
   483         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   484         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   485         break;
   486     case SDL_TextureScaleMode_Slow:
   487     case SDL_TextureScaleMode_Best:
   488         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   489         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   490         break;
   491     }
   492 
   493     glBegin(GL_TRIANGLE_STRIP);
   494     glTexCoord2f(minu, minv);
   495     glVertex2i(minx, miny);
   496     glTexCoord2f(maxu, minv);
   497     glVertex2i(maxx, miny);
   498     glTexCoord2f(minu, maxv);
   499     glVertex2i(miny, maxy);
   500     glTexCoord2f(maxu, maxv);
   501     glVertex2i(maxx, maxy);
   502     glEnd();
   503 
   504     return 0;
   505 }
   506 
   507 static void
   508 GL_RenderPresent(SDL_Renderer * renderer)
   509 {
   510     SDL_GL_SwapWindow(renderer->window);
   511 }
   512 
   513 static void
   514 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   515 {
   516     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   517 
   518     if (!data) {
   519         return;
   520     }
   521     if (data->texture) {
   522         IDirect3DTexture9_Release(data->texture);
   523     }
   524     SDL_free(data);
   525     texture->driverdata = NULL;
   526 }
   527 
   528 void
   529 GL_DestroyRenderer(SDL_Renderer * renderer)
   530 {
   531     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   532 
   533     if (data) {
   534         if (data->device) {
   535             IDirect3DDevice9_Release(data->device);
   536         }
   537         SDL_free(data);
   538     }
   539     SDL_free(renderer);
   540 }
   541 
   542 #endif /* 0 */
   543 #endif /* SDL_VIDEO_OPENGL */
   544 
   545 /* vi: set ts=4 sw=4 expandtab: */