diff src/video/win32/SDL_d3drender.c @ 1903:f132024010be

More of the Direct3D renderer is implemented, I'm not sure why it's not showing texture copies yet...
author Sam Lantinga <slouken@libsdl.org>
date Fri, 14 Jul 2006 06:40:53 +0000
parents f1828a500391
children 1a713f9d1f71
line wrap: on
line diff
--- a/src/video/win32/SDL_d3drender.c	Thu Jul 13 08:15:35 2006 +0000
+++ b/src/video/win32/SDL_d3drender.c	Fri Jul 14 06:40:53 2006 +0000
@@ -24,7 +24,6 @@
 #if SDL_VIDEO_RENDER_D3D
 
 #include "SDL_win32video.h"
-#include "../SDL_yuv_sw_c.h"
 
 /* Direct3D renderer implementation */
 
@@ -32,9 +31,6 @@
                                             Uint32 flags);
 static int SDL_D3D_CreateTexture(SDL_Renderer * renderer,
                                  SDL_Texture * texture);
-static int SDL_D3D_QueryTexturePixels(SDL_Renderer * renderer,
-                                      SDL_Texture * texture, void **pixels,
-                                      int *pitch);
 static int SDL_D3D_SetTexturePalette(SDL_Renderer * renderer,
                                      SDL_Texture * texture,
                                      const SDL_Color * colors, int firstcolor,
@@ -85,19 +81,20 @@
      (SDL_TextureBlendMode_None |
       SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend),
      (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast),
-     11,
+     12,
      {
       SDL_PixelFormat_Index8,
+      SDL_PixelFormat_RGB332,
+      SDL_PixelFormat_RGB444,
       SDL_PixelFormat_RGB555,
+      SDL_PixelFormat_ARGB4444,
+      SDL_PixelFormat_ARGB1555,
       SDL_PixelFormat_RGB565,
       SDL_PixelFormat_RGB888,
-      SDL_PixelFormat_BGR888,
       SDL_PixelFormat_ARGB8888,
-      SDL_PixelFormat_RGBA8888,
-      SDL_PixelFormat_ABGR8888,
-      SDL_PixelFormat_BGRA8888,
-      SDL_PixelFormat_YUY2,
-      SDL_PixelFormat_UYVY},
+      SDL_PixelFormat_ARGB2101010,
+      SDL_PixelFormat_UYVY,
+      SDL_PixelFormat_YUY2},
      0,
      0}
 };
@@ -110,9 +107,15 @@
 
 typedef struct
 {
-    SDL_SW_YUVTexture *yuv;
+    IDirect3DTexture9 *texture;
 } SDL_D3D_TextureData;
 
+typedef struct
+{
+    float x, y, z;
+    float tu, tv;
+} Vertex;
+
 static void
 D3D_SetError(const char *prefix, HRESULT result)
 {
@@ -192,18 +195,37 @@
     SDL_SetError("%s: %s", prefix, error);
 }
 
-static void
-UpdateYUVTextureData(SDL_Texture * texture)
+static D3DFORMAT
+PixelFormatToD3DFMT(Uint32 format)
 {
-    SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
-    SDL_Rect rect;
-
-    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, data->pixels, data->pitch);
+    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_UYVY:
+        return D3DFMT_UYVY;
+    case SDL_PixelFormat_YUY2:
+        return D3DFMT_YUY2;
+    default:
+        return D3DFMT_UNKNOWN;
+    }
 }
 
 void
@@ -243,7 +265,6 @@
     SDL_zerop(data);
 
     renderer->CreateTexture = SDL_D3D_CreateTexture;
-    renderer->QueryTexturePixels = SDL_D3D_QueryTexturePixels;
     renderer->SetTexturePalette = SDL_D3D_SetTexturePalette;
     renderer->GetTexturePalette = SDL_D3D_GetTexturePalette;
     renderer->UpdateTexture = SDL_D3D_UpdateTexture;
@@ -267,7 +288,12 @@
     SDL_zero(pparams);
     pparams.BackBufferWidth = window->w;
     pparams.BackBufferHeight = window->h;
