diff src/render/direct3d/SDL_d3drender.c @ 5159:307ccc9c135e

Made it possible to create a texture of any format, even if not supported by the renderer. This allows me to reduce the set of formats supported by the renderers to the most optimal set, for a nice speed boost.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 03 Feb 2011 00:19:40 -0800
parents fb424691cfc7
children 657543cc92f9
line wrap: on
line diff
--- a/src/render/direct3d/SDL_d3drender.c	Wed Feb 02 22:55:12 2011 -0800
+++ b/src/render/direct3d/SDL_d3drender.c	Thu Feb 03 00:19:40 2011 -0800
@@ -28,7 +28,6 @@
 #include "SDL_loadso.h"
 #include "SDL_syswm.h"
 #include "../SDL_sysrender.h"
-#include "../../video/SDL_yuv_sw_c.h"
 
 #if SDL_VIDEO_RENDER_D3D
 #define D3D_DEBUG_INFO
@@ -89,7 +88,8 @@
 
 /* Direct3D renderer implementation */
 
-#if 1                           /* This takes more memory but you won't lose your texture data */
+#if 1
+/* This takes more memory but you won't lose your texture data */
 #define D3DPOOL_SDL    D3DPOOL_MANAGED
 #define SDL_MEMORY_POOL_MANAGED
 #else
@@ -99,18 +99,12 @@
 
 static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int D3D_QueryTexturePixels(SDL_Renderer * renderer,
-                                  SDL_Texture * texture, void **pixels,
-                                  int *pitch);
 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                              const SDL_Rect * rect, const void *pixels,
                              int pitch);
 static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
-                           const SDL_Rect * rect, int markDirty,
-                           void **pixels, int *pitch);
+                           const SDL_Rect * rect, void **pixels, int *pitch);
 static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static void D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
