From 03f8528315fa46c95991a34f3325d7b33ae5538c Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Sat, 02 May 2020 21:48:36 +0000
Subject: [PATCH] Update source to SDL2 2.0.12
---
source/src/render/direct3d11/SDL_render_d3d11.c | 1387 +++++++++++++++++++++++++++++----------------------------
1 files changed, 713 insertions(+), 674 deletions(-)
diff --git a/source/src/render/direct3d11/SDL_render_d3d11.c b/source/src/render/direct3d11/SDL_render_d3d11.c
index 7a37039..735173e 100644
--- a/source/src/render/direct3d11/SDL_render_d3d11.c
+++ b/source/src/render/direct3d11/SDL_render_d3d11.c
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
- Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+ Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -55,6 +55,9 @@
#define SAFE_RELEASE(X) if ((X)) { IUnknown_Release(SDL_static_cast(IUnknown*, X)); X = NULL; }
+
+/* !!! FIXME: vertex buffer bandwidth could be significantly lower; move color to a uniform, only use UV coords
+ !!! FIXME: when textures are needed, and don't ever pass Z, since it's always zero. */
/* Vertex shader, common values */
typedef struct
@@ -120,7 +123,8 @@
ID3D11RenderTargetView *mainRenderTargetView;
ID3D11RenderTargetView *currentOffscreenRenderTargetView;
ID3D11InputLayout *inputLayout;
- ID3D11Buffer *vertexBuffer;
+ ID3D11Buffer *vertexBuffers[8];
+ size_t vertexBufferSizes[8];
ID3D11VertexShader *vertexShader;
ID3D11PixelShader *pixelShaders[NUM_SHADERS];
int blendModesCount;
@@ -145,6 +149,14 @@
ID3D11PixelShader *currentShader;
ID3D11ShaderResourceView *currentShaderResource;
ID3D11SamplerState *currentSampler;
+ SDL_bool cliprectDirty;
+ SDL_bool currentCliprectEnabled;
+ SDL_Rect currentCliprect;
+ SDL_Rect currentViewport;
+ int currentViewportRotation;
+ SDL_bool viewportDirty;
+ Float4X4 identity;
+ int currentVertexBuffer;
} D3D11_RenderData;
@@ -174,75 +186,6 @@
#pragma GCC diagnostic pop
#endif
-
-/* Direct3D 11.1 renderer implementation */
-static SDL_Renderer *D3D11_CreateRenderer(SDL_Window * window, Uint32 flags);
-static void D3D11_WindowEvent(SDL_Renderer * renderer,
- const SDL_WindowEvent *event);
-static SDL_bool D3D11_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
-static int D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, const void *srcPixels,
- int srcPitch);
-static int D3D11_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect,
- const Uint8 *Yplane, int Ypitch,
- const Uint8 *Uplane, int Upitch,
- const Uint8 *Vplane, int Vpitch);
-static int D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, void **pixels, int *pitch);
-static void D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
-static int D3D11_UpdateViewport(SDL_Renderer * renderer);
-static int D3D11_UpdateClipRect(SDL_Renderer * renderer);
-static int D3D11_RenderClear(SDL_Renderer * renderer);
-static int D3D11_RenderDrawPoints(SDL_Renderer * renderer,
- const SDL_FPoint * points, int count);
-static int D3D11_RenderDrawLines(SDL_Renderer * renderer,
- const SDL_FPoint * points, int count);
-static int D3D11_RenderFillRects(SDL_Renderer * renderer,
- const SDL_FRect * rects, int count);
-static int D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_FRect * dstrect);
-static int D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_FRect * dstrect,
- const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
-static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
- Uint32 format, void * pixels, int pitch);
-static void D3D11_RenderPresent(SDL_Renderer * renderer);
-static void D3D11_DestroyTexture(SDL_Renderer * renderer,
- SDL_Texture * texture);
-static void D3D11_DestroyRenderer(SDL_Renderer * renderer);
-
-/* Direct3D 11.1 Internal Functions */
-static HRESULT D3D11_CreateDeviceResources(SDL_Renderer * renderer);
-static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer);
-static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer);
-static HRESULT D3D11_HandleDeviceLost(SDL_Renderer * renderer);
-static void D3D11_ReleaseMainRenderTargetView(SDL_Renderer * renderer);
-
-SDL_RenderDriver D3D11_RenderDriver = {
- D3D11_CreateRenderer,
- {
- "direct3d11",
- (
- SDL_RENDERER_ACCELERATED |
- SDL_RENDERER_PRESENTVSYNC |
- SDL_RENDERER_TARGETTEXTURE
- ), /* flags. see SDL_RendererFlags */
- 6, /* num_texture_formats */
- { /* texture_formats */
- SDL_PIXELFORMAT_ARGB8888,
- SDL_PIXELFORMAT_RGB888,
- SDL_PIXELFORMAT_YV12,
- SDL_PIXELFORMAT_IYUV,
- SDL_PIXELFORMAT_NV12,
- SDL_PIXELFORMAT_NV21
- },
- 0, /* max_texture_width: will be filled in later */
- 0 /* max_texture_height: will be filled in later */
- }
-};
Uint32
@@ -276,84 +219,7 @@
}
}
-SDL_Renderer *
-D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
-{
- SDL_Renderer *renderer;
- D3D11_RenderData *data;
-
- renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
- if (!renderer) {
- SDL_OutOfMemory();
- return NULL;
- }
-
- data = (D3D11_RenderData *) SDL_calloc(1, sizeof(*data));
- if (!data) {
- SDL_OutOfMemory();
- return NULL;
- }
-
- renderer->WindowEvent = D3D11_WindowEvent;
- renderer->SupportsBlendMode = D3D11_SupportsBlendMode;
- renderer->CreateTexture = D3D11_CreateTexture;
- renderer->UpdateTexture = D3D11_UpdateTexture;
- renderer->UpdateTextureYUV = D3D11_UpdateTextureYUV;
- renderer->LockTexture = D3D11_LockTexture;
- renderer->UnlockTexture = D3D11_UnlockTexture;
- renderer->SetRenderTarget = D3D11_SetRenderTarget;
- renderer->UpdateViewport = D3D11_UpdateViewport;
- renderer->UpdateClipRect = D3D11_UpdateClipRect;
- renderer->RenderClear = D3D11_RenderClear;
- renderer->RenderDrawPoints = D3D11_RenderDrawPoints;
- renderer->RenderDrawLines = D3D11_RenderDrawLines;
- renderer->RenderFillRects = D3D11_RenderFillRects;
- renderer->RenderCopy = D3D11_RenderCopy;
- renderer->RenderCopyEx = D3D11_RenderCopyEx;
- renderer->RenderReadPixels = D3D11_RenderReadPixels;
- renderer->RenderPresent = D3D11_RenderPresent;
- renderer->DestroyTexture = D3D11_DestroyTexture;
- renderer->DestroyRenderer = D3D11_DestroyRenderer;
- renderer->info = D3D11_RenderDriver.info;
- renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
- renderer->driverdata = data;
-
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- /* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
- * Failure to use it seems to either result in:
- *
- * - with the D3D11 debug runtime turned OFF, vsync seemingly gets turned
- * off (framerate doesn't get capped), but nothing appears on-screen
- *
- * - with the D3D11 debug runtime turned ON, vsync gets automatically
- * turned back on, and the following gets output to the debug console:
- *
- * DXGI ERROR: IDXGISwapChain::Present: Interval 0 is not supported, changed to Interval 1. [ UNKNOWN ERROR #1024: ]
- */
- renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
-#else
- if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
- renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
- }
-#endif
-
- /* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
- * order to give init functions access to the underlying window handle:
- */
- renderer->window = window;
-
- /* Initialize Direct3D resources */
- if (FAILED(D3D11_CreateDeviceResources(renderer))) {
- D3D11_DestroyRenderer(renderer);
- return NULL;
- }
- if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) {
- D3D11_DestroyRenderer(renderer);
- return NULL;
- }
-
- return renderer;
-}
+static void D3D11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static void
D3D11_ReleaseAll(SDL_Renderer * renderer)
@@ -378,7 +244,9 @@
SAFE_RELEASE(data->mainRenderTargetView);
SAFE_RELEASE(data->currentOffscreenRenderTargetView);
SAFE_RELEASE(data->inputLayout);
- SAFE_RELEASE(data->vertexBuffer);
+ for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) {
+ SAFE_RELEASE(data->vertexBuffers[i]);
+ }
SAFE_RELEASE(data->vertexShader);
for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
SAFE_RELEASE(data->pixelShaders[i]);
@@ -477,7 +345,7 @@
}
}
-static SDL_bool
+static ID3D11BlendState *
D3D11_CreateBlendState(SDL_Renderer * renderer, SDL_BlendMode blendMode)
{
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
@@ -506,21 +374,21 @@
result = ID3D11Device_CreateBlendState(data->d3dDevice, &blendDesc, &blendState);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBlendState"), result);
- return SDL_FALSE;
+ return NULL;
}
blendModes = (D3D11_BlendMode *)SDL_realloc(data->blendModes, (data->blendModesCount + 1) * sizeof(*blendModes));
if (!blendModes) {
SAFE_RELEASE(blendState);
SDL_OutOfMemory();
- return SDL_FALSE;
+ return NULL;
}
blendModes[data->blendModesCount].blendMode = blendMode;
blendModes[data->blendModesCount].blendState = blendState;
data->blendModes = blendModes;
++data->blendModesCount;
- return SDL_TRUE;
+ return blendState;
}
/* Create resources that depend on the device. */
@@ -768,7 +636,8 @@
/* Create blending states: */
if (!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_BLEND) ||
!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_ADD) ||
- !D3D11_CreateBlendState(renderer, SDL_BLENDMODE_MOD)) {
+ !D3D11_CreateBlendState(renderer, SDL_BLENDMODE_MOD) ||
+ !D3D11_CreateBlendState(renderer, SDL_BLENDMODE_MUL)) {
/* D3D11_CreateBlendMode will set the SDL error, if it fails */
goto done;
}
@@ -964,6 +833,45 @@
return result;
}
+static void
+D3D11_ReleaseMainRenderTargetView(SDL_Renderer * renderer)
+{
+ D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
+ ID3D11DeviceContext_OMSetRenderTargets(data->d3dContext, 0, NULL, NULL);
+ SAFE_RELEASE(data->mainRenderTargetView);
+}
+
+static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer);
+
+
+HRESULT
+D3D11_HandleDeviceLost(SDL_Renderer * renderer)
+{
+ HRESULT result = S_OK;
+
+ D3D11_ReleaseAll(renderer);
+
+ result = D3D11_CreateDeviceResources(renderer);
+ if (FAILED(result)) {
+ /* D3D11_CreateDeviceResources will set the SDL error */
+ return result;
+ }
+
+ result = D3D11_UpdateForWindowSizeChange(renderer);
+ if (FAILED(result)) {
+ /* D3D11_UpdateForWindowSizeChange will set the SDL error */
+ return result;
+ }
+
+ /* Let the application know that the device has been reset */
+ {
+ SDL_Event event;
+ event.type = SDL_RENDER_DEVICE_RESET;
+ SDL_PushEvent(&event);
+ }
+
+ return S_OK;
+}
/* Initialize all resources that change when the window's size changes. */
static HRESULT
@@ -1066,11 +974,7 @@
goto done;
}
- if (D3D11_UpdateViewport(renderer) != 0) {
- /* D3D11_UpdateViewport will set the SDL error if it fails. */
- result = E_FAIL;
- goto done;
- }
+ data->viewportDirty = SDL_TRUE;
done:
SAFE_RELEASE(backBuffer);
@@ -1082,35 +986,6 @@
D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer)
{
return D3D11_CreateWindowSizeDependentResources(renderer);
-}
-
-HRESULT
-D3D11_HandleDeviceLost(SDL_Renderer * renderer)
-{
- HRESULT result = S_OK;
-
- D3D11_ReleaseAll(renderer);
-
- result = D3D11_CreateDeviceResources(renderer);
- if (FAILED(result)) {
- /* D3D11_CreateDeviceResources will set the SDL error */
- return result;
- }
-
- result = D3D11_UpdateForWindowSizeChange(renderer);
- if (FAILED(result)) {
- /* D3D11_UpdateForWindowSizeChange will set the SDL error */
- return result;
- }
-
- /* Let the application know that the device has been reset */
- {
- SDL_Event event;
- event.type = SDL_RENDER_DEVICE_RESET;
- SDL_PushEvent(&event);
- }
-
- return S_OK;
}
void
@@ -1649,6 +1524,18 @@
SAFE_RELEASE(textureData->stagingTexture);
}
+static void
+D3D11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
+{
+ D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
+
+ if (!textureData) {
+ return;
+ }
+
+ textureData->scaleMode = (scaleMode == SDL_ScaleModeNearest) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+}
+
static int
D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
{
@@ -1671,45 +1558,371 @@
return 0;
}
-static void
-D3D11_SetModelMatrix(SDL_Renderer *renderer, const Float4X4 *matrix)
+static int
+D3D11_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
{
- D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
+ return 0; /* nothing to do in this backend. */
+}
- if (matrix) {
- data->vertexShaderConstantsData.model = *matrix;
- } else {
- data->vertexShaderConstantsData.model = MatrixIdentity();
+static int
+D3D11_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
+{
+ VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
+ const float r = (float)(cmd->data.draw.r / 255.0f);
+ const float g = (float)(cmd->data.draw.g / 255.0f);
+ const float b = (float)(cmd->data.draw.b / 255.0f);
+ const float a = (float)(cmd->data.draw.a / 255.0f);
+ int i;
+
+ if (!verts) {
+ return -1;
}
- ID3D11DeviceContext_UpdateSubresource(data->d3dContext,
- (ID3D11Resource *)data->vertexShaderConstants,
+ cmd->data.draw.count = count;
+
+ for (i = 0; i < count; i++) {
+ verts->pos.x = points[i].x + 0.5f;
+ verts->pos.y = points[i].y + 0.5f;
+ verts->pos.z = 0.0f;
+ verts->tex.x = 0.0f;
+ verts->tex.y = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+ }
+
+ return 0;
+}
+
+static int
+D3D11_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
+{
+ VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
+ const float r = (float)(cmd->data.draw.r / 255.0f);
+ const float g = (float)(cmd->data.draw.g / 255.0f);
+ const float b = (float)(cmd->data.draw.b / 255.0f);
+ const float a = (float)(cmd->data.draw.a / 255.0f);
+ int i;
+
+ if (!verts) {
+ return -1;
+ }
+
+ cmd->data.draw.count = count;
+
+ for (i = 0; i < count; i++) {
+ verts->pos.x = rects[i].x;
+ verts->pos.y = rects[i].y;
+ verts->pos.z = 0.0f;
+ verts->tex.x = 0.0f;
+ verts->tex.y = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+
+ verts->pos.x = rects[i].x;
+ verts->pos.y = rects[i].y + rects[i].h;
+ verts->pos.z = 0.0f;
+ verts->tex.x = 0.0f;
+ verts->tex.y = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+
+ verts->pos.x = rects[i].x + rects[i].w;
+ verts->pos.y = rects[i].y;
+ verts->pos.z = 0.0f;
+ verts->tex.x = 0.0f;
+ verts->tex.y = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+
+ verts->pos.x = rects[i].x + rects[i].w;
+ verts->pos.y = rects[i].y + rects[i].h;
+ verts->pos.z = 0.0f;
+ verts->tex.x = 0.0f;
+ verts->tex.y = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+ }
+
+ return 0;
+}
+
+static int
+D3D11_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_FRect * dstrect)
+{
+ VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, 4 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
+ const float r = (float)(cmd->data.draw.r / 255.0f);
+ const float g = (float)(cmd->data.draw.g / 255.0f);
+ const float b = (float)(cmd->data.draw.b / 255.0f);
+ const float a = (float)(cmd->data.draw.a / 255.0f);
+ const float minu = (float) srcrect->x / texture->w;
+ const float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
+ const float minv = (float) srcrect->y / texture->h;
+ const float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
+
+ if (!verts) {
+ return -1;
+ }
+
+ cmd->data.draw.count = 1;
+
+ verts->pos.x = dstrect->x;
+ verts->pos.y = dstrect->y;
+ verts->pos.z = 0.0f;
+ verts->tex.x = minu;
+ verts->tex.y = minv;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+
+ verts->pos.x = dstrect->x;
+ verts->pos.y = dstrect->y + dstrect->h;
+ verts->pos.z = 0.0f;
+ verts->tex.x = minu;
+ verts->tex.y = maxv;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+
+ verts->pos.x = dstrect->x + dstrect->w;
+ verts->pos.y = dstrect->y;
+ verts->pos.z = 0.0f;
+ verts->tex.x = maxu;
+ verts->tex.y = minv;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+
+ verts->pos.x = dstrect->x + dstrect->w;
+ verts->pos.y = dstrect->y + dstrect->h;
+ verts->pos.z = 0.0f;
+ verts->tex.x = maxu;
+ verts->tex.y = maxv;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts++;
+
+ return 0;
+}
+
+static int
+D3D11_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_FRect * dstrect,
+ const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
+{
+ VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, 5 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
+ const float r = (float)(cmd->data.draw.r / 255.0f);
+ const float g = (float)(cmd->data.draw.g / 255.0f);
+ const float b = (float)(cmd->data.draw.b / 255.0f);
+ const float a = (float)(cmd->data.draw.a / 255.0f);
+ float minx, miny, maxx, maxy;
+ float minu, maxu, minv, maxv;
+
+ if (!verts) {
+ return -1;
+ }
+
+ cmd->data.draw.count = 1;
+
+ minx = -center->x;
+ maxx = dstrect->w - center->x;
+ miny = -center->y;
+ maxy = dstrect->h - center->y;
+
+ if (flip & SDL_FLIP_HORIZONTAL) {
+ minu = (float) (srcrect->x + srcrect->w) / texture->w;
+ maxu = (float) srcrect->x / texture->w;
+ } else {
+ minu = (float) srcrect->x / texture->w;
+ maxu = (float) (srcrect->x + srcrect->w) / texture->w;
+ }
+
+ if (flip & SDL_FLIP_VERTICAL) {
+ minv = (float) (srcrect->y + srcrect->h) / texture->h;
+ maxv = (float) srcrect->y / texture->h;
+ } else {
+ minv = (float) srcrect->y / texture->h;
+ maxv = (float) (srcrect->y + srcrect->h) / texture->h;
+ }
+
+
+
+ verts->pos.x = minx;
+ verts->pos.y = miny;
+ verts->pos.z = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts->tex.x = minu;
+ verts->tex.y = minv;
+ verts++;
+
+ verts->pos.x = minx;
+ verts->pos.y = maxy;
+ verts->pos.z = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts->tex.x = minu;
+ verts->tex.y = maxv;
+ verts++;
+
+ verts->pos.x = maxx;
+ verts->pos.y = miny;
+ verts->pos.z = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts->tex.x = maxu;
+ verts->tex.y = minv;
+ verts++;
+
+ verts->pos.x = maxx;
+ verts->pos.y = maxy;
+ verts->pos.z = 0.0f;
+ verts->color.x = r;
+ verts->color.y = g;
+ verts->color.z = b;
+ verts->color.w = a;
+ verts->tex.x = maxu;
+ verts->tex.y = maxv;
+ verts++;
+
+ verts->pos.x = dstrect->x + center->x; /* X translation */
+ verts->pos.y = dstrect->y + center->y; /* Y translation */
+ verts->pos.z = (float)(M_PI * (float) angle / 180.0f); /* rotation */
+ verts->color.x = 0;
+ verts->color.y = 0;
+ verts->color.z = 0;
+ verts->color.w = 0;
+ verts->tex.x = 0.0f;
+ verts->tex.y = 0.0f;
+ verts++;
+
+ return 0;
+}
+
+
+static int
+D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
+ const void * vertexData, size_t dataSizeInBytes)
+{
+ D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
+ HRESULT result = S_OK;
+ const int vbidx = rendererData->currentVertexBuffer;
+ const UINT stride = sizeof(VertexPositionColor);
+ const UINT offset = 0;
+
+ if (dataSizeInBytes == 0) {
+ return 0; /* nothing to do. */
+ }
+
+ if (rendererData->vertexBuffers[vbidx] && rendererData->vertexBufferSizes[vbidx] >= dataSizeInBytes) {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = ID3D11DeviceContext_Map(rendererData->d3dContext,
+ (ID3D11Resource *)rendererData->vertexBuffers[vbidx],
+ 0,
+ D3D11_MAP_WRITE_DISCARD,
+ 0,
+ &mappedResource
+ );
+ if (FAILED(result)) {
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [vertex buffer]"), result);
+ return -1;
+ }
+ SDL_memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
+ ID3D11DeviceContext_Unmap(rendererData->d3dContext, (ID3D11Resource *)rendererData->vertexBuffers[vbidx], 0);
+ } else {
+ D3D11_BUFFER_DESC vertexBufferDesc;
+ D3D11_SUBRESOURCE_DATA vertexBufferData;
+
+ SAFE_RELEASE(rendererData->vertexBuffers[vbidx]);
+
+ SDL_zero(vertexBufferDesc);
+ vertexBufferDesc.ByteWidth = (UINT) dataSizeInBytes;
+ vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+ SDL_zero(vertexBufferData);
+ vertexBufferData.pSysMem = vertexData;
+ vertexBufferData.SysMemPitch = 0;
+ vertexBufferData.SysMemSlicePitch = 0;
+
+ result = ID3D11Device_CreateBuffer(rendererData->d3dDevice,
+ &vertexBufferDesc,
+ &vertexBufferData,
+ &rendererData->vertexBuffers[vbidx]
+ );
+ if (FAILED(result)) {
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex buffer]"), result);
+ return -1;
+ }
+
+ rendererData->vertexBufferSizes[vbidx] = dataSizeInBytes;
+ }
+
+ ID3D11DeviceContext_IASetVertexBuffers(rendererData->d3dContext,
0,
- NULL,
- &data->vertexShaderConstantsData,
- 0,
- 0
+ 1,
+ &rendererData->vertexBuffers[vbidx],
+ &stride,
+ &offset
);
+
+ rendererData->currentVertexBuffer++;
+ if (rendererData->currentVertexBuffer >= SDL_arraysize(rendererData->vertexBuffers)) {
+ rendererData->currentVertexBuffer = 0;
+ }
+
+ return 0;
}
static int
D3D11_UpdateViewport(SDL_Renderer * renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
+ const SDL_Rect *viewport = &data->currentViewport;
Float4X4 projection;
Float4X4 view;
SDL_FRect orientationAlignedViewport;
BOOL swapDimensions;
- D3D11_VIEWPORT viewport;
+ D3D11_VIEWPORT d3dviewport;
const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
- if (renderer->viewport.w == 0 || renderer->viewport.h == 0) {
+ if (viewport->w == 0 || viewport->h == 0) {
/* If the viewport is empty, assume that it is because
* SDL_CreateRenderer is calling it, and will call it again later
* with a non-empty viewport.
*/
/* SDL_Log("%s, no viewport was set!\n", __FUNCTION__); */
- return 0;
+ return -1;
}
/* Make sure the SDL viewport gets rotated to that of the physical display's rotation.
@@ -1735,21 +1948,12 @@
}
/* Update the view matrix */
- view.m[0][0] = 2.0f / renderer->viewport.w;
- view.m[0][1] = 0.0f;
- view.m[0][2] = 0.0f;
- view.m[0][3] = 0.0f;
- view.m[1][0] = 0.0f;
- view.m[1][1] = -2.0f / renderer->viewport.h;
- view.m[1][2] = 0.0f;
- view.m[1][3] = 0.0f;
- view.m[2][0] = 0.0f;
- view.m[2][1] = 0.0f;
+ SDL_zero(view);
+ view.m[0][0] = 2.0f / viewport->w;
+ view.m[1][1] = -2.0f / viewport->h;
view.m[2][2] = 1.0f;
- view.m[2][3] = 0.0f;
view.m[3][0] = -1.0f;
view.m[3][1] = 1.0f;
- view.m[3][2] = 0.0f;
view.m[3][3] = 1.0f;
/* Combine the projection + view matrix together now, as both only get
@@ -1760,9 +1964,6 @@
view,
projection);
- /* Reset the model matrix */
- D3D11_SetModelMatrix(renderer, NULL);
-
/* Update the Direct3D viewport, which seems to be aligned to the
* swap buffer's coordinate space, which is always in either
* a landscape mode, for all Windows 8/RT devices, or a portrait mode,
@@ -1770,158 +1971,59 @@
*/
swapDimensions = D3D11_IsDisplayRotated90Degrees(rotation);
if (swapDimensions) {
- orientationAlignedViewport.x = (float) renderer->viewport.y;
- orientationAlignedViewport.y = (float) renderer->viewport.x;
- orientationAlignedViewport.w = (float) renderer->viewport.h;
- orientationAlignedViewport.h = (float) renderer->viewport.w;
+ orientationAlignedViewport.x = (float) viewport->y;
+ orientationAlignedViewport.y = (float) viewport->x;
+ orientationAlignedViewport.w = (float) viewport->h;
+ orientationAlignedViewport.h = (float) viewport->w;
} else {
- orientationAlignedViewport.x = (float) renderer->viewport.x;
- orientationAlignedViewport.y = (float) renderer->viewport.y;
- orientationAlignedViewport.w = (float) renderer->viewport.w;
- orientationAlignedViewport.h = (float) renderer->viewport.h;
+ orientationAlignedViewport.x = (float) viewport->x;
+ orientationAlignedViewport.y = (float) viewport->y;
+ orientationAlignedViewport.w = (float) viewport->w;
+ orientationAlignedViewport.h = (float) viewport->h;
}
/* TODO, WinRT: get custom viewports working with non-Landscape modes (Portrait, PortraitFlipped, and LandscapeFlipped) */
- viewport.TopLeftX = orientationAlignedViewport.x;
- viewport.TopLeftY = orientationAlignedViewport.y;
- viewport.Width = orientationAlignedViewport.w;
- viewport.Height = orientationAlignedViewport.h;
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- /* SDL_Log("%s: D3D viewport = {%f,%f,%f,%f}\n", __FUNCTION__, viewport.TopLeftX, viewport.TopLeftY, viewport.Width, viewport.Height); */
- ID3D11DeviceContext_RSSetViewports(data->d3dContext, 1, &viewport);
+ d3dviewport.TopLeftX = orientationAlignedViewport.x;
+ d3dviewport.TopLeftY = orientationAlignedViewport.y;
+ d3dviewport.Width = orientationAlignedViewport.w;
+ d3dviewport.Height = orientationAlignedViewport.h;
+ d3dviewport.MinDepth = 0.0f;
+ d3dviewport.MaxDepth = 1.0f;
+ /* SDL_Log("%s: D3D viewport = {%f,%f,%f,%f}\n", __FUNCTION__, d3dviewport.TopLeftX, d3dviewport.TopLeftY, d3dviewport.Width, d3dviewport.Height); */
+ ID3D11DeviceContext_RSSetViewports(data->d3dContext, 1, &d3dviewport);
+
+ data->viewportDirty = SDL_FALSE;
return 0;
-}
-
-static int
-D3D11_UpdateClipRect(SDL_Renderer * renderer)
-{
- D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
-
- if (!renderer->clipping_enabled) {
- ID3D11DeviceContext_RSSetScissorRects(data->d3dContext, 0, NULL);
- } else {
- D3D11_RECT scissorRect;
- if (D3D11_GetViewportAlignedD3DRect(renderer, &renderer->clip_rect, &scissorRect, TRUE) != 0) {
- /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
- return -1;
- }
- ID3D11DeviceContext_RSSetScissorRects(data->d3dContext, 1, &scissorRect);
- }
-
- return 0;
-}
-
-static void
-D3D11_ReleaseMainRenderTargetView(SDL_Renderer * renderer)
-{
- D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
- ID3D11DeviceContext_OMSetRenderTargets(data->d3dContext, 0, NULL, NULL);
- SAFE_RELEASE(data->mainRenderTargetView);
}
static ID3D11RenderTargetView *
D3D11_GetCurrentRenderTargetView(SDL_Renderer * renderer)
{
- D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
+ D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
if (data->currentOffscreenRenderTargetView) {
return data->currentOffscreenRenderTargetView;
- } else {
+ }
+ else {
return data->mainRenderTargetView;
}
}
static int
-D3D11_RenderClear(SDL_Renderer * renderer)
-{
- D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
- const float colorRGBA[] = {
- (renderer->r / 255.0f),
- (renderer->g / 255.0f),
- (renderer->b / 255.0f),
- (renderer->a / 255.0f)
- };
- ID3D11DeviceContext_ClearRenderTargetView(data->d3dContext,
- D3D11_GetCurrentRenderTargetView(renderer),
- colorRGBA
- );
- return 0;
-}
+D3D11_SetDrawState(SDL_Renderer * renderer, const SDL_RenderCommand *cmd, ID3D11PixelShader * shader,
+ const int numShaderResources, ID3D11ShaderResourceView ** shaderResources,
+ ID3D11SamplerState * sampler, const Float4X4 *matrix)
-static int
-D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
- const void * vertexData, size_t dataSizeInBytes)
-{
- D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
- D3D11_BUFFER_DESC vertexBufferDesc;
- HRESULT result = S_OK;
- D3D11_SUBRESOURCE_DATA vertexBufferData;
- const UINT stride = sizeof(VertexPositionColor);
- const UINT offset = 0;
-
- if (rendererData->vertexBuffer) {
- ID3D11Buffer_GetDesc(rendererData->vertexBuffer, &vertexBufferDesc);
- } else {
- SDL_zero(vertexBufferDesc);
- }
-
- if (rendererData->vertexBuffer && vertexBufferDesc.ByteWidth >= dataSizeInBytes) {
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- result = ID3D11DeviceContext_Map(rendererData->d3dContext,
- (ID3D11Resource *)rendererData->vertexBuffer,
- 0,
- D3D11_MAP_WRITE_DISCARD,
- 0,
- &mappedResource
- );
- if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [vertex buffer]"), result);
- return -1;
- }
- SDL_memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
- ID3D11DeviceContext_Unmap(rendererData->d3dContext, (ID3D11Resource *)rendererData->vertexBuffer, 0);
- } else {
- SAFE_RELEASE(rendererData->vertexBuffer);
-
- vertexBufferDesc.ByteWidth = (UINT) dataSizeInBytes;
- vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-
- SDL_zero(vertexBufferData);
- vertexBufferData.pSysMem = vertexData;
- vertexBufferData.SysMemPitch = 0;
- vertexBufferData.SysMemSlicePitch = 0;
-
- result = ID3D11Device_CreateBuffer(rendererData->d3dDevice,
- &vertexBufferDesc,
- &vertexBufferData,
- &rendererData->vertexBuffer
- );
- if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex buffer]"), result);
- return -1;
- }
-
- ID3D11DeviceContext_IASetVertexBuffers(rendererData->d3dContext,
- 0,
- 1,
- &rendererData->vertexBuffer,
- &stride,
- &offset
- );
- }
-
- return 0;
-}
-
-static void
-D3D11_RenderStartDrawOp(SDL_Renderer * renderer)
{
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
+ const Float4X4 *newmatrix = matrix ? matrix : &rendererData->identity;
ID3D11RasterizerState *rasterizerState;
ID3D11RenderTargetView *renderTargetView = D3D11_GetCurrentRenderTargetView(renderer);
+ ID3D11ShaderResourceView *shaderResource;
+ const SDL_BlendMode blendMode = cmd->data.draw.blend;
+ ID3D11BlendState *blendState = NULL;
+ SDL_bool updateSubresource = SDL_FALSE;
+
if (renderTargetView != rendererData->currentRenderTargetView) {
ID3D11DeviceContext_OMSetRenderTargets(rendererData->d3dContext,
1,
@@ -1931,7 +2033,28 @@
rendererData->currentRenderTargetView = renderTargetView;
}
- if (!renderer->clipping_enabled) {
+ if (rendererData->viewportDirty) {
+ if (D3D11_UpdateViewport(renderer) == 0) {
+ /* vertexShaderConstantsData.projectionAndView has changed */
+ updateSubresource = SDL_TRUE;
+ }
+ }
+
+ if (rendererData->cliprectDirty) {
+ if (!rendererData->currentCliprectEnabled) {
+ ID3D11DeviceContext_RSSetScissorRects(rendererData->d3dContext, 0, NULL);
+ } else {
+ D3D11_RECT scissorRect;
+ if (D3D11_GetViewportAlignedD3DRect(renderer, &rendererData->currentCliprect, &scissorRect, TRUE) != 0) {
+ /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
+ return -1;
+ }
+ ID3D11DeviceContext_RSSetScissorRects(rendererData->d3dContext, 1, &scissorRect);
+ }
+ rendererData->cliprectDirty = SDL_FALSE;
+ }
+
+ if (!rendererData->currentCliprectEnabled) {
rasterizerState = rendererData->mainRasterizer;
} else {
rasterizerState = rendererData->clippedRasterizer;
@@ -1940,13 +2063,7 @@
ID3D11DeviceContext_RSSetState(rendererData->d3dContext, rasterizerState);
rendererData->currentRasterizerState = rasterizerState;
}
-}
-static void
-D3D11_RenderSetBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
-{
- D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
- ID3D11BlendState *blendState = NULL;
if (blendMode != SDL_BLENDMODE_NONE) {
int i;
for (i = 0; i < rendererData->blendModesCount; ++i) {
@@ -1956,28 +2073,17 @@
}
}
if (!blendState) {
- if (D3D11_CreateBlendState(renderer, blendMode)) {
- /* Successfully created the blend state, try again */
- D3D11_RenderSetBlendMode(renderer, blendMode);
+ blendState = D3D11_CreateBlendState(renderer, blendMode);
+ if (!blendState) {
+ return -1;
}
- return;
}
}
if (blendState != rendererData->currentBlendState) {
ID3D11DeviceContext_OMSetBlendState(rendererData->d3dContext, blendState, 0, 0xFFFFFFFF);
rendererData->currentBlendState = blendState;
}
-}
-static void
-D3D11_SetPixelShader(SDL_Renderer * renderer,
- ID3D11PixelShader * shader,
- int numShaderResources,
- ID3D11ShaderResourceView ** shaderResources,
- ID3D11SamplerState * sampler)
-{
- D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
- ID3D11ShaderResourceView *shaderResource;
if (shader != rendererData->currentShader) {
ID3D11DeviceContext_PSSetShader(rendererData->d3dContext, shader, NULL, 0);
rendererData->currentShader = shader;
@@ -1995,146 +2101,26 @@
ID3D11DeviceContext_PSSetSamplers(rendererData->d3dContext, 0, 1, &sampler);
rendererData->currentSampler = sampler;
}
-}
-static void
-D3D11_RenderFinishDrawOp(SDL_Renderer * renderer,
- D3D11_PRIMITIVE_TOPOLOGY primitiveTopology,
- UINT vertexCount)
-{
- D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
-
- ID3D11DeviceContext_IASetPrimitiveTopology(rendererData->d3dContext, primitiveTopology);
- ID3D11DeviceContext_Draw(rendererData->d3dContext, vertexCount, 0);
-}
-
-static int
-D3D11_RenderDrawPoints(SDL_Renderer * renderer,
- const SDL_FPoint * points, int count)
-{
- D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
- float r, g, b, a;
- VertexPositionColor *vertices;
- int i;
-
- r = (float)(renderer->r / 255.0f);
- g = (float)(renderer->g / 255.0f);
- b = (float)(renderer->b / 255.0f);
- a = (float)(renderer->a / 255.0f);
-
- vertices = SDL_stack_alloc(VertexPositionColor, count);
- for (i = 0; i < count; ++i) {
- const VertexPositionColor v = { { points[i].x + 0.5f, points[i].y + 0.5f, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } };
- vertices[i] = v;
- }
-
- D3D11_RenderStartDrawOp(renderer);
- D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
- if (D3D11_UpdateVertexBuffer(renderer, vertices, (unsigned int)count * sizeof(VertexPositionColor)) != 0) {
- SDL_stack_free(vertices);
- return -1;
- }
-
- D3D11_SetPixelShader(
- renderer,
- rendererData->pixelShaders[SHADER_SOLID],
- 0,
- NULL,
- NULL);
-
- D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, count);
- SDL_stack_free(vertices);
- return 0;
-}
-
-static int
-D3D11_RenderDrawLines(SDL_Renderer * renderer,
- const SDL_FPoint * points, int count)
-{
- D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
- float r, g, b, a;
- VertexPositionColor *vertices;
- int i;
-
- r = (float)(renderer->r / 255.0f);
- g = (float)(renderer->g / 255.0f);
- b = (float)(renderer->b / 255.0f);
- a = (float)(renderer->a / 255.0f);
-
- vertices = SDL_stack_alloc(VertexPositionColor, count);
- for (i = 0; i < count; ++i) {
- const VertexPositionColor v = { { points[i].x + 0.5f, points[i].y + 0.5f, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } };
- vertices[i] = v;
- }
-
- D3D11_RenderStartDrawOp(renderer);
- D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
- if (D3D11_UpdateVertexBuffer(renderer, vertices, (unsigned int)count * sizeof(VertexPositionColor)) != 0) {
- SDL_stack_free(vertices);
- return -1;
- }
-
- D3D11_SetPixelShader(
- renderer,
- rendererData->pixelShaders[SHADER_SOLID],
- 0,
- NULL,
- NULL);
-
- D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, count);
-
- if (points[0].x != points[count - 1].x || points[0].y != points[count - 1].y) {
- ID3D11DeviceContext_IASetPrimitiveTopology(rendererData->d3dContext, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
- ID3D11DeviceContext_Draw(rendererData->d3dContext, 1, count - 1);
- }
-
- SDL_stack_free(vertices);
- return 0;
-}
-
-static int
-D3D11_RenderFillRects(SDL_Renderer * renderer,
- const SDL_FRect * rects, int count)
-{
- D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
- float r, g, b, a;
- int i;
-
- r = (float)(renderer->r / 255.0f);
- g = (float)(renderer->g / 255.0f);
- b = (float)(renderer->b / 255.0f);
- a = (float)(renderer->a / 255.0f);
-
- for (i = 0; i < count; ++i) {
- VertexPositionColor vertices[] = {
- { { rects[i].x, rects[i].y, 0.0f }, { 0.0f, 0.0f}, {r, g, b, a} },
- { { rects[i].x, rects[i].y + rects[i].h, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } },
- { { rects[i].x + rects[i].w, rects[i].y, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } },
- { { rects[i].x + rects[i].w, rects[i].y + rects[i].h, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } },
- };
-
- D3D11_RenderStartDrawOp(renderer);
- D3D11_RenderSetBlendMode(renderer, renderer->blendMode);
- if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
- return -1;
- }
-
- D3D11_SetPixelShader(
- renderer,
- rendererData->pixelShaders[SHADER_SOLID],
+ if (updateSubresource == SDL_TRUE || SDL_memcmp(&rendererData->vertexShaderConstantsData.model, newmatrix, sizeof (*newmatrix)) != 0) {
+ SDL_memcpy(&rendererData->vertexShaderConstantsData.model, newmatrix, sizeof (*newmatrix));
+ ID3D11DeviceContext_UpdateSubresource(rendererData->d3dContext,
+ (ID3D11Resource *)rendererData->vertexShaderConstants,
0,
NULL,
- NULL);
-
- D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, SDL_arraysize(vertices));
+ &rendererData->vertexShaderConstantsData,
+ 0,
+ 0
+ );
}
return 0;
}
static int
-D3D11_RenderSetupSampler(SDL_Renderer * renderer, SDL_Texture * texture)
+D3D11_SetCopyState(SDL_Renderer * renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix)
{
+ SDL_Texture *texture = cmd->data.draw.texture;
D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
ID3D11SamplerState *textureSampler;
@@ -2172,12 +2158,8 @@
return SDL_SetError("Unsupported YUV conversion mode");
}
- D3D11_SetPixelShader(
- renderer,
- rendererData->pixelShaders[shader],
- SDL_arraysize(shaderResources),
- shaderResources,
- textureSampler);
+ return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[shader],
+ SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix);
} else if (textureData->nv12) {
ID3D11ShaderResourceView *shaderResources[] = {
@@ -2200,188 +2182,140 @@
return SDL_SetError("Unsupported YUV conversion mode");
}
- D3D11_SetPixelShader(
- renderer,
- rendererData->pixelShaders[shader],
- SDL_arraysize(shaderResources),
- shaderResources,
- textureSampler);
+ return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[shader],
+ SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix);
- } else {
- D3D11_SetPixelShader(
- renderer,
- rendererData->pixelShaders[SHADER_RGB],
- 1,
- &textureData->mainTextureResourceView,
- textureSampler);
}
- return 0;
+ return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_RGB],
+ 1, &textureData->mainTextureResourceView, textureSampler, matrix);
+}
+
+static void
+D3D11_DrawPrimitives(SDL_Renderer * renderer, D3D11_PRIMITIVE_TOPOLOGY primitiveTopology, const size_t vertexStart, const size_t vertexCount)
+{
+ D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
+ ID3D11DeviceContext_IASetPrimitiveTopology(rendererData->d3dContext, primitiveTopology);
+ ID3D11DeviceContext_Draw(rendererData->d3dContext, (UINT) vertexCount, (UINT) vertexStart);
}
static int
-D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_FRect * dstrect)
+D3D11_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
- float minu, maxu, minv, maxv;
- Float4 color;
- VertexPositionColor vertices[4];
+ D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
+ const int viewportRotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
+ size_t i;
- D3D11_RenderStartDrawOp(renderer);
- D3D11_RenderSetBlendMode(renderer, texture->blendMode);
-
- minu = (float) srcrect->x / texture->w;
- maxu = (float) (srcrect->x + srcrect->w) / texture->w;
- minv = (float) srcrect->y / texture->h;
- maxv = (float) (srcrect->y + srcrect->h) / texture->h;
-
- color.x = 1.0f; /* red */
- color.y = 1.0f; /* green */
- color.z = 1.0f; /* blue */
- color.w = 1.0f; /* alpha */
- if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
- color.x = (float)(texture->r / 255.0f); /* red */
- color.y = (float)(texture->g / 255.0f); /* green */
- color.z = (float)(texture->b / 255.0f); /* blue */
- }
- if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
- color.w = (float)(texture->a / 255.0f); /* alpha */
+ if (rendererData->currentViewportRotation != viewportRotation) {
+ rendererData->currentViewportRotation = viewportRotation;
+ rendererData->viewportDirty = SDL_TRUE;
}
- vertices[0].pos.x = dstrect->x;
- vertices[0].pos.y = dstrect->y;
- vertices[0].pos.z = 0.0f;
- vertices[0].tex.x = minu;
- vertices[0].tex.y = minv;
- vertices[0].color = color;
-
- vertices[1].pos.x = dstrect->x;
- vertices[1].pos.y = dstrect->y + dstrect->h;
- vertices[1].pos.z = 0.0f;
- vertices[1].tex.x = minu;
- vertices[1].tex.y = maxv;
- vertices[1].color = color;
-
- vertices[2].pos.x = dstrect->x + dstrect->w;
- vertices[2].pos.y = dstrect->y;
- vertices[2].pos.z = 0.0f;
- vertices[2].tex.x = maxu;
- vertices[2].tex.y = minv;
- vertices[2].color = color;
-
- vertices[3].pos.x = dstrect->x + dstrect->w;
- vertices[3].pos.y = dstrect->y + dstrect->h;
- vertices[3].pos.z = 0.0f;
- vertices[3].tex.x = maxu;
- vertices[3].tex.y = maxv;
- vertices[3].color = color;
-
- if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
+ if (D3D11_UpdateVertexBuffer(renderer, vertices, vertsize) < 0) {
return -1;
}
- if (D3D11_RenderSetupSampler(renderer, texture) < 0) {
- return -1;
+ while (cmd) {
+ switch (cmd->command) {
+ case SDL_RENDERCMD_SETDRAWCOLOR: {
+ break; /* this isn't currently used in this render backend. */
+ }
+
+ case SDL_RENDERCMD_SETVIEWPORT: {
+ SDL_Rect *viewport = &rendererData->currentViewport;
+ if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
+ SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
+ rendererData->viewportDirty = SDL_TRUE;
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_SETCLIPRECT: {
+ const SDL_Rect *rect = &cmd->data.cliprect.rect;
+ if (rendererData->currentCliprectEnabled != cmd->data.cliprect.enabled) {
+ rendererData->currentCliprectEnabled = cmd->data.cliprect.enabled;
+ rendererData->cliprectDirty = SDL_TRUE;
+ }
+ if (SDL_memcmp(&rendererData->currentCliprect, rect, sizeof (SDL_Rect)) != 0) {
+ SDL_memcpy(&rendererData->currentCliprect, rect, sizeof (SDL_Rect));
+ rendererData->cliprectDirty = SDL_TRUE;
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_CLEAR: {
+ const float colorRGBA[] = {
+ (cmd->data.color.r / 255.0f),
+ (cmd->data.color.g / 255.0f),
+ (cmd->data.color.b / 255.0f),
+ (cmd->data.color.a / 255.0f)
+ };
+ ID3D11DeviceContext_ClearRenderTargetView(rendererData->d3dContext, D3D11_GetCurrentRenderTargetView(renderer), colorRGBA);
+ break;
+ }
+
+ case SDL_RENDERCMD_DRAW_POINTS: {
+ const size_t count = cmd->data.draw.count;
+ const size_t first = cmd->data.draw.first;
+ const size_t start = first / sizeof (VertexPositionColor);
+ D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
+ D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start, count);
+ break;
+ }
+
+ case SDL_RENDERCMD_DRAW_LINES: {
+ const size_t count = cmd->data.draw.count;
+ const size_t first = cmd->data.draw.first;
+ const size_t start = first / sizeof (VertexPositionColor);
+ const VertexPositionColor *verts = (VertexPositionColor *) (((Uint8 *) vertices) + first);
+ D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
+ D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count);
+ if (verts[0].pos.x != verts[count - 1].pos.x || verts[0].pos.y != verts[count - 1].pos.y) {
+ D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start + (count-1), 1);
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_FILL_RECTS: {
+ const size_t count = cmd->data.draw.count;
+ const size_t first = cmd->data.draw.first;
+ const size_t start = first / sizeof (VertexPositionColor);
+ size_t offset = 0;
+ D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
+ for (i = 0; i < count; i++, offset += 4) {
+ D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start + offset, 4);
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_COPY: {
+ const size_t first = cmd->data.draw.first;
+ const size_t start = first / sizeof (VertexPositionColor);
+ D3D11_SetCopyState(renderer, cmd, NULL);
+ D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start, 4);
+ break;
+ }
+
+ case SDL_RENDERCMD_COPY_EX: {
+ const size_t first = cmd->data.draw.first;
+ const size_t start = first / sizeof (VertexPositionColor);
+ const VertexPositionColor *verts = (VertexPositionColor *) (((Uint8 *) vertices) + first);
+ const VertexPositionColor *transvert = verts + 4;
+ const float translatex = transvert->pos.x;
+ const float translatey = transvert->pos.y;
+ const float rotation = transvert->pos.z;
+ const Float4X4 matrix = MatrixMultiply(MatrixRotationZ(rotation), MatrixTranslation(translatex, translatey, 0));
+ D3D11_SetCopyState(renderer, cmd, &matrix);
+ D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start, 4);
+ break;
+ }
+
+ case SDL_RENDERCMD_NO_OP:
+ break;
+ }
+
+ cmd = cmd->next;
}
-
- D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
-
- return 0;
-}
-
-static int
-D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_FRect * dstrect,
- const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
-{
- float minu, maxu, minv, maxv;
- Float4 color;
- Float4X4 modelMatrix;
- float minx, maxx, miny, maxy;
- VertexPositionColor vertices[4];
-
- D3D11_RenderStartDrawOp(renderer);
- D3D11_RenderSetBlendMode(renderer, texture->blendMode);
-
- minu = (float) srcrect->x / texture->w;
- maxu = (float) (srcrect->x + srcrect->w) / texture->w;
- minv = (float) srcrect->y / texture->h;
- maxv = (float) (srcrect->y + srcrect->h) / texture->h;
-
- color.x = 1.0f; /* red */
- color.y = 1.0f; /* green */
- color.z = 1.0f; /* blue */
- color.w = 1.0f; /* alpha */
- if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
- color.x = (float)(texture->r / 255.0f); /* red */
- color.y = (float)(texture->g / 255.0f); /* green */
- color.z = (float)(texture->b / 255.0f); /* blue */
- }
- if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
- color.w = (float)(texture->a / 255.0f); /* alpha */
- }
-
- if (flip & SDL_FLIP_HORIZONTAL) {
- float tmp = maxu;
- maxu = minu;
- minu = tmp;
- }
- if (flip & SDL_FLIP_VERTICAL) {
- float tmp = maxv;
- maxv = minv;
- minv = tmp;
- }
-
- modelMatrix = MatrixMultiply(
- MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)),
- MatrixTranslation(dstrect->x + center->x, dstrect->y + center->y, 0)
- );
- D3D11_SetModelMatrix(renderer, &modelMatrix);
-
- minx = -center->x;
- maxx = dstrect->w - center->x;
- miny = -center->y;
- maxy = dstrect->h - center->y;
-
- vertices[0].pos.x = minx;
- vertices[0].pos.y = miny;
- vertices[0].pos.z = 0.0f;
- vertices[0].tex.x = minu;
- vertices[0].tex.y = minv;
- vertices[0].color = color;
-
- vertices[1].pos.x = minx;
- vertices[1].pos.y = maxy;
- vertices[1].pos.z = 0.0f;
- vertices[1].tex.x = minu;
- vertices[1].tex.y = maxv;
- vertices[1].color = color;
-
- vertices[2].pos.x = maxx;
- vertices[2].pos.y = miny;
- vertices[2].pos.z = 0.0f;
- vertices[2].tex.x = maxu;
- vertices[2].tex.y = minv;
- vertices[2].color = color;
-
- vertices[3].pos.x = maxx;
- vertices[3].pos.y = maxy;
- vertices[3].pos.z = 0.0f;
- vertices[3].tex.x = maxu;
- vertices[3].tex.y = maxv;
- vertices[3].color = color;
-
- if (D3D11_UpdateVertexBuffer(renderer, vertices, sizeof(vertices)) != 0) {
- return -1;
- }
-
- if (D3D11_RenderSetupSampler(renderer, texture) < 0) {
- return -1;
- }
-
- D3D11_RenderFinishDrawOp(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, sizeof(vertices) / sizeof(VertexPositionColor));
-
- D3D11_SetModelMatrix(renderer, NULL);
return 0;
}
@@ -2550,6 +2484,111 @@
}
}
+SDL_Renderer *
+D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+ SDL_Renderer *renderer;
+ D3D11_RenderData *data;
+
+ renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+ if (!renderer) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ data = (D3D11_RenderData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ data->identity = MatrixIdentity();
+
+ renderer->WindowEvent = D3D11_WindowEvent;
+ renderer->SupportsBlendMode = D3D11_SupportsBlendMode;
+ renderer->CreateTexture = D3D11_CreateTexture;
+ renderer->UpdateTexture = D3D11_UpdateTexture;
+ renderer->UpdateTextureYUV = D3D11_UpdateTextureYUV;
+ renderer->LockTexture = D3D11_LockTexture;
+ renderer->UnlockTexture = D3D11_UnlockTexture;
+ renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode;
+ renderer->SetRenderTarget = D3D11_SetRenderTarget;
+ renderer->QueueSetViewport = D3D11_QueueSetViewport;
+ renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
+ renderer->QueueDrawPoints = D3D11_QueueDrawPoints;
+ renderer->QueueDrawLines = D3D11_QueueDrawPoints; /* lines and points queue vertices the same way. */
+ renderer->QueueFillRects = D3D11_QueueFillRects;
+ renderer->QueueCopy = D3D11_QueueCopy;
+ renderer->QueueCopyEx = D3D11_QueueCopyEx;
+ renderer->RunCommandQueue = D3D11_RunCommandQueue;
+ renderer->RenderReadPixels = D3D11_RenderReadPixels;
+ renderer->RenderPresent = D3D11_RenderPresent;
+ renderer->DestroyTexture = D3D11_DestroyTexture;
+ renderer->DestroyRenderer = D3D11_DestroyRenderer;
+ renderer->info = D3D11_RenderDriver.info;
+ renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
+ renderer->driverdata = data;
+
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+ /* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
+ * Failure to use it seems to either result in:
+ *
+ * - with the D3D11 debug runtime turned OFF, vsync seemingly gets turned
+ * off (framerate doesn't get capped), but nothing appears on-screen
+ *
+ * - with the D3D11 debug runtime turned ON, vsync gets automatically
+ * turned back on, and the following gets output to the debug console:
+ *
+ * DXGI ERROR: IDXGISwapChain::Present: Interval 0 is not supported, changed to Interval 1. [ UNKNOWN ERROR #1024: ]
+ */
+ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
+#else
+ if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
+ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
+ }
+#endif
+
+ /* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
+ * order to give init functions access to the underlying window handle:
+ */
+ renderer->window = window;
+
+ /* Initialize Direct3D resources */
+ if (FAILED(D3D11_CreateDeviceResources(renderer))) {
+ D3D11_DestroyRenderer(renderer);
+ return NULL;
+ }
+ if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) {
+ D3D11_DestroyRenderer(renderer);
+ return NULL;
+ }
+
+ return renderer;
+}
+
+SDL_RenderDriver D3D11_RenderDriver = {
+ D3D11_CreateRenderer,
+ {
+ "direct3d11",
+ (
+ SDL_RENDERER_ACCELERATED |
+ SDL_RENDERER_PRESENTVSYNC |
+ SDL_RENDERER_TARGETTEXTURE
+ ), /* flags. see SDL_RendererFlags */
+ 6, /* num_texture_formats */
+ { /* texture_formats */
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_RGB888,
+ SDL_PIXELFORMAT_YV12,
+ SDL_PIXELFORMAT_IYUV,
+ SDL_PIXELFORMAT_NV12,
+ SDL_PIXELFORMAT_NV21
+ },
+ 0, /* max_texture_width: will be filled in later */
+ 0 /* max_texture_height: will be filled in later */
+ }
+};
+
#endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */
--
Gitblit v1.9.3