-    pparams.BackBufferFormat = D3DFMT_UNKNOWN;  /* FIXME */
+    if (window->flags & SDL_WINDOW_FULLSCREEN) {
+        pparams.BackBufferFormat =
+            PixelFormatToD3DFMT(display->fullscreen_mode->format);
+    } else {
+        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
+    }
     if (flags & SDL_Renderer_PresentFlip2) {
         pparams.BackBufferCount = 2;
         pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
@@ -283,10 +309,12 @@
     }
     if (window->flags & SDL_WINDOW_FULLSCREEN) {
         pparams.Windowed = FALSE;
+        pparams.FullScreen_RefreshRateInHz =
+            display->fullscreen_mode->refresh_rate;
     } else {
         pparams.Windowed = TRUE;
+        pparams.FullScreen_RefreshRateInHz = 0;
     }
-    pparams.FullScreen_RefreshRateInHz = 0;     /* FIXME */
     pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
 
     result = IDirect3D9_CreateDevice(videodata->d3d, D3DADAPTER_DEFAULT,        /* FIXME */
@@ -301,6 +329,11 @@
     }
     data->beginScene = SDL_TRUE;
 
+    /* Set up parameters for rendering */
+    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
+                                    D3DCULL_NONE);
+    IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZ | D3DFVF_TEX1);
+
     return renderer;
 }
 
@@ -312,6 +345,8 @@
     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
     SDL_D3D_TextureData *data;
+    D3DPOOL pool;
+    HRESULT result;
 
     data = (SDL_D3D_TextureData *) SDL_malloc(sizeof(*data));
     if (!data) {
@@ -322,20 +357,23 @@
 
     texture->driverdata = data;
 
-    return 0;
-}
+    if (texture->access == SDL_TextureAccess_Local) {
+        pool = D3DPOOL_MANAGED;
+    } else {
+        pool = D3DPOOL_DEFAULT;
+    }
+    result =
+        IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
+                                       texture->h, 1, 0,
+                                       PixelFormatToD3DFMT(texture->format),
+                                       pool, &data->texture, NULL);
+    if (FAILED(result)) {
+        SDL_free(data);
+        D3D_SetError("CreateTexture()", result);
+        return -1;
+    }
 
-static int
-SDL_D3D_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
-                           void **pixels, int *pitch)
-{
-    SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
-
-    if (data->yuv) {
-        return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
-    } else {
-        return 0;
-    }
+    return 0;
 }
 
 static int
@@ -347,12 +385,7 @@
         (SDL_D3D_RenderData *) renderer->driverdata;
     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
 
-    if (data->yuv) {
-        SDL_SetError("YUV textures don't have a palette");
-        return -1;
-    } else {
-        return 0;
-    }
+    return 0;
 }
 
 static int
@@ -361,12 +394,7 @@
 {
     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
 
-    if (data->yuv) {
-        SDL_SetError("YUV textures don't have a palette");
-        return -1;
-    } else {
-        return 0;
-    }
+    return 0;
 }
 
 static int
@@ -374,19 +402,59 @@
                       const SDL_Rect * rect, const void *pixels, int pitch)
 {
     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
+    SDL_D3D_RenderData *renderdata =
+        (SDL_D3D_RenderData *) renderer->driverdata;
+    IDirect3DTexture9 *temp;
+    RECT d3drect;
+    D3DLOCKED_RECT locked;
+    const Uint8 *src;
+    Uint8 *dst;
+    int row, length;
+    HRESULT result;
 
-    if (data->yuv) {
-        if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
-            return -1;
-        }
-        UpdateYUVTextureData(texture);
-        return 0;
-    } else {
-        SDL_D3D_RenderData *renderdata =
-            (SDL_D3D_RenderData *) renderer->driverdata;
+    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;
+
+    result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
+    if (FAILED(result)) {
+        IDirect3DTexture9_Release(temp);
+        D3D_SetError("LockRect()", result);
+        return -1;
+    }
 
-        return 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;
+    }
+    return 0;
 }
 
 static int