-                             int numrects, const SDL_Rect * rects);
 static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
                                 const SDL_Point * points, int count);
 static int D3D_RenderDrawLines(SDL_Renderer * renderer,
@@ -134,8 +128,8 @@
     {
      "d3d",
      (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
-     0,
-     {0},
+     1,
+     {SDL_PIXELFORMAT_ARGB8888},
      0,
      0}
 };
@@ -152,7 +146,6 @@
 
 typedef struct
 {
-    SDL_SW_YUVTexture *yuv;
     Uint32 format;
     IDirect3DTexture9 *texture;
 } D3D_TextureData;
@@ -248,113 +241,30 @@
 PixelFormatToD3DFMT(Uint32 format)
 {
     switch (format) {
-    case SDL_PIXELFORMAT_INDEX8:
-        return D3DFMT_P8;
-    case SDL_PIXELFORMAT_RGB332:
-        return D3DFMT_R3G3B2;
-    case SDL_PIXELFORMAT_RGB444:
-        return D3DFMT_X4R4G4B4;
-    case SDL_PIXELFORMAT_RGB555:
-        return D3DFMT_X1R5G5B5;
-    case SDL_PIXELFORMAT_ARGB4444:
-        return D3DFMT_A4R4G4B4;
-    case SDL_PIXELFORMAT_ARGB1555:
-        return D3DFMT_A1R5G5B5;
     case SDL_PIXELFORMAT_RGB565:
         return D3DFMT_R5G6B5;
     case SDL_PIXELFORMAT_RGB888:
         return D3DFMT_X8R8G8B8;
     case SDL_PIXELFORMAT_ARGB8888:
         return D3DFMT_A8R8G8B8;
-    case SDL_PIXELFORMAT_ARGB2101010:
-        return D3DFMT_A2R10G10B10;
-    case SDL_PIXELFORMAT_YV12:
-        return MAKEFOURCC('Y','V','1','2');
-    case SDL_PIXELFORMAT_IYUV:
-        return MAKEFOURCC('I','4','2','0');
-    case SDL_PIXELFORMAT_UYVY:
-        return D3DFMT_UYVY;
-    case SDL_PIXELFORMAT_YUY2:
-        return D3DFMT_YUY2;
     default:
         return D3DFMT_UNKNOWN;
     }
 }
 
-static SDL_bool
-D3D_IsTextureFormatAvailable(IDirect3D9 * d3d, UINT adapter,
-                             D3DFORMAT display_format,
-                             D3DFORMAT texture_format)
+static Uint32
+D3DFMTToPixelFormat(D3DFORMAT format)
 {
-    HRESULT result;
-
-    result = IDirect3D9_CheckDeviceFormat(d3d, adapter,
-                                          D3DDEVTYPE_HAL,
-                                          display_format,
-                                          0,
-                                          D3DRTYPE_TEXTURE,
-                                          texture_format);
-    return FAILED(result) ? SDL_FALSE : SDL_TRUE;
-}
-
-static void
-UpdateYUVTextureData(SDL_Texture * texture)
-{
-    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
-    SDL_Rect rect;
-    RECT d3drect;
-    D3DLOCKED_RECT locked;
-    HRESULT result;
-
-    d3drect.left = 0;
-    d3drect.right = texture->w;
-    d3drect.top = 0;
-    d3drect.bottom = texture->h;
-
-    result =
-        IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
-    if (FAILED(result)) {
-        return;
+    switch (format) {
+    case D3DFMT_R5G6B5:
+        return SDL_PIXELFORMAT_RGB565;
+    case D3DFMT_X8R8G8B8:
+        return SDL_PIXELFORMAT_RGB888;
+    case D3DFMT_A8R8G8B8:
+        return SDL_PIXELFORMAT_ARGB8888;
+    default:
+        return SDL_PIXELFORMAT_UNKNOWN;
     }
-
-    rect.x = 0;
-    rect.y = 0;
-    rect.w = texture->w;
-    rect.h = texture->h;
-    SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
-                        texture->h, locked.pBits, locked.Pitch);
-
-    IDirect3DTexture9_UnlockRect(data->texture, 0);
-}
-
-static void
-D3D_AddTextureFormats(D3D_RenderData *data, SDL_RendererInfo *info)
-{
-    int i;
-    int formats[] = {
-        SDL_PIXELFORMAT_RGB332,
-        SDL_PIXELFORMAT_RGB444,
-        SDL_PIXELFORMAT_RGB555,
-        SDL_PIXELFORMAT_ARGB4444,
-        SDL_PIXELFORMAT_ARGB1555,
-        SDL_PIXELFORMAT_RGB565,
-        SDL_PIXELFORMAT_RGB888,
-        SDL_PIXELFORMAT_ARGB8888,
-        SDL_PIXELFORMAT_ARGB2101010,
-    };
-
-    info->num_texture_formats = 0;
-    for (i = 0; i < SDL_arraysize(formats); ++i) {
-        if (D3D_IsTextureFormatAvailable
-            (data->d3d, data->adapter, data->pparams.BackBufferFormat, PixelFormatToD3DFMT(formats[i]))) {
-            info->texture_formats[info->num_texture_formats++] = formats[i];
-        }
-    }
-    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YV12;
-    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
-    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2;
-    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
-    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU;
 }
 
 SDL_Renderer *
@@ -367,6 +277,9 @@
     D3DPRESENT_PARAMETERS pparams;
     IDirect3DSwapChain9 *chain;
     D3DCAPS9 caps;
+    Uint32 window_flags;
+    int w, h;
+    SDL_DisplayMode fullscreen_mode;
 
     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
     if (!renderer) {
@@ -404,11 +317,9 @@
     }
 
     renderer->CreateTexture = D3D_CreateTexture;
-    renderer->QueryTexturePixels = D3D_QueryTexturePixels;
     renderer->UpdateTexture = D3D_UpdateTexture;
     renderer->LockTexture = D3D_LockTexture;
     renderer->UnlockTexture = D3D_UnlockTexture;
-    renderer->DirtyTexture = D3D_DirtyTexture;
     renderer->RenderDrawPoints = D3D_RenderDrawPoints;
     renderer->RenderDrawLines = D3D_RenderDrawLines;
     renderer->RenderFillRects = D3D_RenderFillRects;
@@ -427,23 +338,27 @@
     SDL_VERSION(&windowinfo.version);
     SDL_GetWindowWMInfo(window, &windowinfo);
 
+    window_flags = SDL_GetWindowFlags(window);
+    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetWindowDisplayMode(window, &fullscreen_mode);
+
     SDL_zero(pparams);
     pparams.hDeviceWindow = windowinfo.info.win.window;
-    pparams.BackBufferWidth = window->w;
-    pparams.BackBufferHeight = window->h;
-    if (window->flags & SDL_WINDOW_FULLSCREEN) {
+    pparams.BackBufferWidth = w;
+    pparams.BackBufferHeight = h;
+    if (window_flags & SDL_WINDOW_FULLSCREEN) {
         pparams.BackBufferFormat =
-            PixelFormatToD3DFMT(window->fullscreen_mode.format);
+            PixelFormatToD3DFMT(fullscreen_mode.format);
     } else {
         pparams.BackBufferFormat = D3DFMT_UNKNOWN;
     }
     pparams.BackBufferCount = 1;
     pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
 
-    if (window->flags & SDL_WINDOW_FULLSCREEN) {
+    if (window_flags & SDL_WINDOW_FULLSCREEN) {
         pparams.Windowed = FALSE;
         pparams.FullScreen_RefreshRateInHz =
-            window->fullscreen_mode.refresh_rate;
+            fullscreen_mode.refresh_rate;
     } else {
         pparams.Windowed = TRUE;
         pparams.FullScreen_RefreshRateInHz = 0;
@@ -494,8 +409,6 @@
     }
     data->pparams = pparams;
 
-    D3D_AddTextureFormats(data, &renderer->info);
-
     IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
     renderer->info.max_texture_width = caps.MaxTextureWidth;
     renderer->info.max_texture_height = caps.MaxTextureHeight;
@@ -594,22 +507,7 @@
 
     texture->driverdata = data;
 
-    if (SDL_ISPIXELFORMAT_FOURCC(texture->format) &&
-        (texture->format != SDL_PIXELFORMAT_YUY2 ||
-         !D3D_IsTextureFormatAvailable(renderdata->d3d, renderdata->adapter,
-                                       display_format, PixelFormatToD3DFMT(texture->format)))
-        && (texture->format != SDL_PIXELFORMAT_YVYU
-            || !D3D_IsTextureFormatAvailable(renderdata->d3d, renderdata->adapter,
-                                             display_format, PixelFormatToD3DFMT(texture->format)))) {
-        data->yuv =
-            SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
-        if (!data->yuv) {
-            return -1;
-        }
-        data->format = SDL_GetWindowPixelFormat(window);
-    } else {
-        data->format = texture->format;
-    }
+    data->format = texture->format;
 
     result =
         IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
@@ -625,153 +523,118 @@
 }
 
 static int
-D3D_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
-                       void **pixels, int *pitch)
-{
-    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
-
-    if (data->yuv) {
-        return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
-    } else {
-        /* D3D textures don't have their pixels hanging out */
-        return -1;
-    }
-}
-
-static int
 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                   const SDL_Rect * rect, const void *pixels, int pitch)
 {
     D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
     D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
 
-    if (data->yuv) {
-        if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
-            return -1;
-        }
-        UpdateYUVTextureData(texture);
-        return 0;
-    } else {
 #ifdef SDL_MEMORY_POOL_DEFAULT
-        IDirect3DTexture9 *temp;
-        RECT d3drect;
-        D3DLOCKED_RECT locked;
-        const Uint8 *src;
-        Uint8 *dst;
-        int row, length;
-        HRESULT result;
+    IDirect3DTexture9 *temp;
+    RECT d3drect;
+    D3DLOCKED_RECT locked;
+    const Uint8 *src;
+    Uint8 *dst;
+    int row, length;
+    HRESULT result;
 
-        result =
-            IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
-                                           texture->h, 1, 0,
-                                           PixelFormatToD3DFMT(texture->
-                                                               format),
-                                           D3DPOOL_SYSTEMMEM, &temp, NULL);
-        if (FAILED(result)) {
-            D3D_SetError("CreateTexture()", result);
-            return -1;
-        }
+    result =
+        IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
+                                       texture->h, 1, 0,
+                                       PixelFormatToD3DFMT(texture-> format),
+                                       D3DPOOL_SYSTEMMEM, &temp, NULL);
+    if (FAILED(result)) {
+        D3D_SetError("CreateTexture()", result);
+        return -1;
+    }
 
