render: first shot at moving Direct3D 9 backend to new interface. Untested! SDL-ryan-batching-renderer
authorRyan C. Gordon <icculus@icculus.org>
Mon, 01 Oct 2018 01:23:02 -0400
branchSDL-ryan-batching-renderer
changeset 12278f0e949a32e2f
parent 12264 9727984170f7
child 12279 4b8721c990f9
render: first shot at moving Direct3D 9 backend to new interface. Untested!
src/render/direct3d/SDL_render_d3d.c
     1.1 --- a/src/render/direct3d/SDL_render_d3d.c	Sat Sep 29 04:00:38 2018 +0000
     1.2 +++ b/src/render/direct3d/SDL_render_d3d.c	Mon Oct 01 01:23:02 2018 -0400
     1.3 @@ -41,61 +41,23 @@
     1.4  
     1.5  #include "SDL_shaders_d3d.h"
     1.6  
     1.7 +typedef struct
     1.8 +{
     1.9 +    SDL_Rect viewport;
    1.10 +    SDL_bool viewport_dirty;
    1.11 +    SDL_Texture *texture;
    1.12 +    SDL_BlendMode blend;
    1.13 +    SDL_bool cliprect_enabled;
    1.14 +    SDL_bool cliprect_enabled_dirty;
    1.15 +    SDL_Rect cliprect;
    1.16 +    SDL_bool cliprect_dirty;
    1.17 +    SDL_bool is_copy_ex;
    1.18 +    LPDIRECT3DPIXELSHADER9 shader;
    1.19 +} D3D_DrawStateCache;
    1.20 +
    1.21  
    1.22  /* Direct3D renderer implementation */
    1.23  
    1.24 -static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
    1.25 -static void D3D_WindowEvent(SDL_Renderer * renderer,
    1.26 -                            const SDL_WindowEvent *event);
    1.27 -static SDL_bool D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
    1.28 -static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.29 -static int D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.30 -static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.31 -                             const SDL_Rect * rect, const void *pixels,
    1.32 -                             int pitch);
    1.33 -static int D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
    1.34 -                                const SDL_Rect * rect,
    1.35 -                                const Uint8 *Yplane, int Ypitch,
    1.36 -                                const Uint8 *Uplane, int Upitch,
    1.37 -                                const Uint8 *Vplane, int Vpitch);
    1.38 -static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.39 -                           const SDL_Rect * rect, void **pixels, int *pitch);
    1.40 -static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    1.41 -static int D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture);
    1.42 -static int D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
    1.43 -static int D3D_UpdateViewport(SDL_Renderer * renderer);
    1.44 -static int D3D_UpdateClipRect(SDL_Renderer * renderer);
    1.45 -static int D3D_RenderClear(SDL_Renderer * renderer);
    1.46 -static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
    1.47 -                                const SDL_FPoint * points, int count);
    1.48 -static int D3D_RenderDrawLines(SDL_Renderer * renderer,
    1.49 -                               const SDL_FPoint * points, int count);
    1.50 -static int D3D_RenderFillRects(SDL_Renderer * renderer,
    1.51 -                               const SDL_FRect * rects, int count);
    1.52 -static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    1.53 -                          const SDL_Rect * srcrect, const SDL_FRect * dstrect);
    1.54 -static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
    1.55 -                          const SDL_Rect * srcrect, const SDL_FRect * dstrect,
    1.56 -                          const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
    1.57 -static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    1.58 -                                Uint32 format, void * pixels, int pitch);
    1.59 -static void D3D_RenderPresent(SDL_Renderer * renderer);
    1.60 -static void D3D_DestroyTexture(SDL_Renderer * renderer,
    1.61 -                               SDL_Texture * texture);
    1.62 -static void D3D_DestroyRenderer(SDL_Renderer * renderer);
    1.63 -
    1.64 -
    1.65 -SDL_RenderDriver D3D_RenderDriver = {
    1.66 -    D3D_CreateRenderer,
    1.67 -    {
    1.68 -     "direct3d",
    1.69 -     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
    1.70 -     1,
    1.71 -     {SDL_PIXELFORMAT_ARGB8888},
    1.72 -     0,
    1.73 -     0}
    1.74 -};
    1.75 -
    1.76  typedef struct
    1.77  {
    1.78      void* d3dDLL;
    1.79 @@ -106,11 +68,17 @@
    1.80      SDL_bool updateSize;
    1.81      SDL_bool beginScene;
    1.82      SDL_bool enableSeparateAlphaBlend;
    1.83 +    SDL_bool supportsStreamOffset;
    1.84      D3DTEXTUREFILTERTYPE scaleMode[8];
    1.85      IDirect3DSurface9 *defaultRenderTarget;
    1.86      IDirect3DSurface9 *currentRenderTarget;
    1.87      void* d3dxDLL;
    1.88      LPDIRECT3DPIXELSHADER9 shaders[NUM_SHADERS];
    1.89 +    IDirect3DVertexBuffer9 vertexBuffers[8];
    1.90 +    GLsizeiptr vertexBufferSize[8];
    1.91 +    int currentVertexBuffer;
    1.92 +    SDL_bool reportedVboProblem;
    1.93 +    D3D_DrawStateCache drawstate;
    1.94  } D3D_RenderData;
    1.95  
    1.96  typedef struct
    1.97 @@ -265,9 +233,8 @@
    1.98      D3DMATRIX matrix;
    1.99  
   1.100      IDirect3DDevice9 *device = data->device;
   1.101 -
   1.102 +    IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
   1.103      IDirect3DDevice9_SetVertexShader(device, NULL);
   1.104 -    IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
   1.105      IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
   1.106      IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
   1.107      IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
   1.108 @@ -300,21 +267,10 @@
   1.109                                            D3DTOP_DISABLE);
   1.110  
   1.111      /* Set an identity world and view matrix */
   1.112 +    SDL_zero(matrix);
   1.113      matrix.m[0][0] = 1.0f;
   1.114 -    matrix.m[0][1] = 0.0f;
   1.115 -    matrix.m[0][2] = 0.0f;
   1.116 -    matrix.m[0][3] = 0.0f;
   1.117 -    matrix.m[1][0] = 0.0f;
   1.118      matrix.m[1][1] = 1.0f;
   1.119 -    matrix.m[1][2] = 0.0f;
   1.120 -    matrix.m[1][3] = 0.0f;
   1.121 -    matrix.m[2][0] = 0.0f;
   1.122 -    matrix.m[2][1] = 0.0f;
   1.123      matrix.m[2][2] = 1.0f;
   1.124 -    matrix.m[2][3] = 0.0f;
   1.125 -    matrix.m[3][0] = 0.0f;
   1.126 -    matrix.m[3][1] = 0.0f;
   1.127 -    matrix.m[3][2] = 0.0f;
   1.128      matrix.m[3][3] = 1.0f;
   1.129      IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &matrix);
   1.130      IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix);
   1.131 @@ -431,177 +387,6 @@
   1.132      return 0;
   1.133  }
   1.134  
   1.135 -SDL_Renderer *
   1.136 -D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
   1.137 -{
   1.138 -    SDL_Renderer *renderer;
   1.139 -    D3D_RenderData *data;
   1.140 -    SDL_SysWMinfo windowinfo;
   1.141 -    HRESULT result;
   1.142 -    D3DPRESENT_PARAMETERS pparams;
   1.143 -    IDirect3DSwapChain9 *chain;
   1.144 -    D3DCAPS9 caps;
   1.145 -    DWORD device_flags;
   1.146 -    Uint32 window_flags;
   1.147 -    int w, h;
   1.148 -    SDL_DisplayMode fullscreen_mode;
   1.149 -    int displayIndex;
   1.150 -
   1.151 -    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   1.152 -    if (!renderer) {
   1.153 -        SDL_OutOfMemory();
   1.154 -        return NULL;
   1.155 -    }
   1.156 -
   1.157 -    data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
   1.158 -    if (!data) {
   1.159 -        SDL_free(renderer);
   1.160 -        SDL_OutOfMemory();
   1.161 -        return NULL;
   1.162 -    }
   1.163 -
   1.164 -    if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) {
   1.165 -        SDL_free(renderer);
   1.166 -        SDL_free(data);
   1.167 -        SDL_SetError("Unable to create Direct3D interface");
   1.168 -        return NULL;
   1.169 -    }
   1.170 -
   1.171 -    renderer->WindowEvent = D3D_WindowEvent;
   1.172 -    renderer->SupportsBlendMode = D3D_SupportsBlendMode;
   1.173 -    renderer->CreateTexture = D3D_CreateTexture;
   1.174 -    renderer->UpdateTexture = D3D_UpdateTexture;
   1.175 -    renderer->UpdateTextureYUV = D3D_UpdateTextureYUV;
   1.176 -    renderer->LockTexture = D3D_LockTexture;
   1.177 -    renderer->UnlockTexture = D3D_UnlockTexture;
   1.178 -    renderer->SetRenderTarget = D3D_SetRenderTarget;
   1.179 -    renderer->UpdateViewport = D3D_UpdateViewport;
   1.180 -    renderer->UpdateClipRect = D3D_UpdateClipRect;
   1.181 -    renderer->RenderClear = D3D_RenderClear;
   1.182 -    renderer->RenderDrawPoints = D3D_RenderDrawPoints;
   1.183 -    renderer->RenderDrawLines = D3D_RenderDrawLines;
   1.184 -    renderer->RenderFillRects = D3D_RenderFillRects;
   1.185 -    renderer->RenderCopy = D3D_RenderCopy;
   1.186 -    renderer->RenderCopyEx = D3D_RenderCopyEx;
   1.187 -    renderer->RenderReadPixels = D3D_RenderReadPixels;
   1.188 -    renderer->RenderPresent = D3D_RenderPresent;
   1.189 -    renderer->DestroyTexture = D3D_DestroyTexture;
   1.190 -    renderer->DestroyRenderer = D3D_DestroyRenderer;
   1.191 -    renderer->info = D3D_RenderDriver.info;
   1.192 -    renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
   1.193 -    renderer->driverdata = data;
   1.194 -
   1.195 -    SDL_VERSION(&windowinfo.version);
   1.196 -    SDL_GetWindowWMInfo(window, &windowinfo);
   1.197 -
   1.198 -    window_flags = SDL_GetWindowFlags(window);
   1.199 -    SDL_GetWindowSize(window, &w, &h);
   1.200 -    SDL_GetWindowDisplayMode(window, &fullscreen_mode);
   1.201 -
   1.202 -    SDL_zero(pparams);
   1.203 -    pparams.hDeviceWindow = windowinfo.info.win.window;
   1.204 -    pparams.BackBufferWidth = w;
   1.205 -    pparams.BackBufferHeight = h;
   1.206 -    pparams.BackBufferCount = 1;
   1.207 -    pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
   1.208 -
   1.209 -    if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
   1.210 -        pparams.Windowed = FALSE;
   1.211 -        pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format);
   1.212 -        pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
   1.213 -    } else {
   1.214 -        pparams.Windowed = TRUE;
   1.215 -        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
   1.216 -        pparams.FullScreen_RefreshRateInHz = 0;
   1.217 -    }
   1.218 -    if (flags & SDL_RENDERER_PRESENTVSYNC) {
   1.219 -        pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
   1.220 -    } else {
   1.221 -        pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
   1.222 -    }
   1.223 -
   1.224 -    /* Get the adapter for the display that the window is on */
   1.225 -    displayIndex = SDL_GetWindowDisplayIndex(window);
   1.226 -    data->adapter = SDL_Direct3D9GetAdapterIndex(displayIndex);
   1.227 -
   1.228 -    IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
   1.229 -
   1.230 -    device_flags = D3DCREATE_FPU_PRESERVE;
   1.231 -    if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
   1.232 -        device_flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
   1.233 -    } else {
   1.234 -        device_flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
   1.235 -    }
   1.236 -
   1.237 -    if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_FALSE)) {
   1.238 -        device_flags |= D3DCREATE_MULTITHREADED;
   1.239 -    }
   1.240 -
   1.241 -    result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
   1.242 -                                     D3DDEVTYPE_HAL,
   1.243 -                                     pparams.hDeviceWindow,
   1.244 -                                     device_flags,
   1.245 -                                     &pparams, &data->device);
   1.246 -    if (FAILED(result)) {
   1.247 -        D3D_DestroyRenderer(renderer);
   1.248 -        D3D_SetError("CreateDevice()", result);
   1.249 -        return NULL;
   1.250 -    }
   1.251 -
   1.252 -    /* Get presentation parameters to fill info */
   1.253 -    result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
   1.254 -    if (FAILED(result)) {
   1.255 -        D3D_DestroyRenderer(renderer);
   1.256 -        D3D_SetError("GetSwapChain()", result);
   1.257 -        return NULL;
   1.258 -    }
   1.259 -    result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
   1.260 -    if (FAILED(result)) {
   1.261 -        IDirect3DSwapChain9_Release(chain);
   1.262 -        D3D_DestroyRenderer(renderer);
   1.263 -        D3D_SetError("GetPresentParameters()", result);
   1.264 -        return NULL;
   1.265 -    }
   1.266 -    IDirect3DSwapChain9_Release(chain);
   1.267 -    if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
   1.268 -        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   1.269 -    }
   1.270 -    data->pparams = pparams;
   1.271 -
   1.272 -    IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
   1.273 -    renderer->info.max_texture_width = caps.MaxTextureWidth;
   1.274 -    renderer->info.max_texture_height = caps.MaxTextureHeight;
   1.275 -    if (caps.NumSimultaneousRTs >= 2) {
   1.276 -        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
   1.277 -    }
   1.278 -
   1.279 -    if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) {
   1.280 -        data->enableSeparateAlphaBlend = SDL_TRUE;
   1.281 -    }
   1.282 -
   1.283 -    /* Store the default render target */
   1.284 -    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
   1.285 -    data->currentRenderTarget = NULL;
   1.286 -
   1.287 -    /* Set up parameters for rendering */
   1.288 -    D3D_InitRenderState(data);
   1.289 -
   1.290 -    if (caps.MaxSimultaneousTextures >= 3) {
   1.291 -        int i;
   1.292 -        for (i = 0; i < SDL_arraysize(data->shaders); ++i) {
   1.293 -            result = D3D9_CreatePixelShader(data->device, (D3D9_Shader)i, &data->shaders[i]);
   1.294 -            if (FAILED(result)) {
   1.295 -                D3D_SetError("CreatePixelShader()", result);
   1.296 -            }
   1.297 -        }
   1.298 -        if (data->shaders[SHADER_YUV_JPEG] && data->shaders[SHADER_YUV_BT601] && data->shaders[SHADER_YUV_BT709]) {
   1.299 -            renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
   1.300 -            renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
   1.301 -        }
   1.302 -    }
   1.303 -    return renderer;
   1.304 -}
   1.305 -
   1.306  static void
   1.307  D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   1.308  {
   1.309 @@ -702,33 +487,6 @@
   1.310  }
   1.311  
   1.312  static int
   1.313 -D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler)
   1.314 -{
   1.315 -    HRESULT result;
   1.316 -
   1.317 -    if (texture->dirty && texture->staging) {
   1.318 -        if (!texture->texture) {
   1.319 -            result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
   1.320 -                PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL);
   1.321 -            if (FAILED(result)) {
   1.322 -                return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
   1.323 -            }
   1.324 -        }
   1.325 -
   1.326 -        result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
   1.327 -        if (FAILED(result)) {
   1.328 -            return D3D_SetError("UpdateTexture()", result);
   1.329 -        }
   1.330 -        texture->dirty = SDL_FALSE;
   1.331 -    }
   1.332 -    result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture);
   1.333 -    if (FAILED(result)) {
   1.334 -        return D3D_SetError("SetTexture()", result);
   1.335 -    }
   1.336 -    return 0;
   1.337 -}
   1.338 -
   1.339 -static int
   1.340  D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture)
   1.341  {
   1.342      if (texture->texture) {
   1.343 @@ -1072,330 +830,256 @@
   1.344      return D3D_SetRenderTargetInternal(renderer, texture);
   1.345  }
   1.346  
   1.347 +
   1.348  static int
   1.349 -D3D_UpdateViewport(SDL_Renderer * renderer)
   1.350 +D3D_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
   1.351  {
   1.352 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.353 -    D3DVIEWPORT9 viewport;
   1.354 -    D3DMATRIX matrix;
   1.355 +    return 0;  /* nothing to do in this backend. */
   1.356 +}
   1.357  
   1.358 -    /* Set the viewport */
   1.359 -    viewport.X = renderer->viewport.x;
   1.360 -    viewport.Y = renderer->viewport.y;
   1.361 -    viewport.Width = renderer->viewport.w;
   1.362 -    viewport.Height = renderer->viewport.h;
   1.363 -    viewport.MinZ = 0.0f;
   1.364 -    viewport.MaxZ = 1.0f;
   1.365 -    IDirect3DDevice9_SetViewport(data->device, &viewport);
   1.366 +static int
   1.367 +D3D_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
   1.368 +{
   1.369 +    const DWORD color = D3DCOLOR_ARGB(cmd->data.draw.a, cmd->data.draw.r, cmd->data.draw.g, cmd->data.draw.b);
   1.370 +    const size_t vertslen = count * sizeof (Vertex);
   1.371 +    Vertex *verts = (Vertex *) SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first);
   1.372 +    size_t i;
   1.373  
   1.374 -    /* Set an orthographic projection matrix */
   1.375 -    if (renderer->viewport.w && renderer->viewport.h) {
   1.376 -        matrix.m[0][0] = 2.0f / renderer->viewport.w;
   1.377 -        matrix.m[0][1] = 0.0f;
   1.378 -        matrix.m[0][2] = 0.0f;
   1.379 -        matrix.m[0][3] = 0.0f;
   1.380 -        matrix.m[1][0] = 0.0f;
   1.381 -        matrix.m[1][1] = -2.0f / renderer->viewport.h;
   1.382 -        matrix.m[1][2] = 0.0f;
   1.383 -        matrix.m[1][3] = 0.0f;
   1.384 -        matrix.m[2][0] = 0.0f;
   1.385 -        matrix.m[2][1] = 0.0f;
   1.386 -        matrix.m[2][2] = 1.0f;
   1.387 -        matrix.m[2][3] = 0.0f;
   1.388 -        matrix.m[3][0] = -1.0f;
   1.389 -        matrix.m[3][1] = 1.0f;
   1.390 -        matrix.m[3][2] = 0.0f;
   1.391 -        matrix.m[3][3] = 1.0f;
   1.392 -        IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
   1.393 +    if (!verts) {
   1.394 +        return -1;
   1.395 +    }
   1.396 +
   1.397 +    SDL_memset(verts, '\0', vertslen);
   1.398 +    cmd->data.draw.count = count;
   1.399 +
   1.400 +    for (i = 0; i < count; i++, verts++, points++) {
   1.401 +        verts->x = points->x;
   1.402 +        verts->y = points->y;
   1.403 +        verts->color = color;
   1.404      }
   1.405  
   1.406      return 0;
   1.407  }
   1.408  
   1.409  static int
   1.410 -D3D_UpdateClipRect(SDL_Renderer * renderer)
   1.411 +D3D_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
   1.412  {
   1.413 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.414 +    const DWORD color = D3DCOLOR_ARGB(cmd->data.draw.a, cmd->data.draw.r, cmd->data.draw.g, cmd->data.draw.b);
   1.415 +    const size_t vertslen = count * sizeof (Vertex) * 4;
   1.416 +    Vertex *verts = (Vertex *) SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first);
   1.417 +    size_t i;
   1.418  
   1.419 -    if (renderer->clipping_enabled) {
   1.420 -        const SDL_Rect *rect = &renderer->clip_rect;
   1.421 -        RECT r;
   1.422 -        HRESULT result;
   1.423 +    if (!verts) {
   1.424 +        return -1;
   1.425 +    }
   1.426  
   1.427 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
   1.428 -        r.left = renderer->viewport.x + rect->x;
   1.429 -        r.top = renderer->viewport.y + rect->y;
   1.430 -        r.right = renderer->viewport.x + rect->x + rect->w;
   1.431 -        r.bottom = renderer->viewport.y + rect->y + rect->h;
   1.432 +    SDL_memset(verts, '\0', vertslen);
   1.433 +    cmd->data.draw.count = count;
   1.434  
   1.435 -        result = IDirect3DDevice9_SetScissorRect(data->device, &r);
   1.436 -        if (result != D3D_OK) {
   1.437 -            D3D_SetError("SetScissor()", result);
   1.438 -            return -1;
   1.439 -        }
   1.440 -    } else {
   1.441 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
   1.442 +    for (i = 0; i < count; i++) {
   1.443 +        const SDL_FRect *rect = &rects[i];
   1.444 +        const float minx = rect->x;
   1.445 +        const float maxx = rect->x + rect->w;
   1.446 +        const float miny = rect->y;
   1.447 +        const float maxy = rect->y + rect->h;
   1.448 +
   1.449 +        verts->x = minx;
   1.450 +        verts->y = miny;
   1.451 +        verts->color = color;
   1.452 +        verts++;
   1.453 +
   1.454 +        verts->x = maxx;
   1.455 +        verts->y = miny;
   1.456 +        verts->color = color;
   1.457 +        verts++;
   1.458 +
   1.459 +        verts->x = maxx;
   1.460 +        verts->y = maxy;
   1.461 +        verts->color = color;
   1.462 +        verts++;
   1.463 +
   1.464 +        verts->x = minx;
   1.465 +        verts->y = maxy;
   1.466 +        verts->color = color;
   1.467 +        verts++;
   1.468      }
   1.469 +
   1.470      return 0;
   1.471  }
   1.472  
   1.473  static int
   1.474 -D3D_RenderClear(SDL_Renderer * renderer)
   1.475 +D3D_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   1.476 +                          const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   1.477  {
   1.478 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.479 -    DWORD color;
   1.480 -    HRESULT result;
   1.481 -    int BackBufferWidth, BackBufferHeight;
   1.482 +    const DWORD color = D3DCOLOR_ARGB(cmd->data.draw.a, cmd->data.draw.r, cmd->data.draw.g, cmd->data.draw.b);
   1.483 +    float minx, miny, maxx, maxy;
   1.484 +    float minu, maxu, minv, maxv;
   1.485 +    const size_t vertslen = sizeof (Vertex) * 4;
   1.486 +    Vertex *verts = (Vertex *) SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first);
   1.487  
   1.488 -    if (D3D_ActivateRenderer(renderer) < 0) {
   1.489 +    if (!verts) {
   1.490          return -1;
   1.491      }
   1.492  
   1.493 -    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   1.494 +    cmd->data.draw.count = 1;
   1.495  
   1.496 -    if (renderer->target) {
   1.497 -        BackBufferWidth = renderer->target->w;
   1.498 -        BackBufferHeight = renderer->target->h;
   1.499 -    } else {
   1.500 -        BackBufferWidth = data->pparams.BackBufferWidth;
   1.501 -        BackBufferHeight = data->pparams.BackBufferHeight;
   1.502 +    minx = dstrect->x - 0.5f;
   1.503 +    miny = dstrect->y - 0.5f;
   1.504 +    maxx = dstrect->x + dstrect->w - 0.5f;
   1.505 +    maxy = dstrect->y + dstrect->h - 0.5f;
   1.506 +
   1.507 +    minu = (float) srcrect->x / texture->w;
   1.508 +    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
   1.509 +    minv = (float) srcrect->y / texture->h;
   1.510 +    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
   1.511 +
   1.512 +    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
   1.513 +
   1.514 +    verts->x = minx;
   1.515 +    verts->y = miny;
   1.516 +    verts->z = 0.0f;
   1.517 +    verts->color = color;
   1.518 +    verts->u = minu;
   1.519 +    verts->v = minv;
   1.520 +    verts++;
   1.521 +
   1.522 +    verts->x = maxx;
   1.523 +    verts->y = miny;
   1.524 +    verts->z = 0.0f;
   1.525 +    verts->color = color;
   1.526 +    verts->u = maxu;
   1.527 +    verts->v = minv;
   1.528 +    verts++;
   1.529 +
   1.530 +    verts->x = maxx;
   1.531 +    verts->y = maxy;
   1.532 +    verts->z = 0.0f;
   1.533 +    verts->color = color;
   1.534 +    verts->u = maxu;
   1.535 +    verts->v = maxv;
   1.536 +    verts++;
   1.537 +
   1.538 +    verts->x = minx;
   1.539 +    verts->y = maxy;
   1.540 +    verts->z = 0.0f;
   1.541 +    verts->color = color;
   1.542 +    verts->u = minu;
   1.543 +    verts->v = maxv;
   1.544 +    verts++;
   1.545 +
   1.546 +    return 0;
   1.547 +}
   1.548 +
   1.549 +static int
   1.550 +D3D_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   1.551 +                        const SDL_Rect * srcquad, const SDL_FRect * dstrect,
   1.552 +                        const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
   1.553 +{
   1.554 +    const DWORD color = D3DCOLOR_ARGB(cmd->data.draw.a, cmd->data.draw.r, cmd->data.draw.g, cmd->data.draw.b);
   1.555 +    float minx, miny, maxx, maxy;
   1.556 +    float minu, maxu, minv, maxv;
   1.557 +    const size_t vertslen = sizeof (Vertex) * 5;
   1.558 +    Vertex *verts = (Vertex *) SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first);
   1.559 +
   1.560 +    if (!verts) {
   1.561 +        return -1;
   1.562      }
   1.563  
   1.564 -    if (renderer->clipping_enabled) {
   1.565 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
   1.566 +    cmd->data.draw.count = 1;
   1.567 +
   1.568 +    minx = -center->x;
   1.569 +    maxx = dstrect->w - center->x;
   1.570 +    miny = -center->y;
   1.571 +    maxy = dstrect->h - center->y;
   1.572 +
   1.573 +    if (flip & SDL_FLIP_HORIZONTAL) {
   1.574 +        minu = (float) (srcquad->x + srcquad->w) / texture->w;
   1.575 +        maxu = (float) srcquad->x / texture->w;
   1.576 +    } else {
   1.577 +        minu = (float) srcquad->x / texture->w;
   1.578 +        maxu = (float) (srcquad->x + srcquad->w) / texture->w;
   1.579      }
   1.580  
   1.581 -    /* Don't reset the viewport if we don't have to! */
   1.582 -    if (!renderer->viewport.x && !renderer->viewport.y &&
   1.583 -        renderer->viewport.w == BackBufferWidth &&
   1.584 -        renderer->viewport.h == BackBufferHeight) {
   1.585 -        result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
   1.586 +    if (flip & SDL_FLIP_VERTICAL) {
   1.587 +        minv = (float) (srcquad->y + srcquad->h) / texture->h;
   1.588 +        maxv = (float) srcquad->y / texture->h;
   1.589      } else {
   1.590 -        D3DVIEWPORT9 viewport;
   1.591 -
   1.592 -        /* Clear is defined to clear the entire render target */
   1.593 -        viewport.X = 0;
   1.594 -        viewport.Y = 0;
   1.595 -        viewport.Width = BackBufferWidth;
   1.596 -        viewport.Height = BackBufferHeight;
   1.597 -        viewport.MinZ = 0.0f;
   1.598 -        viewport.MaxZ = 1.0f;
   1.599 -        IDirect3DDevice9_SetViewport(data->device, &viewport);
   1.600 -
   1.601 -        result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
   1.602 -
   1.603 -        /* Reset the viewport */
   1.604 -        viewport.X = renderer->viewport.x;
   1.605 -        viewport.Y = renderer->viewport.y;
   1.606 -        viewport.Width = renderer->viewport.w;
   1.607 -        viewport.Height = renderer->viewport.h;
   1.608 -        viewport.MinZ = 0.0f;
   1.609 -        viewport.MaxZ = 1.0f;
   1.610 -        IDirect3DDevice9_SetViewport(data->device, &viewport);
   1.611 +        minv = (float) srcquad->y / texture->h;
   1.612 +        maxv = (float) (srcquad->y + srcquad->h) / texture->h;
   1.613      }
   1.614  
   1.615 -    if (renderer->clipping_enabled) {
   1.616 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
   1.617 +    verts->x = minx;
   1.618 +    verts->y = miny;
   1.619 +    verts->z = 0.0f;
   1.620 +    verts->color = color;
   1.621 +    verts->u = minu;
   1.622 +    verts->v = minv;
   1.623 +    verts++;
   1.624 +
   1.625 +    verts->x = maxx;
   1.626 +    verts->y = miny;
   1.627 +    verts->z = 0.0f;
   1.628 +    verts->color = color;
   1.629 +    verts->u = maxu;
   1.630 +    verts->v = minv;
   1.631 +    verts++;
   1.632 +
   1.633 +    verts->x = maxx;
   1.634 +    verts->y = maxy;
   1.635 +    verts->z = 0.0f;
   1.636 +    verts->color = color;
   1.637 +    verts->u = maxu;
   1.638 +    verts->v = maxv;
   1.639 +    verts++;
   1.640 +
   1.641 +    verts->x = minx;
   1.642 +    verts->y = maxy;
   1.643 +    verts->z = 0.0f;
   1.644 +    verts->color = color;
   1.645 +    verts->u = minu;
   1.646 +    verts->v = maxv;
   1.647 +    verts++;
   1.648 +
   1.649 +    verts->x = dstrect->x + center->x - 0.5f;  /* X translation */
   1.650 +    verts->y = dstrect->y + center->y - 0.5f;  /* Y translation */
   1.651 +    verts->z = (float)(M_PI * (float) angle / 180.0f);  /* rotation */
   1.652 +    verts->color = 0;
   1.653 +    verts->u = 0.0f;
   1.654 +    verts->v = 0.0f;
   1.655 +    verts++;
   1.656 +
   1.657 +    return 0;
   1.658 +}
   1.659 +
   1.660 +static int
   1.661 +BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler)
   1.662 +{
   1.663 +    HRESULT result;
   1.664 +
   1.665 +    if (texture->dirty && texture->staging) {
   1.666 +        if (!texture->texture) {
   1.667 +            result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
   1.668 +                PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL);
   1.669 +            if (FAILED(result)) {
   1.670 +                return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
   1.671 +            }
   1.672 +        }
   1.673 +
   1.674 +        result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
   1.675 +        if (FAILED(result)) {
   1.676 +            return D3D_SetError("UpdateTexture()", result);
   1.677 +        }
   1.678 +        texture->dirty = SDL_FALSE;
   1.679      }
   1.680 -
   1.681 +    result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture);
   1.682      if (FAILED(result)) {
   1.683 -        return D3D_SetError("Clear()", result);
   1.684 +        return D3D_SetError("SetTexture()", result);
   1.685      }
   1.686      return 0;
   1.687  }
   1.688  
   1.689  static void
   1.690 -D3D_SetBlendMode(D3D_RenderData * data, SDL_BlendMode blendMode)
   1.691 -{
   1.692 -    if (blendMode == SDL_BLENDMODE_NONE) {
   1.693 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, FALSE);
   1.694 -    } else {
   1.695 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, TRUE);
   1.696 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
   1.697 -                                        GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)));
   1.698 -        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
   1.699 -                                        GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
   1.700 -        if (data->enableSeparateAlphaBlend) {
   1.701 -            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
   1.702 -                                            GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)));
   1.703 -            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
   1.704 -                                            GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
   1.705 -        }
   1.706 -    }
   1.707 -}
   1.708 -
   1.709 -static int
   1.710 -D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
   1.711 -                     int count)
   1.712 -{
   1.713 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.714 -    DWORD color;
   1.715 -    Vertex *vertices;
   1.716 -    int i;
   1.717 -    HRESULT result;
   1.718 -
   1.719 -    if (D3D_ActivateRenderer(renderer) < 0) {
   1.720 -        return -1;
   1.721 -    }
   1.722 -
   1.723 -    D3D_SetBlendMode(data, renderer->blendMode);
   1.724 -
   1.725 -    result =
   1.726 -        IDirect3DDevice9_SetTexture(data->device, 0,
   1.727 -                                    (IDirect3DBaseTexture9 *) 0);
   1.728 -    if (FAILED(result)) {
   1.729 -        return D3D_SetError("SetTexture()", result);
   1.730 -    }
   1.731 -
   1.732 -    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   1.733 -
   1.734 -    vertices = SDL_stack_alloc(Vertex, count);
   1.735 -    for (i = 0; i < count; ++i) {
   1.736 -        vertices[i].x = points[i].x;
   1.737 -        vertices[i].y = points[i].y;
   1.738 -        vertices[i].z = 0.0f;
   1.739 -        vertices[i].color = color;
   1.740 -        vertices[i].u = 0.0f;
   1.741 -        vertices[i].v = 0.0f;
   1.742 -    }
   1.743 -    result =
   1.744 -        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
   1.745 -                                         vertices, sizeof(*vertices));
   1.746 -    SDL_stack_free(vertices);
   1.747 -    if (FAILED(result)) {
   1.748 -        return D3D_SetError("DrawPrimitiveUP()", result);
   1.749 -    }
   1.750 -    return 0;
   1.751 -}
   1.752 -
   1.753 -static int
   1.754 -D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
   1.755 -                    int count)
   1.756 -{
   1.757 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.758 -    DWORD color;
   1.759 -    Vertex *vertices;
   1.760 -    int i;
   1.761 -    HRESULT result;
   1.762 -
   1.763 -    if (D3D_ActivateRenderer(renderer) < 0) {
   1.764 -        return -1;
   1.765 -    }
   1.766 -
   1.767 -    D3D_SetBlendMode(data, renderer->blendMode);
   1.768 -
   1.769 -    result =
   1.770 -        IDirect3DDevice9_SetTexture(data->device, 0,
   1.771 -                                    (IDirect3DBaseTexture9 *) 0);
   1.772 -    if (FAILED(result)) {
   1.773 -        return D3D_SetError("SetTexture()", result);
   1.774 -    }
   1.775 -
   1.776 -    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   1.777 -
   1.778 -    vertices = SDL_stack_alloc(Vertex, count);
   1.779 -    for (i = 0; i < count; ++i) {
   1.780 -        vertices[i].x = points[i].x;
   1.781 -        vertices[i].y = points[i].y;
   1.782 -        vertices[i].z = 0.0f;
   1.783 -        vertices[i].color = color;
   1.784 -        vertices[i].u = 0.0f;
   1.785 -        vertices[i].v = 0.0f;
   1.786 -    }
   1.787 -    result =
   1.788 -        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
   1.789 -                                         vertices, sizeof(*vertices));
   1.790 -
   1.791 -    /* DirectX 9 has the same line rasterization semantics as GDI,
   1.792 -       so we need to close the endpoint of the line */
   1.793 -    if (count == 2 ||
   1.794 -        points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
   1.795 -        vertices[0].x = points[count-1].x;
   1.796 -        vertices[0].y = points[count-1].y;
   1.797 -        result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
   1.798 -    }
   1.799 -
   1.800 -    SDL_stack_free(vertices);
   1.801 -    if (FAILED(result)) {
   1.802 -        return D3D_SetError("DrawPrimitiveUP()", result);
   1.803 -    }
   1.804 -    return 0;
   1.805 -}
   1.806 -
   1.807 -static int
   1.808 -D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
   1.809 -                    int count)
   1.810 -{
   1.811 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.812 -    DWORD color;
   1.813 -    int i;
   1.814 -    float minx, miny, maxx, maxy;
   1.815 -    Vertex vertices[4];
   1.816 -    HRESULT result;
   1.817 -
   1.818 -    if (D3D_ActivateRenderer(renderer) < 0) {
   1.819 -        return -1;
   1.820 -    }
   1.821 -
   1.822 -    D3D_SetBlendMode(data, renderer->blendMode);
   1.823 -
   1.824 -    result =
   1.825 -        IDirect3DDevice9_SetTexture(data->device, 0,
   1.826 -                                    (IDirect3DBaseTexture9 *) 0);
   1.827 -    if (FAILED(result)) {
   1.828 -        return D3D_SetError("SetTexture()", result);
   1.829 -    }
   1.830 -
   1.831 -    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
   1.832 -
   1.833 -    for (i = 0; i < count; ++i) {
   1.834 -        const SDL_FRect *rect = &rects[i];
   1.835 -
   1.836 -        minx = rect->x;
   1.837 -        miny = rect->y;
   1.838 -        maxx = rect->x + rect->w;
   1.839 -        maxy = rect->y + rect->h;
   1.840 -
   1.841 -        vertices[0].x = minx;
   1.842 -        vertices[0].y = miny;
   1.843 -        vertices[0].z = 0.0f;
   1.844 -        vertices[0].color = color;
   1.845 -        vertices[0].u = 0.0f;
   1.846 -        vertices[0].v = 0.0f;
   1.847 -
   1.848 -        vertices[1].x = maxx;
   1.849 -        vertices[1].y = miny;
   1.850 -        vertices[1].z = 0.0f;
   1.851 -        vertices[1].color = color;
   1.852 -        vertices[1].u = 0.0f;
   1.853 -        vertices[1].v = 0.0f;
   1.854 -
   1.855 -        vertices[2].x = maxx;
   1.856 -        vertices[2].y = maxy;
   1.857 -        vertices[2].z = 0.0f;
   1.858 -        vertices[2].color = color;
   1.859 -        vertices[2].u = 0.0f;
   1.860 -        vertices[2].v = 0.0f;
   1.861 -
   1.862 -        vertices[3].x = minx;
   1.863 -        vertices[3].y = maxy;
   1.864 -        vertices[3].z = 0.0f;
   1.865 -        vertices[3].color = color;
   1.866 -        vertices[3].u = 0.0f;
   1.867 -        vertices[3].v = 0.0f;
   1.868 -
   1.869 -        result =
   1.870 -            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
   1.871 -                                             2, vertices, sizeof(*vertices));
   1.872 -        if (FAILED(result)) {
   1.873 -            return D3D_SetError("DrawPrimitiveUP()", result);
   1.874 -        }
   1.875 -    }
   1.876 -    return 0;
   1.877 -}
   1.878 -
   1.879 -static void
   1.880 -D3D_UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
   1.881 +UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
   1.882  {
   1.883      if (texturedata->scaleMode != data->scaleMode[index]) {
   1.884          IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER,
   1.885 @@ -1411,22 +1095,20 @@
   1.886  }
   1.887  
   1.888  static int
   1.889 -D3D_RenderSetupTextureState(SDL_Renderer * renderer, SDL_Texture * texture, LPDIRECT3DPIXELSHADER9 *shader)
   1.890 +SetupTextureState(D3D_RenderData *data, SDL_Texture * texture, LPDIRECT3DPIXELSHADER9 *shader)
   1.891  {
   1.892 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
   1.893 -    D3D_TextureData *texturedata;
   1.894 +    D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
   1.895  
   1.896 -    *shader = NULL;
   1.897 +    SDL_assert(*shader == NULL);
   1.898  
   1.899 -    texturedata = (D3D_TextureData *)texture->driverdata;
   1.900      if (!texturedata) {
   1.901          SDL_SetError("Texture is not currently available");
   1.902          return -1;
   1.903      }
   1.904  
   1.905 -    D3D_UpdateTextureScaleMode(data, texturedata, 0);
   1.906 +    UpdateTextureScaleMode(data, texturedata, 0);
   1.907  
   1.908 -    if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
   1.909 +    if (BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
   1.910          return -1;
   1.911      }
   1.912  
   1.913 @@ -1445,13 +1127,13 @@
   1.914              return SDL_SetError("Unsupported YUV conversion mode");
   1.915          }
   1.916  
   1.917 -        D3D_UpdateTextureScaleMode(data, texturedata, 1);
   1.918 -        D3D_UpdateTextureScaleMode(data, texturedata, 2);
   1.919 +        UpdateTextureScaleMode(data, texturedata, 1);
   1.920 +        UpdateTextureScaleMode(data, texturedata, 2);
   1.921  
   1.922 -        if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
   1.923 +        if (BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
   1.924              return -1;
   1.925          }
   1.926 -        if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
   1.927 +        if (BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
   1.928              return -1;
   1.929          }
   1.930      }
   1.931 @@ -1459,194 +1141,331 @@
   1.932  }
   1.933  
   1.934  static int
   1.935 -D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   1.936 -               const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   1.937 +SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd, const D3D_ImageSource imgsrc)
   1.938 +{
   1.939 +    const SDL_bool was_copy_ex = data->drawstate.is_copy_ex;
   1.940 +    const SDL_bool is_copy_ex = (cmd->command == SDL_RENDERCMD_COPY_EX);
   1.941 +    SDL_Texture *texture = cmd->data.draw.texture;
   1.942 +    const SDL_BlendMode blend = cmd->data.draw.blend;
   1.943 +
   1.944 +    if (texture != data->drawstate.texture) {
   1.945 +        D3D_TextureData *oldtexturedata = data->drawstate.texture ? (D3D_TextureData *) data->drawstate.texture->driverdata : NULL;
   1.946 +        D3D_TextureData *newtexturedata = texture ? (D3D_TextureData *) texture->driverdata : NULL;
   1.947 +        LPDIRECT3DPIXELSHADER9 shader = NULL;
   1.948 +
   1.949 +        /* disable any enabled textures we aren't going to use, let SetupTextureState() do the rest. */
   1.950 +        if (texture == NULL) {
   1.951 +            IDirect3DDevice9_SetTexture(data->device, 0, NULL);
   1.952 +        }
   1.953 +        if ((!newtexturedata || !newtexturedata->yuv) && (oldtexturedata && oldtexturedata->yuv)) {
   1.954 +            IDirect3DDevice9_SetTexture(data->device, 1, NULL);
   1.955 +            IDirect3DDevice9_SetTexture(data->device, 2, NULL);
   1.956 +        }
   1.957 +        if (texture && RenderSetupTextureState(renderer, texture, &shader) < 0) {
   1.958 +            return -1;
   1.959 +        }
   1.960 +
   1.961 +        if (shader != data->drawstate.shader)
   1.962 +            if (FAILED(IDirect3DDevice9_SetPixelShader(data->device, shader))) {
   1.963 +                return D3D_SetError("IDirect3DDevice9_SetPixelShader()", result);
   1.964 +            }
   1.965 +            data->drawstate.shader = shader;
   1.966 +        }
   1.967 +
   1.968 +        data->drawstate.texture = texture;
   1.969 +    }
   1.970 +
   1.971 +    if (blend != data->drawstate.blend) {
   1.972 +        if (blend == SDL_BLENDMODE_NONE) {
   1.973 +            IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, FALSE);
   1.974 +        } else {
   1.975 +            IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, TRUE);
   1.976 +            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
   1.977 +                                            GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)));
   1.978 +            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
   1.979 +                                            GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
   1.980 +            if (data->enableSeparateAlphaBlend) {
   1.981 +                IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
   1.982 +                                                GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)));
   1.983 +                IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
   1.984 +                                                GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
   1.985 +            }
   1.986 +        }
   1.987 +
   1.988 +        data->drawstate.blend = blend;
   1.989 +    }
   1.990 +
   1.991 +    if (is_copy_ex != was_copy_ex) {
   1.992 +        if (!is_copy_ex) {  /* SDL_RENDERCMD_COPY_EX will set this, we only want to reset it here if necessary. */
   1.993 +            const Float4X4 d3dmatrix = MatrixIdentity();
   1.994 +            IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*) &d3dmatrix);
   1.995 +        }
   1.996 +        data->drawstate.is_copy_ex = is_copy_ex;
   1.997 +    }
   1.998 +
   1.999 +    if (data->drawstate.viewport_dirty) {
  1.1000 +        const SDL_Rect *viewport = &data->drawstate.viewport;
  1.1001 +        const D3DVIEWPORT9 d3dviewport = { viewport->x, viewport->y, viewport->w, viewport->h, 0.0f, 1.0f };
  1.1002 +        IDirect3DDevice9_SetViewport(data->device, &d3dviewport);
  1.1003 +
  1.1004 +        /* Set an orthographic projection matrix */
  1.1005 +        if (viewport->w && viewport->h) {
  1.1006 +            D3DMATRIX d3dmatrix;
  1.1007 +            SDL_zero(d3dmatrix);
  1.1008 +            d3dmatrix.m[0][0] = 2.0f / viewport->w;
  1.1009 +            d3dmatrix.m[1][1] = -2.0f / viewport->h;
  1.1010 +            d3dmatrix.m[2][2] = 1.0f;
  1.1011 +            d3dmatrix.m[3][0] = -1.0f;
  1.1012 +            d3dmatrix.m[3][1] = 1.0f;
  1.1013 +            d3dmatrix.m[3][3] = 1.0f;
  1.1014 +            IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &d3dmatrix);
  1.1015 +        }
  1.1016 +
  1.1017 +        data->drawstate.viewport_dirty = SDL_FALSE;
  1.1018 +    }
  1.1019 +
  1.1020 +    if (data->drawstate.cliprect_enabled_dirty) {
  1.1021 +        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, data->drawstate.cliprect_enabled ? TRUE : FALSE);
  1.1022 +        data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
  1.1023 +    }
  1.1024 +
  1.1025 +    if (data->drawstate.cliprect_dirty) {
  1.1026 +        const SDL_Rect *viewport = &data->drawstate.viewport;
  1.1027 +        const SDL_Rect *rect = &cmd->data.cliprect.rect;
  1.1028 +        const RECT d3drect = { viewport->x + rect->x, viewport->y + rect->y, viewport->x + rect->x + rect->w, viewport->y + rect->y + rect->h };
  1.1029 +        IDirect3DDevice9_SetScissorRect(data->device, &d3drect);
  1.1030 +        data->drawstate.cliprect_dirty = SDL_FALSE;
  1.1031 +    }
  1.1032 +
  1.1033 +    return 0;
  1.1034 +}
  1.1035 +
  1.1036 +static int
  1.1037 +D3D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
  1.1038  {
  1.1039      D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
  1.1040 -    LPDIRECT3DPIXELSHADER9 shader;
  1.1041 -    float minx, miny, maxx, maxy;
  1.1042 -    float minu, maxu, minv, maxv;
  1.1043 -    DWORD color;
  1.1044 -    Vertex vertices[4];
  1.1045 -    HRESULT result;
  1.1046 +    const int vboidx = data->currentVertexBuffer;
  1.1047 +    IDirect3DVertexBuffer9 *vbo = NULL;
  1.1048 +    const SDL_bool istarget = renderer->target != NULL;
  1.1049 +    size_t i;
  1.1050  
  1.1051      if (D3D_ActivateRenderer(renderer) < 0) {
  1.1052          return -1;
  1.1053      }
  1.1054  
  1.1055 -    minx = dstrect->x - 0.5f;
  1.1056 -    miny = dstrect->y - 0.5f;
  1.1057 -    maxx = dstrect->x + dstrect->w - 0.5f;
  1.1058 -    maxy = dstrect->y + dstrect->h - 0.5f;
  1.1059 +    /* upload the new VBO data for this set of commands. */
  1.1060 +    if (data->supportsStreamOffset) {
  1.1061 +        vbo = data->vertexBuffers[vboidx];
  1.1062 +        if (!vbo || (data->vertexBufferSize[vboidx] < vertsize)) {
  1.1063 +            const DWORD usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
  1.1064 +            const DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
  1.1065 +            if (vbo) {
  1.1066 +                IDirect3DVertexBuffer9_Release(vbo);
  1.1067 +            }
  1.1068  
  1.1069 -    minu = (float) srcrect->x / texture->w;
  1.1070 -    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  1.1071 -    minv = (float) srcrect->y / texture->h;
  1.1072 -    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  1.1073 +            if (FAILED(IDirect3DVertexBuffer9_CreateVertexBuffer(vertsize, usage, fvf, D3DPOOL_DEFAULT, &vbo, NULL))) {
  1.1074 +                vbo = NULL;
  1.1075 +            }
  1.1076 +            data->vertexBuffers[vboidx] = vbo;
  1.1077 +            data->vertex_buffer_size[vboidx] = vbo ? vertsize : 0;
  1.1078 +        }
  1.1079  
  1.1080 -    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
  1.1081 +        if (vbo) {
  1.1082 +            void *ptr;
  1.1083 +            if (FAILED(IDirect3DVertexBuffer9_Lock(vbo, 0, vertsize, &ptr, D3DLOCK_DISCARD)) {
  1.1084 +                vbo = NULL;  /* oh well, we'll do immediate mode drawing.  :(  */
  1.1085 +            } else {
  1.1086 +                SDL_memcpy(ptr, vertices, vertsize);
  1.1087 +                if (FAILED(IDirect3DVertexBuffer9_Unlock(vbo))) {
  1.1088 +                    vbo = NULL;  /* oh well, we'll do immediate mode drawing.  :(  */
  1.1089 +                }
  1.1090 +            }
  1.1091 +        }
  1.1092  
  1.1093 -    vertices[0].x = minx;
  1.1094 -    vertices[0].y = miny;
  1.1095 -    vertices[0].z = 0.0f;
  1.1096 -    vertices[0].color = color;
  1.1097 -    vertices[0].u = minu;
  1.1098 -    vertices[0].v = minv;
  1.1099 -
  1.1100 -    vertices[1].x = maxx;
  1.1101 -    vertices[1].y = miny;
  1.1102 -    vertices[1].z = 0.0f;
  1.1103 -    vertices[1].color = color;
  1.1104 -    vertices[1].u = maxu;
  1.1105 -    vertices[1].v = minv;
  1.1106 -
  1.1107 -    vertices[2].x = maxx;
  1.1108 -    vertices[2].y = maxy;
  1.1109 -    vertices[2].z = 0.0f;
  1.1110 -    vertices[2].color = color;
  1.1111 -    vertices[2].u = maxu;
  1.1112 -    vertices[2].v = maxv;
  1.1113 -
  1.1114 -    vertices[3].x = minx;
  1.1115 -    vertices[3].y = maxy;
  1.1116 -    vertices[3].z = 0.0f;
  1.1117 -    vertices[3].color = color;
  1.1118 -    vertices[3].u = minu;
  1.1119 -    vertices[3].v = maxv;
  1.1120 -
  1.1121 -    D3D_SetBlendMode(data, texture->blendMode);
  1.1122 -
  1.1123 -    if (D3D_RenderSetupTextureState(renderer, texture, &shader) < 0) {
  1.1124 -        return -1;
  1.1125 -    }
  1.1126 -    
  1.1127 -    if (shader) {
  1.1128 -        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
  1.1129 -        if (FAILED(result)) {
  1.1130 -            return D3D_SetError("SetShader()", result);
  1.1131 +        /* cycle through a few VBOs so D3D has some time with the data before we replace it. */
  1.1132 +        if (vbo) {
  1.1133 +            data->currentVertexBuffer++;
  1.1134 +            if (data->currentVertexBuffer >= SDL_arraysize(data->vertexBuffers)) {
  1.1135 +                data->currentVertexBuffer = 0;
  1.1136 +            }
  1.1137          }
  1.1138      }
  1.1139 -    result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
  1.1140 -                                              vertices, sizeof(*vertices));
  1.1141 -    if (FAILED(result)) {
  1.1142 -        D3D_SetError("DrawPrimitiveUP()", result);
  1.1143 +
  1.1144 +    if (!vbo && !data->reportedVboProblem) {
  1.1145 +        SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL failed to get a vertex buffer for this Direct3D 9 rendering batch!");
  1.1146 +        SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Dropping back to a slower method.");
  1.1147 +        SDL_LogError(SDL_LOG_CATEGORY_RENDER, "This might be a brief hiccup, but if performance is bad, this is probably why.");
  1.1148 +        SDL_LogError(SDL_LOG_CATEGORY_RENDER, "This error will not be logged again for this renderer.");
  1.1149 +        data->reportedVboProblem = SDL_TRUE;
  1.1150      }
  1.1151 -    if (shader) {
  1.1152 -        IDirect3DDevice9_SetPixelShader(data->device, NULL);
  1.1153 +
  1.1154 +    while (cmd) {
  1.1155 +        switch (cmd->command) {
  1.1156 +            case SDL_RENDERCMD_SETDRAWCOLOR: {
  1.1157 +                /* currently this is sent with each vertex, but if we move to
  1.1158 +                   shaders, we can put this in a uniform here and reduce vertex
  1.1159 +                   buffer bandwidth */
  1.1160 +                break;
  1.1161 +            }
  1.1162 +
  1.1163 +            case SDL_RENDERCMD_SETVIEWPORT: {
  1.1164 +                SDL_Rect *viewport = &data->drawstate.viewport;
  1.1165 +                if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
  1.1166 +                    SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
  1.1167 +                    data->drawstate.viewport_dirty = SDL_TRUE;
  1.1168 +                }
  1.1169 +                break;
  1.1170 +            }
  1.1171 +
  1.1172 +            case SDL_RENDERCMD_SETCLIPRECT: {
  1.1173 +                const SDL_Rect *rect = &cmd->data.cliprect.rect;
  1.1174 +                if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
  1.1175 +                    data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
  1.1176 +                    data->drawstate.cliprect_enabled_dirty = true;
  1.1177 +                }
  1.1178 +
  1.1179 +                if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
  1.1180 +                    SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
  1.1181 +                    data->drawstate.cliprect_dirty = SDL_TRUE;
  1.1182 +                }
  1.1183 +                break;
  1.1184 +            }
  1.1185 +
  1.1186 +            case SDL_RENDERCMD_CLEAR: {
  1.1187 +                const DWORD color = D3DCOLOR_ARGB(cmd->data.color.a, cmd->data.color.r, cmd->data.color.g, cmd->data.color.b);
  1.1188 +                const SDL_Rect *viewport = &data->drawstate.viewport;
  1.1189 +                const int backw = istarget ? renderer->target->w : data->pparams.BackBufferWidth;
  1.1190 +                const int backh = istarget ? renderer->target->h : data->pparams.backh;
  1.1191 +
  1.1192 +                if (data->drawstate.clipping_enabled) {
  1.1193 +                    IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
  1.1194 +                    data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
  1.1195 +                }
  1.1196 +
  1.1197 +                /* Don't reset the viewport if we don't have to! */
  1.1198 +                if (!viewport->.x && !viewport->y && (viewport->w == backw) && (viewport->h == backh)) {
  1.1199 +                    result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
  1.1200 +                } else {
  1.1201 +                    /* Clear is defined to clear the entire render target */
  1.1202 +                    const D3DVIEWPORT9 wholeviewport = { 0, 0, backw, backh, 0.0f, 1.0f };
  1.1203 +                    IDirect3DDevice9_SetViewport(data->device, &wholeviewport);
  1.1204 +                    data->drawstate.viewport_dirty = SDL_TRUE;
  1.1205 +                    IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
  1.1206 +                }
  1.1207 +
  1.1208 +                break;
  1.1209 +            }
  1.1210 +
  1.1211 +            case SDL_RENDERCMD_DRAW_POINTS: {
  1.1212 +                const size_t count = cmd->data.draw.count;
  1.1213 +                const size_t first = cmd->data.draw.first;
  1.1214 +                SetDrawState(data, cmd);
  1.1215 +                if (vbo) {
  1.1216 +                    IDirect3DDevice9_SetStreamSource(data->device, 0, vbo, (UINT) first, sizeof (Vertex));
  1.1217 +                    IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_POINTLIST, 0, count);
  1.1218 +                } else {
  1.1219 +                    const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
  1.1220 +                    IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count, vertices, sizeof (Vertex));
  1.1221 +                }
  1.1222 +                break;
  1.1223 +            }
  1.1224 +
  1.1225 +            case SDL_RENDERCMD_DRAW_LINES: {
  1.1226 +                const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
  1.1227 +                const size_t count = cmd->data.draw.count;
  1.1228 +                const size_t first = cmd->data.draw.first;
  1.1229 +
  1.1230 +                /* DirectX 9 has the same line rasterization semantics as GDI,
  1.1231 +                   so we need to close the endpoint of the line with a second draw call. */
  1.1232 +                const SDL_bool close_endpoint = ((count == 2) || (verts[0].x != verts[count-1].x) || (verts[0].y != verts[count-1].y));
  1.1233 +
  1.1234 +                SetDrawState(data, cmd);
  1.1235 +
  1.1236 +                if (vbo) {
  1.1237 +                    IDirect3DDevice9_SetStreamSource(data->device, 0, vbo, (UINT) first, sizeof (Vertex));
  1.1238 +                    IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_LINESTRIP, 0, count - 1);
  1.1239 +                    if (close_endpoint) {
  1.1240 +                        IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_POINTLIST, count - 1, 1);
  1.1241 +                    }
  1.1242 +                } else {
  1.1243 +                    IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count - 1, verts, sizeof (Vertex));
  1.1244 +                    if (close_endpoint) {
  1.1245 +                        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, &verts[count-1], sizeof (Vertex));
  1.1246 +                    }
  1.1247 +                }
  1.1248 +                break;
  1.1249 +            }
  1.1250 +
  1.1251 +            case SDL_RENDERCMD_FILL_RECTS: {
  1.1252 +                const size_t count = cmd->data.draw.count;
  1.1253 +                const size_t first = cmd->data.draw.first;
  1.1254 +                SetDrawState(data, cmd);
  1.1255 +                if (vbo) {
  1.1256 +                    size_t offset = 0;
  1.1257 +                    IDirect3DDevice9_SetStreamSource(data->device, 0, vbo, (UINT) first, sizeof (Vertex));
  1.1258 +                    for (i = 0; i < count; ++i, offset += 4) {
  1.1259 +                        IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_TRIANGLEFAN, offset, 2);
  1.1260 +                    }
  1.1261 +                } else {
  1.1262 +                    const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
  1.1263 +                    for (i = 0; i < count; ++i, verts += 4) {
  1.1264 +                        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2, verts, sizeof (Vertex));
  1.1265 +                    }
  1.1266 +                }
  1.1267 +                break;
  1.1268 +            }
  1.1269 +
  1.1270 +            case SDL_RENDERCMD_COPY: {
  1.1271 +                const size_t count = cmd->data.draw.count;
  1.1272 +                const size_t first = cmd->data.draw.first;
  1.1273 +                SetDrawState(data, cmd);
  1.1274 +                if (vbo) {
  1.1275 +                    size_t offset = 0;
  1.1276 +                    IDirect3DDevice9_SetStreamSource(data->device, 0, vbo, (UINT) first, sizeof (Vertex));
  1.1277 +                    for (i = 0; i < count; ++i, offset += 4) {
  1.1278 +                        IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_TRIANGLEFAN, offset, 2);
  1.1279 +                    }
  1.1280 +                } else {
  1.1281 +                    const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
  1.1282 +                    for (i = 0; i < count; ++i, verts += 4) {
  1.1283 +                        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2, verts, sizeof (Vertex));
  1.1284 +                    }
  1.1285 +                }
  1.1286 +                break;
  1.1287 +            }
  1.1288 +
  1.1289 +            case SDL_RENDERCMD_COPY_EX: {
  1.1290 +                const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
  1.1291 +                const Vertex *transvert = verts + 4;
  1.1292 +                const float translatex = transvert->x;
  1.1293 +                const float translatey = transvert->y;
  1.1294 +                const float rotation = transvert->z;
  1.1295 +                const Float4X4 d3dmatrix = MatrixMultiply(MatrixRotationZ(rotation), MatrixTranslation(translatex, translatey, 0));
  1.1296 +                SetDrawState(data, cmd);
  1.1297 +
  1.1298 +                IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&d3dmatrix);
  1.1299 +
  1.1300 +                if (vbo) {
  1.1301 +                    IDirect3DDevice9_SetStreamSource(data->device, 0, vbo, (UINT) first, sizeof (Vertex));
  1.1302 +                    IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_TRIANGLEFAN, 0, 2);
  1.1303 +                } else {
  1.1304 +                    IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2, verts, sizeof (Vertex));
  1.1305 +                }
  1.1306 +                break;
  1.1307 +            }
  1.1308 +
  1.1309 +            case SDL_RENDERCMD_NO_OP:
  1.1310 +                break;
  1.1311 +        }
  1.1312 +
  1.1313 +        cmd = cmd->next;
  1.1314      }
  1.1315 -    return FAILED(result) ? -1 : 0;
  1.1316 +
  1.1317 +    return 0;
  1.1318  }
  1.1319  
  1.1320  
  1.1321  static int
  1.1322 -D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
  1.1323 -               const SDL_Rect * srcrect, const SDL_FRect * dstrect,
  1.1324 -               const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
  1.1325 -{
  1.1326 -    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
  1.1327 -    LPDIRECT3DPIXELSHADER9 shader = NULL;
  1.1328 -    float minx, miny, maxx, maxy;
  1.1329 -    float minu, maxu, minv, maxv;
  1.1330 -    float centerx, centery;
  1.1331 -    DWORD color;
  1.1332 -    Vertex vertices[4];
  1.1333 -    Float4X4 modelMatrix;
  1.1334 -    HRESULT result;
  1.1335 -
  1.1336 -    if (D3D_ActivateRenderer(renderer) < 0) {
  1.1337 -        return -1;
  1.1338 -    }
  1.1339 -
  1.1340 -    centerx = center->x;
  1.1341 -    centery = center->y;
  1.1342 -
  1.1343 -    minx = -centerx;
  1.1344 -    maxx = dstrect->w - centerx;
  1.1345 -    miny = -centery;
  1.1346 -    maxy = dstrect->h - centery;
  1.1347 -
  1.1348 -    minu = (float) srcrect->x / texture->w;
  1.1349 -    maxu = (float) (srcrect->x + srcrect->w) / texture->w;
  1.1350 -    minv = (float) srcrect->y / texture->h;
  1.1351 -    maxv = (float) (srcrect->y + srcrect->h) / texture->h;
  1.1352 -
  1.1353 -    if (flip & SDL_FLIP_HORIZONTAL) {
  1.1354 -        float tmp = maxu;
  1.1355 -        maxu = minu;
  1.1356 -        minu = tmp;
  1.1357 -    }
  1.1358 -    if (flip & SDL_FLIP_VERTICAL) {
  1.1359 -        float tmp = maxv;
  1.1360 -        maxv = minv;
  1.1361 -        minv = tmp;
  1.1362 -    }
  1.1363 -
  1.1364 -    color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
  1.1365 -
  1.1366 -    vertices[0].x = minx;
  1.1367 -    vertices[0].y = miny;
  1.1368 -    vertices[0].z = 0.0f;
  1.1369 -    vertices[0].color = color;
  1.1370 -    vertices[0].u = minu;
  1.1371 -    vertices[0].v = minv;
  1.1372 -
  1.1373 -    vertices[1].x = maxx;
  1.1374 -    vertices[1].y = miny;
  1.1375 -    vertices[1].z = 0.0f;
  1.1376 -    vertices[1].color = color;
  1.1377 -    vertices[1].u = maxu;
  1.1378 -    vertices[1].v = minv;
  1.1379 -
  1.1380 -    vertices[2].x = maxx;
  1.1381 -    vertices[2].y = maxy;
  1.1382 -    vertices[2].z = 0.0f;
  1.1383 -    vertices[2].color = color;
  1.1384 -    vertices[2].u = maxu;
  1.1385 -    vertices[2].v = maxv;
  1.1386 -
  1.1387 -    vertices[3].x = minx;
  1.1388 -    vertices[3].y = maxy;
  1.1389 -    vertices[3].z = 0.0f;
  1.1390 -    vertices[3].color = color;
  1.1391 -    vertices[3].u = minu;
  1.1392 -    vertices[3].v = maxv;
  1.1393 -
  1.1394 -    D3D_SetBlendMode(data, texture->blendMode);
  1.1395 -
  1.1396 -    if (D3D_RenderSetupTextureState(renderer, texture, &shader) < 0) {
  1.1397 -        return -1;
  1.1398 -    }
  1.1399 -
  1.1400 -    /* Rotate and translate */
  1.1401 -    modelMatrix = MatrixMultiply(
  1.1402 -            MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)),
  1.1403 -            MatrixTranslation(dstrect->x + center->x - 0.5f, dstrect->y + center->y - 0.5f, 0));
  1.1404 -    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
  1.1405 -    
  1.1406 -    if (shader) {
  1.1407 -        result = IDirect3DDevice9_SetPixelShader(data->device, shader);
  1.1408 -        if (FAILED(result)) {
  1.1409 -            D3D_SetError("SetShader()", result);
  1.1410 -            goto done;
  1.1411 -        }
  1.1412 -    }
  1.1413 -    result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
  1.1414 -                                              vertices, sizeof(*vertices));
  1.1415 -    if (FAILED(result)) {
  1.1416 -        D3D_SetError("DrawPrimitiveUP()", result);
  1.1417 -    }
  1.1418 -done:
  1.1419 -    if (shader) {
  1.1420 -        IDirect3DDevice9_SetPixelShader(data->device, NULL);
  1.1421 -    }
  1.1422 -
  1.1423 -    modelMatrix = MatrixIdentity();
  1.1424 -    IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
  1.1425 -
  1.1426 -    return FAILED(result) ? -1 : 0;
  1.1427 -}
  1.1428 -
  1.1429 -static int
  1.1430  D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1.1431                       Uint32 format, void * pixels, int pitch)
  1.1432  {
  1.1433 @@ -1782,6 +1601,193 @@
  1.1434      }
  1.1435      SDL_free(renderer);
  1.1436  }
  1.1437 +
  1.1438 +SDL_Renderer *
  1.1439 +D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
  1.1440 +{
  1.1441 +    SDL_Renderer *renderer;
  1.1442 +    D3D_RenderData *data;
  1.1443 +    SDL_SysWMinfo windowinfo;
  1.1444 +    HRESULT result;
  1.1445 +    D3DPRESENT_PARAMETERS pparams;
  1.1446 +    IDirect3DSwapChain9 *chain;
  1.1447 +    D3DCAPS9 caps;
  1.1448 +    DWORD device_flags;
  1.1449 +    Uint32 window_flags;
  1.1450 +    int w, h;
  1.1451 +    SDL_DisplayMode fullscreen_mode;
  1.1452 +    int displayIndex;
  1.1453 +
  1.1454 +    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
  1.1455 +    if (!renderer) {
  1.1456 +        SDL_OutOfMemory();
  1.1457 +        return NULL;
  1.1458 +    }
  1.1459 +
  1.1460 +    data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
  1.1461 +    if (!data) {
  1.1462 +        SDL_free(renderer);
  1.1463 +        SDL_OutOfMemory();
  1.1464 +        return NULL;
  1.1465 +    }
  1.1466 +
  1.1467 +    if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) {
  1.1468 +        SDL_free(renderer);
  1.1469 +        SDL_free(data);
  1.1470 +        SDL_SetError("Unable to create Direct3D interface");
  1.1471 +        return NULL;
  1.1472 +    }
  1.1473 +
  1.1474 +    renderer->WindowEvent = D3D_WindowEvent;
  1.1475 +    renderer->SupportsBlendMode = D3D_SupportsBlendMode;
  1.1476 +    renderer->CreateTexture = D3D_CreateTexture;
  1.1477 +    renderer->UpdateTexture = D3D_UpdateTexture;
  1.1478 +    renderer->UpdateTextureYUV = D3D_UpdateTextureYUV;
  1.1479 +    renderer->LockTexture = D3D_LockTexture;
  1.1480 +    renderer->UnlockTexture = D3D_UnlockTexture;
  1.1481 +    renderer->SetRenderTarget = D3D_SetRenderTarget;
  1.1482 +    renderer->QueueSetViewport = D3D_QueueSetViewport;
  1.1483 +    renderer->QueueSetDrawColor = D3D_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
  1.1484 +    renderer->QueueDrawPoints = D3D_QueueDrawPoints;
  1.1485 +    renderer->QueueDrawLines = D3D_QueueDrawPoints;  /* lines and points queue vertices the same way. */
  1.1486 +    renderer->QueueFillRects = D3D_QueueFillRects;
  1.1487 +    renderer->QueueCopy = D3D_QueueCopy;
  1.1488 +    renderer->QueueCopyEx = D3D_QueueCopyEx;
  1.1489 +    renderer->RunCommandQueue = D3D_RunCommandQueue;
  1.1490 +    renderer->RenderReadPixels = D3D_RenderReadPixels;
  1.1491 +    renderer->RenderPresent = D3D_RenderPresent;
  1.1492 +    renderer->DestroyTexture = D3D_DestroyTexture;
  1.1493 +    renderer->DestroyRenderer = D3D_DestroyRenderer;
  1.1494 +    renderer->info = D3D_RenderDriver.info;
  1.1495 +    renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
  1.1496 +    renderer->driverdata = data;
  1.1497 +
  1.1498 +    SDL_VERSION(&windowinfo.version);
  1.1499 +    SDL_GetWindowWMInfo(window, &windowinfo);
  1.1500 +
  1.1501 +    window_flags = SDL_GetWindowFlags(window);
  1.1502 +    SDL_GetWindowSize(window, &w, &h);
  1.1503 +    SDL_GetWindowDisplayMode(window, &fullscreen_mode);
  1.1504 +
  1.1505 +    SDL_zero(pparams);
  1.1506 +    pparams.hDeviceWindow = windowinfo.info.win.window;
  1.1507 +    pparams.BackBufferWidth = w;
  1.1508 +    pparams.BackBufferHeight = h;
  1.1509 +    pparams.BackBufferCount = 1;
  1.1510 +    pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
  1.1511 +
  1.1512 +    if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
  1.1513 +        pparams.Windowed = FALSE;
  1.1514 +        pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format);
  1.1515 +        pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
  1.1516 +    } else {
  1.1517 +        pparams.Windowed = TRUE;
  1.1518 +        pparams.BackBufferFormat = D3DFMT_UNKNOWN;
  1.1519 +        pparams.FullScreen_RefreshRateInHz = 0;
  1.1520 +    }
  1.1521 +    if (flags & SDL_RENDERER_PRESENTVSYNC) {
  1.1522 +        pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  1.1523 +    } else {
  1.1524 +        pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  1.1525 +    }
  1.1526 +
  1.1527 +    /* Get the adapter for the display that the window is on */
  1.1528 +    displayIndex = SDL_GetWindowDisplayIndex(window);
  1.1529 +    data->adapter = SDL_Direct3D9GetAdapterIndex(displayIndex);
  1.1530 +
  1.1531 +    IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
  1.1532 +
  1.1533 +    device_flags = D3DCREATE_FPU_PRESERVE;
  1.1534 +    if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
  1.1535 +        device_flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
  1.1536 +    } else {
  1.1537 +        device_flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  1.1538 +    }
  1.1539 +
  1.1540 +    if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_FALSE)) {
  1.1541 +        device_flags |= D3DCREATE_MULTITHREADED;
  1.1542 +    }
  1.1543 +
  1.1544 +    data->supportsStreamOffset = ((caps.Caps2 & D3DDEVCAPS2_STREAMOFFSET) == D3DDEVCAPS2_STREAMOFFSET);
  1.1545 +
  1.1546 +    result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
  1.1547 +                                     D3DDEVTYPE_HAL,
  1.1548 +                                     pparams.hDeviceWindow,
  1.1549 +                                     device_flags,
  1.1550 +                                     &pparams, &data->device);
  1.1551 +    if (FAILED(result)) {
  1.1552 +        D3D_DestroyRenderer(renderer);
  1.1553 +        D3D_SetError("CreateDevice()", result);
  1.1554 +        return NULL;
  1.1555 +    }
  1.1556 +
  1.1557 +    /* Get presentation parameters to fill info */
  1.1558 +    result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
  1.1559 +    if (FAILED(result)) {
  1.1560 +        D3D_DestroyRenderer(renderer);
  1.1561 +        D3D_SetError("GetSwapChain()", result);
  1.1562 +        return NULL;
  1.1563 +    }
  1.1564 +    result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
  1.1565 +    if (FAILED(result)) {
  1.1566 +        IDirect3DSwapChain9_Release(chain);
  1.1567 +        D3D_DestroyRenderer(renderer);
  1.1568 +        D3D_SetError("GetPresentParameters()", result);
  1.1569 +        return NULL;
  1.1570 +    }
  1.1571 +    IDirect3DSwapChain9_Release(chain);
  1.1572 +    if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
  1.1573 +        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
  1.1574 +    }
  1.1575 +    data->pparams = pparams;
  1.1576 +
  1.1577 +    IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
  1.1578 +    renderer->info.max_texture_width = caps.MaxTextureWidth;
  1.1579 +    renderer->info.max_texture_height = caps.MaxTextureHeight;
  1.1580 +    if (caps.NumSimultaneousRTs >= 2) {
  1.1581 +        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
  1.1582 +    }
  1.1583 +
  1.1584 +    if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) {
  1.1585 +        data->enableSeparateAlphaBlend = SDL_TRUE;
  1.1586 +    }
  1.1587 +
  1.1588 +    /* Store the default render target */
  1.1589 +    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
  1.1590 +    data->currentRenderTarget = NULL;
  1.1591 +
  1.1592 +    /* Set up parameters for rendering */
  1.1593 +    D3D_InitRenderState(data);
  1.1594 +
  1.1595 +    if (caps.MaxSimultaneousTextures >= 3) {
  1.1596 +        int i;
  1.1597 +        for (i = 0; i < SDL_arraysize(data->shaders); ++i) {
  1.1598 +            result = D3D9_CreatePixelShader(data->device, (D3D9_Shader)i, &data->shaders[i]);
  1.1599 +            if (FAILED(result)) {
  1.1600 +                D3D_SetError("CreatePixelShader()", result);
  1.1601 +            }
  1.1602 +        }
  1.1603 +        if (data->shaders[SHADER_YUV_JPEG] && data->shaders[SHADER_YUV_BT601] && data->shaders[SHADER_YUV_BT709]) {
  1.1604 +            renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
  1.1605 +            renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
  1.1606 +        }
  1.1607 +    }
  1.1608 +
  1.1609 +    data->drawstate.blend = SDL_BLENDMODE_INVALID;
  1.1610 +
  1.1611 +    return renderer;
  1.1612 +}
  1.1613 +
  1.1614 +SDL_RenderDriver D3D_RenderDriver = {
  1.1615 +    D3D_CreateRenderer,
  1.1616 +    {
  1.1617 +     "direct3d",
  1.1618 +     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
  1.1619 +     1,
  1.1620 +     {SDL_PIXELFORMAT_ARGB8888},
  1.1621 +     0,
  1.1622 +     0}
  1.1623 +};
  1.1624  #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
  1.1625  
  1.1626  #ifdef __WIN32__