@@ -395,13 +463,30 @@
                     int *pitch)
 {
     SDL_D3D_TextureData *data = (SDL_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 {
+    if (texture->access != SDL_TextureAccess_Local) {
+        SDL_SetError("Can't lock remote video memory");
         return -1;
     }
+
+    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;
 }
 
 static void
@@ -409,16 +494,27 @@
 {
     SDL_D3D_TextureData *data = (SDL_D3D_TextureData *) texture->driverdata;
 
-    if (data->yuv) {
-        SDL_SW_UnlockYUVTexture(data->yuv);
-        UpdateYUVTextureData(texture);
-    }
+    IDirect3DTexture9_UnlockRect(data->texture, 0);
 }
 
 static void
 SDL_D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                      int numrects, const SDL_Rect * rects)
 {
+    SDL_D3D_TextureData *data = (SDL_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);
+    }
 }
 
 static void
@@ -441,11 +537,13 @@
     }
 
     d3drect.x1 = rect->x;
-    d3drect.x2 = rect->x+rect->w;
+    d3drect.x2 = rect->x + rect->w;
     d3drect.y1 = rect->y;
-    d3drect.y2 = rect->y+rect->h;
+    d3drect.y2 = rect->y + rect->h;
 
-    result = IDirect3DDevice9_Clear(data->device, 1, &d3drect, D3DCLEAR_TARGET, (D3DCOLOR) color, 1.0f, 0);
+    result =
+        IDirect3DDevice9_Clear(data->device, 1, &d3drect, D3DCLEAR_TARGET,
+                               (D3DCOLOR) color, 1.0f, 0);
     if (FAILED(result)) {
         D3D_SetError("Clear()", result);
         return -1;
@@ -461,11 +559,62 @@
     SDL_D3D_RenderData *data = (SDL_D3D_RenderData *) renderer->driverdata;
     SDL_D3D_TextureData *texturedata =
         (SDL_D3D_TextureData *) texture->driverdata;
+    float minx, miny, maxx, maxy;
+    float mintu, maxtu, mintv, maxtv;
+    Vertex vertices[4];
+    HRESULT result;
 
     if (data->beginScene) {
         IDirect3DDevice9_BeginScene(data->device);
         data->beginScene = SDL_FALSE;
     }
+
+    minx = (float) dstrect->x;
+    miny = (float) dstrect->y;
+    maxx = (float) dstrect->x + dstrect->w;
+    maxy = (float) dstrect->y + dstrect->h;
+
+    mintu = (float) srcrect->x / texture->w;
+    maxtu = (float) (srcrect->x + srcrect->w) / texture->w;
+    mintv = (float) srcrect->y / texture->h;
+    maxtv = (float) (srcrect->y + srcrect->h) / texture->h;
+
+    vertices[0].x = minx;
+    vertices[0].y = miny;
+    vertices[0].z = 0.0f;
+    vertices[0].tu = mintu;
+    vertices[0].tv = mintv;
+    vertices[1].x = maxx;
+    vertices[1].y = miny;
+    vertices[1].z = 0.0f;
+    vertices[1].tu = maxtu;
+    vertices[1].tv = mintv;
+    vertices[2].x = maxx;
+    vertices[2].y = maxy;
+    vertices[2].z = 0.0f;
+    vertices[2].tu = maxtu;
+    vertices[2].tv = maxtv;
+    vertices[3].x = minx;
+    vertices[3].y = maxy;
+    vertices[3].z = 0.0f;
+    vertices[3].tu = mintu;
+    vertices[3].tv = maxtv;
+
+    result =
+        IDirect3DDevice9_SetTexture(data->device, 0,
+                                    (IDirect3DBaseTexture9 *) texturedata->
+                                    texture);
+    if (FAILED(result)) {
+        D3D_SetError("SetTexture()", result);
+        return -1;
+    }
+    result =
+        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
+                                         vertices, sizeof(*vertices));
+    if (FAILED(result)) {
+        D3D_SetError("DrawPrimitiveUP()", result);
+        return -1;
+    }
     return 0;
 }
 
@@ -512,6 +661,9 @@
     if (!data) {
         return;
     }
+    if (data->texture) {
+        IDirect3DTexture9_Release(data->texture);
+    }
     SDL_free(data);
     texture->driverdata = NULL;
 }