-        d3drect.left = rect->x;
-        d3drect.right = rect->x + rect->w;
-        d3drect.top = rect->y;
-        d3drect.bottom = rect->y + rect->h;
+    d3drect.left = rect->x;
+    d3drect.right = rect->x + rect->w;
+    d3drect.top = rect->y;
+    d3drect.bottom = rect->y + rect->h;
 
-        result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
-        if (FAILED(result)) {
-            IDirect3DTexture9_Release(temp);
-            D3D_SetError("LockRect()", result);
-            return -1;
-        }
+    result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
+    if (FAILED(result)) {
+        IDirect3DTexture9_Release(temp);
+        D3D_SetError("LockRect()", result);
+        return -1;
+    }
 
-        src = pixels;
-        dst = locked.pBits;
-        length = rect->w * SDL_BYTESPERPIXEL(texture->format);
-        for (row = 0; row < rect->h; ++row) {
-            SDL_memcpy(dst, src, length);
-            src += pitch;
-            dst += locked.Pitch;
-        }
-        IDirect3DTexture9_UnlockRect(temp, 0);
+    src = pixels;
+    dst = locked.pBits;
+    length = rect->w * SDL_BYTESPERPIXEL(texture->format);
+    for (row = 0; row < rect->h; ++row) {
+        SDL_memcpy(dst, src, length);
+        src += pitch;
+        dst += locked.Pitch;
+    }
+    IDirect3DTexture9_UnlockRect(temp, 0);
 
