src/render/direct3d/SDL_render_d3d.c
changeset 5297 1800dc39b74c
parent 5262 b530ef003506
child 5299 33987021a1ed
     1.1 --- a/src/render/direct3d/SDL_render_d3d.c	Mon Feb 14 11:50:18 2011 -0600
     1.2 +++ b/src/render/direct3d/SDL_render_d3d.c	Tue Feb 15 13:59:59 2011 -0800
     1.3 @@ -90,6 +90,8 @@
     1.4  /* Direct3D renderer implementation */
     1.5  
     1.6  static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
     1.7 +static void D3D_WindowEvent(SDL_Renderer * renderer,
     1.8 +                            const SDL_WindowEvent *event);
     1.9  static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.10  static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.11                               const SDL_Rect * rect, const void *pixels,
    1.12 @@ -97,13 +99,14 @@
    1.13  static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.14                             const SDL_Rect * rect, void **pixels, int *pitch);
    1.15  static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.16 -static void D3D_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect);
    1.17 +static int D3D_UpdateViewport(SDL_Renderer * renderer);
    1.18 +static int D3D_RenderClear(SDL_Renderer * renderer);
    1.19  static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
    1.20                                  const SDL_Point * points, int count);
    1.21  static int D3D_RenderDrawLines(SDL_Renderer * renderer,
    1.22                                 const SDL_Point * points, int count);
    1.23  static int D3D_RenderFillRects(SDL_Renderer * renderer,
    1.24 -                               const SDL_Rect ** rects, int count);
    1.25 +                               const SDL_Rect * rects, int count);
    1.26  static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    1.27                            const SDL_Rect * srcrect, const SDL_Rect * dstrect);
    1.28  static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    1.29 @@ -132,6 +135,7 @@
    1.30      IDirect3DDevice9 *device;
    1.31      UINT adapter;
    1.32      D3DPRESENT_PARAMETERS pparams;
    1.33 +    SDL_bool updateSize;
    1.34      SDL_bool beginScene;
    1.35  } D3D_RenderData;
    1.36  
    1.37 @@ -143,7 +147,6 @@
    1.38  typedef struct
    1.39  {
    1.40      float x, y, z;
    1.41 -    float rhw;
    1.42      DWORD color;
    1.43      float u, v;
    1.44  } Vertex;
    1.45 @@ -257,6 +260,74 @@
    1.46      }
    1.47  }
    1.48  
    1.49 +static int
    1.50 +D3D_Reset(SDL_Renderer * renderer)
    1.51 +{
    1.52 +    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
    1.53 +    HRESULT result;
    1.54 +
    1.55 +    result = IDirect3DDevice9_Reset(data->device, &data->pparams);
    1.56 +    if (FAILED(result)) {
    1.57 +        if (result == D3DERR_DEVICELOST) {
    1.58 +            /* Don't worry about it, we'll reset later... */
    1.59 +            return 0;
    1.60 +        } else {
    1.61 +            D3D_SetError("Reset()", result);
    1.62 +            return -1;
    1.63 +        }
    1.64 +    }
    1.65 +    IDirect3DDevice9_SetVertexShader(data->device, NULL);
    1.66 +    IDirect3DDevice9_SetFVF(data->device,
    1.67 +                            D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
    1.68 +    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
    1.69 +                                    D3DCULL_NONE);
    1.70 +    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
    1.71 +    return 0;
    1.72 +}
    1.73 +
    1.74 +static int
    1.75 +D3D_ActivateRenderer(SDL_Renderer * renderer)
    1.76 +{
    1.77 +    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
    1.78 +    HRESULT result;
    1.79 +
    1.80 +    if (data->updateSize) {
    1.81 +        SDL_Window *window = renderer->window;
    1.82 +        int w, h;
    1.83 +
    1.84 +        SDL_GetWindowSize(window, &w, &h);
    1.85 +        data->pparams.BackBufferWidth = w;
    1.86 +        data->pparams.BackBufferHeight = h;
    1.87 +        if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
    1.88 +            data->pparams.BackBufferFormat =
    1.89 +                PixelFormatToD3DFMT(SDL_GetWindowPixelFormat(window));
    1.90 +        } else {
    1.91 +            data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
    1.92 +        }
    1.93 +        if (D3D_Reset(renderer) < 0) {
    1.94 +            return -1;
    1.95 +        }
    1.96 +        D3D_UpdateViewport(renderer);
    1.97 +
    1.98 +        data->updateSize = SDL_FALSE;
    1.99 +    }
   1.100 +    if (data->beginScene) {
   1.101 +        result = IDirect3DDevice9_BeginScene(data->device);
   1.102 +        if (result == D3DERR_DEVICELOST) {
   1.103 +            if (D3D_Reset(renderer) < 0) {
   1.104 +                return -1;
   1.105 +            }
   1.106 +            result = IDirect3DDevice9_BeginScene(data->device);
   1.107 +        }
   1.108 +        if (FAILED(result)) {
   1.109 +            D3D_SetError("BeginScene()", result);
   1.110 +            return -1;
   1.111 +        }
   1.112 +        data->beginScene = SDL_FALSE;
   1.113 +    }
   1.114 +    return 0;
   1.115 +}
   1.116 +
   1.117  SDL_Renderer *
   1.118  D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
   1.119  {
   1.120 @@ -270,6 +341,7 @@
   1.121      Uint32 window_flags;
   1.122      int w, h;
   1.123      SDL_DisplayMode fullscreen_mode;
   1.124 +    D3DMATRIX matrix;
   1.125  
   1.126      renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   1.127      if (!renderer) {
   1.128 @@ -306,11 +378,13 @@
   1.129          return NULL;
   1.130      }
   1.131  
   1.132 +    renderer->WindowEvent = D3D_WindowEvent;
   1.133      renderer->CreateTexture = D3D_CreateTexture;
   1.134      renderer->UpdateTexture = D3D_UpdateTexture;
   1.135      renderer->LockTexture = D3D_LockTexture;
   1.136      renderer->UnlockTexture = D3D_UnlockTexture;
   1.137 -    renderer->SetClipRect = D3D_SetClipRect;
   1.138 +    renderer->UpdateViewport = D3D_UpdateViewport;
   1.139 +    renderer->RenderClear = D3D_RenderClear;
   1.140      renderer->RenderDrawPoints = D3D_RenderDrawPoints;
   1.141      renderer->RenderDrawLines = D3D_RenderDrawLines;
   1.142      renderer->RenderFillRects = D3D_RenderFillRects;
   1.143 @@ -405,7 +479,7 @@
   1.144      /* Set up parameters for rendering */
   1.145      IDirect3DDevice9_SetVertexShader(data->device, NULL);
   1.146      IDirect3DDevice9_SetFVF(data->device,
   1.147 -                            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
   1.148 +                            D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
   1.149      IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
   1.150      IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
   1.151                                      D3DCULL_NONE);
   1.152 @@ -430,55 +504,39 @@
   1.153      IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
   1.154                                            D3DTOP_DISABLE);
   1.155  
   1.156 +    /* Set an identity world and view matrix */
   1.157 +    matrix.m[0][0] = 1.0f;
   1.158 +    matrix.m[0][1] = 0.0f;
   1.159 +    matrix.m[0][2] = 0.0f;
   1.160 +    matrix.m[0][3] = 0.0f;
   1.161 +    matrix.m[1][0] = 0.0f;
   1.162 +    matrix.m[1][1] = 1.0f;
   1.163 +    matrix.m[1][2] = 0.0f;
   1.164 +    matrix.m[1][3] = 0.0f;
   1.165 +    matrix.m[2][0] = 0.0f;
   1.166 +    matrix.m[2][1] = 0.0f;
   1.167 +    matrix.m[2][2] = 1.0f;
   1.168 +    matrix.m[2][3] = 0.0f;
   1.169 +    matrix.m[3][0] = 0.0f;
   1.170 +    matrix.m[3][1] = 0.0f;
   1.171 +    matrix.m[3][2] = 0.0f;
   1.172 +    matrix.m[3][3] = 1.0f;
   1.173 +    IDirect3DDevice9_SetTransform(data->device, D3DTS_WORLD, &matrix);
   1.174 +    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, &matrix);
   1.175 +
   1.176      return renderer;
   1.177  }
   1.178  
   1.179 -static int
   1.180 -D3D_Reset(SDL_Renderer * renderer)
   1.181 +static void
   1.182 +D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   1.183  {
   1.184      D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.185 -    HRESULT result;
   1.186  
   1.187 -    result = IDirect3DDevice9_Reset(data->device, &data->pparams);
   1.188 -    if (FAILED(result)) {
   1.189 -        if (result == D3DERR_DEVICELOST) {
   1.190 -            /* Don't worry about it, we'll reset later... */
   1.191 -            return 0;
   1.192 -        } else {
   1.193 -            D3D_SetError("Reset()", result);
   1.194 -            return -1;
   1.195 -        }
   1.196 +    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
   1.197 +        data->updateSize = SDL_TRUE;
   1.198      }
   1.199 -    IDirect3DDevice9_SetVertexShader(data->device, NULL);
   1.200 -    IDirect3DDevice9_SetFVF(data->device,
   1.201 -                            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
   1.202 -    IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
   1.203 -                                    D3DCULL_NONE);
   1.204 -    IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
   1.205 -    return 0;
   1.206  }
   1.207  
   1.208 -/* FIXME: This needs to be called... when? */
   1.209 -#if 0
   1.210 -static int
   1.211 -D3D_DisplayModeChanged(SDL_Renderer * renderer)
   1.212 -{
   1.213 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.214 -    SDL_Window *window = renderer->window;
   1.215 -    SDL_VideoDisplay *display = window->display;
   1.216 -
   1.217 -    data->pparams.BackBufferWidth = window->w;
   1.218 -    data->pparams.BackBufferHeight = window->h;
   1.219 -    if (window->flags & SDL_WINDOW_FULLSCREEN) {
   1.220 -        data->pparams.BackBufferFormat =
   1.221 -            PixelFormatToD3DFMT(window->fullscreen_mode.format);
   1.222 -    } else {
   1.223 -        data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
   1.224 -    }
   1.225 -    return D3D_Reset(renderer);
   1.226 -}
   1.227 -#endif
   1.228 -
   1.229  static int
   1.230  D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.231  {
   1.232 @@ -604,25 +662,83 @@
   1.233      IDirect3DTexture9_UnlockRect(data->texture, 0);
   1.234  }
   1.235  
   1.236 -static void
   1.237 -D3D_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
   1.238 +static int
   1.239 +D3D_UpdateViewport(SDL_Renderer * renderer)
   1.240  {
   1.241      D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.242 +    D3DVIEWPORT9 viewport;
   1.243 +    D3DMATRIX matrix;
   1.244  
   1.245 -    if (rect) {
   1.246 -        RECT d3drect;
   1.247 +    /* Set the viewport */
   1.248 +    viewport.X = renderer->viewport.x;
   1.249 +    viewport.Y = renderer->viewport.y;
   1.250 +    viewport.Width = renderer->viewport.w;
   1.251 +    viewport.Height = renderer->viewport.h;
   1.252 +    viewport.MinZ = 0.0f;
   1.253 +    viewport.MaxZ = 1.0f;
   1.254 +    IDirect3DDevice9_SetViewport(data->device, &viewport);
   1.255  
   1.256 -        d3drect.left = rect->x;
   1.257 -        d3drect.right = rect->x + rect->w;
   1.258 -        d3drect.top = rect->y;
   1.259 -        d3drect.bottom = rect->y + rect->h;
   1.260 -        IDirect3DDevice9_SetScissorRect(data->device, &d3drect);
   1.261 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE,
   1.262 -                                        TRUE);
   1.263 -    } else {
   1.264 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE,
   1.265 -                                        FALSE);
   1.266 +    /* Set an orthographic projection matrix */
   1.267 +    matrix.m[0][0] = 2.0f / renderer->viewport.w;
   1.268 +    matrix.m[0][1] = 0.0f;
   1.269 +    matrix.m[0][2] = 0.0f;
   1.270 +    matrix.m[0][3] = 0.0f;
   1.271 +    matrix.m[1][0] = 0.0f;
   1.272 +    matrix.m[1][1] = -2.0f / renderer->viewport.h;
   1.273 +    matrix.m[1][2] = 0.0f;
   1.274 +    matrix.m[1][3] = 0.0f;
   1.275 +    matrix.m[2][0] = 0.0f;
   1.276 +    matrix.m[2][1] = 0.0f;
   1.277 +    matrix.m[2][2] = 1.0f;
   1.278 +    matrix.m[2][3] = 0.0f;
   1.279 +    matrix.m[3][0] = -1.0f;
   1.280 +    matrix.m[3][1] = 1.0f;
   1.281 +    matrix.m[3][2] = 0.0f;
   1.282 +    matrix.m[3][3] = 1.0f;
   1.283 +    IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
   1.284 +
   1.285 +    return 0;
   1.286 +}
   1.287 +
   1.288 +static int
   1.289 +D3D_RenderClear(SDL_Renderer * renderer)
   1.290 +{
   1.291 +    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.292 +    D3DVIEWPORT9 viewport;
   1.293 +    DWORD color;
   1.294 +    HRESULT result;
   1.295 +
   1.296 +    if (D3D_ActivateRenderer(renderer) < 0) {
   1.297 +        return -1;
   1.298      }
   1.299 +
   1.300 +    /* Clear is defined to clear the entire render target */
   1.301 +    viewport.X = 0;
   1.302 +    viewport.Y = 0;
   1.303 +    viewport.Width = data->pparams.BackBufferWidth;
   1.304 +    viewport.Height = data->pparams.BackBufferHeight;
   1.305 +    viewport.MinZ = 0.0f;
   1.306 +    viewport.MaxZ = 1.0f;
   1.307 +    IDirect3DDevice9_SetViewport(data->device, &viewport);
   1.308 +
   1.309 +    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   1.310 +
   1.311 +    result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
   1.312 +
   1.313 +    /* Reset the viewport */
   1.314 +    viewport.X = renderer->viewport.x;
   1.315 +    viewport.Y = renderer->viewport.y;
   1.316 +    viewport.Width = renderer->viewport.w;
   1.317 +    viewport.Height = renderer->viewport.h;
   1.318 +    viewport.MinZ = 0.0f;
   1.319 +    viewport.MaxZ = 1.0f;
   1.320 +    IDirect3DDevice9_SetViewport(data->device, &viewport);
   1.321 +
   1.322 +    if (FAILED(result)) {
   1.323 +        D3D_SetError("Clear()", result);
   1.324 +        return -1;
   1.325 +    }
   1.326 +    return 0;
   1.327  }
   1.328  
   1.329  static void
   1.330 @@ -670,9 +786,8 @@
   1.331      int i;
   1.332      HRESULT result;
   1.333  
   1.334 -    if (data->beginScene) {
   1.335 -        IDirect3DDevice9_BeginScene(data->device);
   1.336 -        data->beginScene = SDL_FALSE;
   1.337 +    if (D3D_ActivateRenderer(renderer) < 0) {
   1.338 +        return -1;
   1.339      }
   1.340  
   1.341      D3D_SetBlendMode(data, renderer->blendMode);
   1.342 @@ -692,7 +807,6 @@
   1.343          vertices[i].x = (float) points[i].x;
   1.344          vertices[i].y = (float) points[i].y;
   1.345          vertices[i].z = 0.0f;
   1.346 -        vertices[i].rhw = 1.0f;
   1.347          vertices[i].color = color;
   1.348          vertices[i].u = 0.0f;
   1.349          vertices[i].v = 0.0f;
   1.350 @@ -718,9 +832,8 @@
   1.351      int i;
   1.352      HRESULT result;
   1.353  
   1.354 -    if (data->beginScene) {
   1.355 -        IDirect3DDevice9_BeginScene(data->device);
   1.356 -        data->beginScene = SDL_FALSE;
   1.357 +    if (D3D_ActivateRenderer(renderer) < 0) {
   1.358 +        return -1;
   1.359      }
   1.360  
   1.361      D3D_SetBlendMode(data, renderer->blendMode);
   1.362 @@ -740,7 +853,6 @@
   1.363          vertices[i].x = (float) points[i].x;
   1.364          vertices[i].y = (float) points[i].y;
   1.365          vertices[i].z = 0.0f;
   1.366 -        vertices[i].rhw = 1.0f;
   1.367          vertices[i].color = color;
   1.368          vertices[i].u = 0.0f;
   1.369          vertices[i].v = 0.0f;
   1.370 @@ -766,7 +878,7 @@
   1.371  }
   1.372  
   1.373  static int
   1.374 -D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
   1.375 +D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * rects,
   1.376                      int count)
   1.377  {
   1.378      D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.379 @@ -776,9 +888,8 @@
   1.380      Vertex vertices[4];
   1.381      HRESULT result;
   1.382  
   1.383 -    if (data->beginScene) {
   1.384 -        IDirect3DDevice9_BeginScene(data->device);
   1.385 -        data->beginScene = SDL_FALSE;
   1.386 +    if (D3D_ActivateRenderer(renderer) < 0) {
   1.387 +        return -1;
   1.388      }
   1.389  
   1.390      D3D_SetBlendMode(data, renderer->blendMode);
   1.391 @@ -794,7 +905,7 @@
   1.392      color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   1.393  
   1.394      for (i = 0; i < count; ++i) {
   1.395 -        const SDL_Rect *rect = rects[i];
   1.396 +        const SDL_Rect *rect = &rects[i];
   1.397  
   1.398          minx = (float) rect->x;
   1.399          miny = (float) rect->y;
   1.400 @@ -804,7 +915,6 @@
   1.401          vertices[0].x = minx;
   1.402          vertices[0].y = miny;
   1.403          vertices[0].z = 0.0f;
   1.404 -        vertices[0].rhw = 1.0f;
   1.405          vertices[0].color = color;
   1.406          vertices[0].u = 0.0f;
   1.407          vertices[0].v = 0.0f;
   1.408 @@ -812,7 +922,6 @@
   1.409          vertices[1].x = maxx;
   1.410          vertices[1].y = miny;
   1.411          vertices[1].z = 0.0f;
   1.412 -        vertices[1].rhw = 1.0f;
   1.413          vertices[1].color = color;
   1.414          vertices[1].u = 0.0f;
   1.415          vertices[1].v = 0.0f;
   1.416 @@ -820,7 +929,6 @@
   1.417          vertices[2].x = maxx;
   1.418          vertices[2].y = maxy;
   1.419          vertices[2].z = 0.0f;
   1.420 -        vertices[2].rhw = 1.0f;
   1.421          vertices[2].color = color;
   1.422          vertices[2].u = 0.0f;
   1.423          vertices[2].v = 0.0f;
   1.424 @@ -828,7 +936,6 @@
   1.425          vertices[3].x = minx;
   1.426          vertices[3].y = maxy;
   1.427          vertices[3].z = 0.0f;
   1.428 -        vertices[3].rhw = 1.0f;
   1.429          vertices[3].color = color;
   1.430          vertices[3].u = 0.0f;
   1.431          vertices[3].v = 0.0f;
   1.432 @@ -857,9 +964,8 @@
   1.433      Vertex vertices[4];
   1.434      HRESULT result;
   1.435  
   1.436 -    if (data->beginScene) {
   1.437 -        IDirect3DDevice9_BeginScene(data->device);
   1.438 -        data->beginScene = SDL_FALSE;
   1.439 +    if (D3D_ActivateRenderer(renderer) < 0) {
   1.440 +        return -1;
   1.441      }
   1.442  
   1.443      minx = (float) dstrect->x - 0.5f;
   1.444 @@ -877,7 +983,6 @@
   1.445      vertices[0].x = minx;
   1.446      vertices[0].y = miny;
   1.447      vertices[0].z = 0.0f;
   1.448 -    vertices[0].rhw = 1.0f;
   1.449      vertices[0].color = color;
   1.450      vertices[0].u = minu;
   1.451      vertices[0].v = minv;
   1.452 @@ -885,7 +990,6 @@
   1.453      vertices[1].x = maxx;
   1.454      vertices[1].y = miny;
   1.455      vertices[1].z = 0.0f;
   1.456 -    vertices[1].rhw = 1.0f;
   1.457      vertices[1].color = color;
   1.458      vertices[1].u = maxu;
   1.459      vertices[1].v = minv;
   1.460 @@ -893,7 +997,6 @@
   1.461      vertices[2].x = maxx;
   1.462      vertices[2].y = maxy;
   1.463      vertices[2].z = 0.0f;
   1.464 -    vertices[2].rhw = 1.0f;
   1.465      vertices[2].color = color;
   1.466      vertices[2].u = maxu;
   1.467      vertices[2].v = maxv;
   1.468 @@ -901,7 +1004,6 @@
   1.469      vertices[3].x = minx;
   1.470      vertices[3].y = maxy;
   1.471      vertices[3].z = 0.0f;
   1.472 -    vertices[3].rhw = 1.0f;
   1.473      vertices[3].color = color;
   1.474      vertices[3].u = minu;
   1.475      vertices[3].v = maxv;