-        result =
-            IDirect3DDevice9_UpdateTexture(renderdata->device,
-                                           (IDirect3DBaseTexture9 *) temp,
-                                           (IDirect3DBaseTexture9 *)
-                                           data->texture);
-        IDirect3DTexture9_Release(temp);
-        if (FAILED(result)) {
-            D3D_SetError("UpdateTexture()", result);
-            return -1;
-        }
+    result =
+        IDirect3DDevice9_UpdateTexture(renderdata->device,
+                                       (IDirect3DBaseTexture9 *) temp,
+                                       (IDirect3DBaseTexture9 *)
+                                       data->texture);
+    IDirect3DTexture9_Release(temp);
+    if (FAILED(result)) {
+        D3D_SetError("UpdateTexture()", result);
+        return -1;
+    }
 #else
-        RECT d3drect;
-        D3DLOCKED_RECT locked;
-        const Uint8 *src;
-        Uint8 *dst;
-        int row, length;
-        HRESULT result;
+    RECT d3drect;
+    D3DLOCKED_RECT locked;
+    const Uint8 *src;
+    Uint8 *dst;
+    int row, length;
+    HRESULT result;
 
-        d3drect.left = rect->x;
-        d3drect.right = rect->x + rect->w;
-        d3drect.top = rect->y;
-        d3drect.bottom = rect->y + rect->h;
+    d3drect.left = rect->x;
+    d3drect.right = rect->x + rect->w;
+    d3drect.top = rect->y;
+    d3drect.bottom = rect->y + rect->h;
 
-        result =
-            IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
-                                       0);
-        if (FAILED(result)) {
-            D3D_SetError("LockRect()", result);
-            return -1;
-        }
+    result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
+    if (FAILED(result)) {
+        D3D_SetError("LockRect()", result);
+        return -1;
+    }
 
-        src = pixels;
-        dst = locked.pBits;
-        length = rect->w * SDL_BYTESPERPIXEL(texture->format);
-        for (row = 0; row < rect->h; ++row) {
-            SDL_memcpy(dst, src, length);
-            src += pitch;
-            dst += locked.Pitch;
-        }
-        IDirect3DTexture9_UnlockRect(data->texture, 0);
+    src = pixels;
+    dst = locked.pBits;
+    length = rect->w * SDL_BYTESPERPIXEL(texture->format);
+    for (row = 0; row < rect->h; ++row) {
+        SDL_memcpy(dst, src, length);
+        src += pitch;
+        dst += locked.Pitch;
+    }
+    IDirect3DTexture9_UnlockRect(data->texture, 0);
 #endif // SDL_MEMORY_POOL_DEFAULT
 
-        return 0;
-    }
+    return 0;
 }
 
 static int
 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
-                const SDL_Rect * rect, int markDirty, void **pixels,
-                int *pitch)
+                const SDL_Rect * rect, void **pixels, int *pitch)
 {
     D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
+    RECT d3drect;
+    D3DLOCKED_RECT locked;
+    HRESULT result;
 
-    if (data->yuv) {
-        return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
-                                     pitch);
-    } else {
-        RECT d3drect;
-        D3DLOCKED_RECT locked;
-        HRESULT result;
+    d3drect.left = rect->x;
+    d3drect.right = rect->x + rect->w;
+    d3drect.top = rect->y;
+    d3drect.bottom = rect->y + rect->h;
 
-        d3drect.left = rect->x;
-        d3drect.right = rect->x + rect->w;
-        d3drect.top = rect->y;
-        d3drect.bottom = rect->y + rect->h;
-
-        result =
-            IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
-                                       markDirty ? 0 :
-                                       D3DLOCK_NO_DIRTY_UPDATE);
-        if (FAILED(result)) {
-            D3D_SetError("LockRect()", result);
-            return -1;
-        }
-        *pixels = locked.pBits;
-        *pitch = locked.Pitch;
-        return 0;
+    result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
+    if (FAILED(result)) {
+        D3D_SetError("LockRect()", result);
+        return -1;
     }
+    *pixels = locked.pBits;
+    *pitch = locked.Pitch;
+    return 0;
 }
 
 static void
@@ -779,32 +642,7 @@
 {
     D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
 
-    if (data->yuv) {
-        SDL_SW_UnlockYUVTexture(data->yuv);
-        UpdateYUVTextureData(texture);
-    } else {
-        IDirect3DTexture9_UnlockRect(data->texture, 0);
-    }
-}
-
-static void
-D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
-                 const SDL_Rect * rects)
-{
-    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
-    RECT d3drect;
-    int i;
-
-    for (i = 0; i < numrects; ++i) {
-        const SDL_Rect *rect = &rects[i];
-
-        d3drect.left = rect->x;
-        d3drect.right = rect->x + rect->w;
-        d3drect.top = rect->y;
-        d3drect.bottom = rect->y + rect->h;
-
-        IDirect3DTexture9_AddDirtyRect(data->texture, &d3drect);
-    }
+    IDirect3DTexture9_UnlockRect(data->texture, 0);
 }
 
 static void
@@ -1123,8 +961,6 @@
                      Uint32 format, void * pixels, int pitch)
 {
     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
-    SDL_Window *window = renderer->window;
-    SDL_VideoDisplay *display = window->display;
     D3DSURFACE_DESC desc;
     LPDIRECT3DSURFACE9 backBuffer;
     LPDIRECT3DSURFACE9 surface;
@@ -1174,7 +1010,7 @@
     }
 
     SDL_ConvertPixels(rect->w, rect->h,
-                      display->current_mode.format, locked.pBits, locked.Pitch,
+                      D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
                       format, pixels, pitch);
 
     IDirect3DSurface9_UnlockRect(surface);
@@ -1227,9 +1063,6 @@
     if (!data) {
         return;
     }
-    if (data->yuv) {
-        SDL_SW_DestroyYUVTexture(data->yuv);
-    }
     if (data->texture) {
         IDirect3DTexture9_Release(data->texture);
     }