Atlas - SDL_render_d3d.c
Home / ext / SDL2 / src / render / direct3d Lines: 1 | Size: 59030 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#include "SDL_render.h" 24#include "SDL_system.h" 25 26#if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED 27 28#include "../../core/windows/SDL_windows.h" 29 30#include "SDL_hints.h" 31#include "SDL_loadso.h" 32#include "SDL_syswm.h" 33#include "../SDL_sysrender.h" 34#include "../SDL_d3dmath.h" 35#include "../../video/windows/SDL_windowsvideo.h" 36 37#if SDL_VIDEO_RENDER_D3D 38#define D3D_DEBUG_INFO 39#include <d3d9.h> 40#endif 41 42#include "SDL_shaders_d3d.h" 43 44 45/* Direct3D renderer implementation */ 46 47static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags); 48static void D3D_WindowEvent(SDL_Renderer * renderer, 49 const SDL_WindowEvent *event); 50static SDL_bool D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode); 51static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); 52static int D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); 53static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 54 const SDL_Rect * rect, const void *pixels, 55 int pitch); 56static int D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, 57 const SDL_Rect * rect, 58 const Uint8 *Yplane, int Ypitch, 59 const Uint8 *Uplane, int Upitch, 60 const Uint8 *Vplane, int Vpitch); 61static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 62 const SDL_Rect * rect, void **pixels, int *pitch); 63static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); 64static int D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture); 65static int D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture); 66static int D3D_UpdateViewport(SDL_Renderer * renderer); 67static int D3D_UpdateClipRect(SDL_Renderer * renderer); 68static int D3D_RenderClear(SDL_Renderer * renderer); 69static int D3D_RenderDrawPoints(SDL_Renderer * renderer, 70 const SDL_FPoint * points, int count); 71static int D3D_RenderDrawLines(SDL_Renderer * renderer, 72 const SDL_FPoint * points, int count); 73static int D3D_RenderFillRects(SDL_Renderer * renderer, 74 const SDL_FRect * rects, int count); 75static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 76 const SDL_Rect * srcrect, const SDL_FRect * dstrect); 77static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, 78 const SDL_Rect * srcrect, const SDL_FRect * dstrect, 79 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip); 80static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, 81 Uint32 format, void * pixels, int pitch); 82static void D3D_RenderPresent(SDL_Renderer * renderer); 83static void D3D_DestroyTexture(SDL_Renderer * renderer, 84 SDL_Texture * texture); 85static void D3D_DestroyRenderer(SDL_Renderer * renderer); 86 87 88SDL_RenderDriver D3D_RenderDriver = { 89 D3D_CreateRenderer, 90 { 91 "direct3d", 92 (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE), 93 1, 94 {SDL_PIXELFORMAT_ARGB8888}, 95 0, 96 0} 97}; 98 99typedef struct 100{ 101 void* d3dDLL; 102 IDirect3D9 *d3d; 103 IDirect3DDevice9 *device; 104 UINT adapter; 105 D3DPRESENT_PARAMETERS pparams; 106 SDL_bool updateSize; 107 SDL_bool beginScene; 108 SDL_bool enableSeparateAlphaBlend; 109 D3DTEXTUREFILTERTYPE scaleMode[8]; 110 IDirect3DSurface9 *defaultRenderTarget; 111 IDirect3DSurface9 *currentRenderTarget; 112 void* d3dxDLL; 113 LPDIRECT3DPIXELSHADER9 shaders[NUM_SHADERS]; 114} D3D_RenderData; 115 116typedef struct 117{ 118 SDL_bool dirty; 119 int w, h; 120 DWORD usage; 121 Uint32 format; 122 D3DFORMAT d3dfmt; 123 IDirect3DTexture9 *texture; 124 IDirect3DTexture9 *staging; 125} D3D_TextureRep; 126 127typedef struct 128{ 129 D3D_TextureRep texture; 130 D3DTEXTUREFILTERTYPE scaleMode; 131 132 /* YV12 texture support */ 133 SDL_bool yuv; 134 D3D_TextureRep utexture; 135 D3D_TextureRep vtexture; 136 Uint8 *pixels; 137 int pitch; 138 SDL_Rect locked_rect; 139} D3D_TextureData; 140 141typedef struct 142{ 143 float x, y, z; 144 DWORD color; 145 float u, v; 146} Vertex; 147 148static int 149D3D_SetError(const char *prefix, HRESULT result) 150{ 151 const char *error; 152 153 switch (result) { 154 case D3DERR_WRONGTEXTUREFORMAT: 155 error = "WRONGTEXTUREFORMAT"; 156 break; 157 case D3DERR_UNSUPPORTEDCOLOROPERATION: 158 error = "UNSUPPORTEDCOLOROPERATION"; 159 break; 160 case D3DERR_UNSUPPORTEDCOLORARG: 161 error = "UNSUPPORTEDCOLORARG"; 162 break; 163 case D3DERR_UNSUPPORTEDALPHAOPERATION: 164 error = "UNSUPPORTEDALPHAOPERATION"; 165 break; 166 case D3DERR_UNSUPPORTEDALPHAARG: 167 error = "UNSUPPORTEDALPHAARG"; 168 break; 169 case D3DERR_TOOMANYOPERATIONS: 170 error = "TOOMANYOPERATIONS"; 171 break; 172 case D3DERR_CONFLICTINGTEXTUREFILTER: 173 error = "CONFLICTINGTEXTUREFILTER"; 174 break; 175 case D3DERR_UNSUPPORTEDFACTORVALUE: 176 error = "UNSUPPORTEDFACTORVALUE"; 177 break; 178 case D3DERR_CONFLICTINGRENDERSTATE: 179 error = "CONFLICTINGRENDERSTATE"; 180 break; 181 case D3DERR_UNSUPPORTEDTEXTUREFILTER: 182 error = "UNSUPPORTEDTEXTUREFILTER"; 183 break; 184 case D3DERR_CONFLICTINGTEXTUREPALETTE: 185 error = "CONFLICTINGTEXTUREPALETTE"; 186 break; 187 case D3DERR_DRIVERINTERNALERROR: 188 error = "DRIVERINTERNALERROR"; 189 break; 190 case D3DERR_NOTFOUND: 191 error = "NOTFOUND"; 192 break; 193 case D3DERR_MOREDATA: 194 error = "MOREDATA"; 195 break; 196 case D3DERR_DEVICELOST: 197 error = "DEVICELOST"; 198 break; 199 case D3DERR_DEVICENOTRESET: 200 error = "DEVICENOTRESET"; 201 break; 202 case D3DERR_NOTAVAILABLE: 203 error = "NOTAVAILABLE"; 204 break; 205 case D3DERR_OUTOFVIDEOMEMORY: 206 error = "OUTOFVIDEOMEMORY"; 207 break; 208 case D3DERR_INVALIDDEVICE: 209 error = "INVALIDDEVICE"; 210 break; 211 case D3DERR_INVALIDCALL: 212 error = "INVALIDCALL"; 213 break; 214 case D3DERR_DRIVERINVALIDCALL: 215 error = "DRIVERINVALIDCALL"; 216 break; 217 case D3DERR_WASSTILLDRAWING: 218 error = "WASSTILLDRAWING"; 219 break; 220 default: 221 error = "UNKNOWN"; 222 break; 223 } 224 return SDL_SetError("%s: %s", prefix, error); 225} 226 227static D3DFORMAT 228PixelFormatToD3DFMT(Uint32 format) 229{ 230 switch (format) { 231 case SDL_PIXELFORMAT_RGB565: 232 return D3DFMT_R5G6B5; 233 case SDL_PIXELFORMAT_RGB888: 234 return D3DFMT_X8R8G8B8; 235 case SDL_PIXELFORMAT_ARGB8888: 236 return D3DFMT_A8R8G8B8; 237 case SDL_PIXELFORMAT_YV12: 238 case SDL_PIXELFORMAT_IYUV: 239 case SDL_PIXELFORMAT_NV12: 240 case SDL_PIXELFORMAT_NV21: 241 return D3DFMT_L8; 242 default: 243 return D3DFMT_UNKNOWN; 244 } 245} 246 247static Uint32 248D3DFMTToPixelFormat(D3DFORMAT format) 249{ 250 switch (format) { 251 case D3DFMT_R5G6B5: 252 return SDL_PIXELFORMAT_RGB565; 253 case D3DFMT_X8R8G8B8: 254 return SDL_PIXELFORMAT_RGB888; 255 case D3DFMT_A8R8G8B8: 256 return SDL_PIXELFORMAT_ARGB8888; 257 default: 258 return SDL_PIXELFORMAT_UNKNOWN; 259 } 260} 261 262static void 263D3D_InitRenderState(D3D_RenderData *data) 264{ 265 D3DMATRIX matrix; 266 267 IDirect3DDevice9 *device = data->device; 268 269 IDirect3DDevice9_SetVertexShader(device, NULL); 270 IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); 271 IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE); 272 IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE); 273 IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE); 274 275 /* Enable color modulation by diffuse color */ 276 IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, 277 D3DTOP_MODULATE); 278 IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, 279 D3DTA_TEXTURE); 280 IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, 281 D3DTA_DIFFUSE); 282 283 /* Enable alpha modulation by diffuse alpha */ 284 IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, 285 D3DTOP_MODULATE); 286 IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, 287 D3DTA_TEXTURE); 288 IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG2, 289 D3DTA_DIFFUSE); 290 291 /* Enable separate alpha blend function, if possible */ 292 if (data->enableSeparateAlphaBlend) { 293 IDirect3DDevice9_SetRenderState(device, D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 294 } 295 296 /* Disable second texture stage, since we're done */ 297 IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, 298 D3DTOP_DISABLE); 299 IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP, 300 D3DTOP_DISABLE); 301 302 /* Set an identity world and view matrix */ 303 matrix.m[0][0] = 1.0f; 304 matrix.m[0][1] = 0.0f; 305 matrix.m[0][2] = 0.0f; 306 matrix.m[0][3] = 0.0f; 307 matrix.m[1][0] = 0.0f; 308 matrix.m[1][1] = 1.0f; 309 matrix.m[1][2] = 0.0f; 310 matrix.m[1][3] = 0.0f; 311 matrix.m[2][0] = 0.0f; 312 matrix.m[2][1] = 0.0f; 313 matrix.m[2][2] = 1.0f; 314 matrix.m[2][3] = 0.0f; 315 matrix.m[3][0] = 0.0f; 316 matrix.m[3][1] = 0.0f; 317 matrix.m[3][2] = 0.0f; 318 matrix.m[3][3] = 1.0f; 319 IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &matrix); 320 IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix); 321 322 /* Reset our current scale mode */ 323 SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode)); 324 325 /* Start the render with beginScene */ 326 data->beginScene = SDL_TRUE; 327} 328 329static int 330D3D_Reset(SDL_Renderer * renderer) 331{ 332 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 333 HRESULT result; 334 SDL_Texture *texture; 335 336 /* Release the default render target before reset */ 337 if (data->defaultRenderTarget) { 338 IDirect3DSurface9_Release(data->defaultRenderTarget); 339 data->defaultRenderTarget = NULL; 340 } 341 if (data->currentRenderTarget != NULL) { 342 IDirect3DSurface9_Release(data->currentRenderTarget); 343 data->currentRenderTarget = NULL; 344 } 345 346 /* Release application render targets */ 347 for (texture = renderer->textures; texture; texture = texture->next) { 348 if (texture->access == SDL_TEXTUREACCESS_TARGET) { 349 D3D_DestroyTexture(renderer, texture); 350 } else { 351 D3D_RecreateTexture(renderer, texture); 352 } 353 } 354 355 result = IDirect3DDevice9_Reset(data->device, &data->pparams); 356 if (FAILED(result)) { 357 if (result == D3DERR_DEVICELOST) { 358 /* Don't worry about it, we'll reset later... */ 359 return 0; 360 } else { 361 return D3D_SetError("Reset()", result); 362 } 363 } 364 365 /* Allocate application render targets */ 366 for (texture = renderer->textures; texture; texture = texture->next) { 367 if (texture->access == SDL_TEXTUREACCESS_TARGET) { 368 D3D_CreateTexture(renderer, texture); 369 } 370 } 371 372 IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget); 373 D3D_InitRenderState(data); 374 D3D_SetRenderTargetInternal(renderer, renderer->target); 375 D3D_UpdateViewport(renderer); 376 377 /* Let the application know that render targets were reset */ 378 { 379 SDL_Event event; 380 event.type = SDL_RENDER_TARGETS_RESET; 381 SDL_PushEvent(&event); 382 } 383 384 return 0; 385} 386 387static int 388D3D_ActivateRenderer(SDL_Renderer * renderer) 389{ 390 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 391 HRESULT result; 392 393 if (data->updateSize) { 394 SDL_Window *window = renderer->window; 395 int w, h; 396 Uint32 window_flags = SDL_GetWindowFlags(window); 397 398 SDL_GetWindowSize(window, &w, &h); 399 data->pparams.BackBufferWidth = w; 400 data->pparams.BackBufferHeight = h; 401 if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) { 402 SDL_DisplayMode fullscreen_mode; 403 SDL_GetWindowDisplayMode(window, &fullscreen_mode); 404 data->pparams.Windowed = FALSE; 405 data->pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format); 406 data->pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate; 407 } else { 408 data->pparams.Windowed = TRUE; 409 data->pparams.BackBufferFormat = D3DFMT_UNKNOWN; 410 data->pparams.FullScreen_RefreshRateInHz = 0; 411 } 412 if (D3D_Reset(renderer) < 0) { 413 return -1; 414 } 415 416 data->updateSize = SDL_FALSE; 417 } 418 if (data->beginScene) { 419 result = IDirect3DDevice9_BeginScene(data->device); 420 if (result == D3DERR_DEVICELOST) { 421 if (D3D_Reset(renderer) < 0) { 422 return -1; 423 } 424 result = IDirect3DDevice9_BeginScene(data->device); 425 } 426 if (FAILED(result)) { 427 return D3D_SetError("BeginScene()", result); 428 } 429 data->beginScene = SDL_FALSE; 430 } 431 return 0; 432} 433 434SDL_Renderer * 435D3D_CreateRenderer(SDL_Window * window, Uint32 flags) 436{ 437 SDL_Renderer *renderer; 438 D3D_RenderData *data; 439 SDL_SysWMinfo windowinfo; 440 HRESULT result; 441 D3DPRESENT_PARAMETERS pparams; 442 IDirect3DSwapChain9 *chain; 443 D3DCAPS9 caps; 444 DWORD device_flags; 445 Uint32 window_flags; 446 int w, h; 447 SDL_DisplayMode fullscreen_mode; 448 int displayIndex; 449 450 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); 451 if (!renderer) { 452 SDL_OutOfMemory(); 453 return NULL; 454 } 455 456 data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data)); 457 if (!data) { 458 SDL_free(renderer); 459 SDL_OutOfMemory(); 460 return NULL; 461 } 462 463 if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) { 464 SDL_free(renderer); 465 SDL_free(data); 466 SDL_SetError("Unable to create Direct3D interface"); 467 return NULL; 468 } 469 470 renderer->WindowEvent = D3D_WindowEvent; 471 renderer->SupportsBlendMode = D3D_SupportsBlendMode; 472 renderer->CreateTexture = D3D_CreateTexture; 473 renderer->UpdateTexture = D3D_UpdateTexture; 474 renderer->UpdateTextureYUV = D3D_UpdateTextureYUV; 475 renderer->LockTexture = D3D_LockTexture; 476 renderer->UnlockTexture = D3D_UnlockTexture; 477 renderer->SetRenderTarget = D3D_SetRenderTarget; 478 renderer->UpdateViewport = D3D_UpdateViewport; 479 renderer->UpdateClipRect = D3D_UpdateClipRect; 480 renderer->RenderClear = D3D_RenderClear; 481 renderer->RenderDrawPoints = D3D_RenderDrawPoints; 482 renderer->RenderDrawLines = D3D_RenderDrawLines; 483 renderer->RenderFillRects = D3D_RenderFillRects; 484 renderer->RenderCopy = D3D_RenderCopy; 485 renderer->RenderCopyEx = D3D_RenderCopyEx; 486 renderer->RenderReadPixels = D3D_RenderReadPixels; 487 renderer->RenderPresent = D3D_RenderPresent; 488 renderer->DestroyTexture = D3D_DestroyTexture; 489 renderer->DestroyRenderer = D3D_DestroyRenderer; 490 renderer->info = D3D_RenderDriver.info; 491 renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); 492 renderer->driverdata = data; 493 494 SDL_VERSION(&windowinfo.version); 495 SDL_GetWindowWMInfo(window, &windowinfo); 496 497 window_flags = SDL_GetWindowFlags(window); 498 SDL_GetWindowSize(window, &w, &h); 499 SDL_GetWindowDisplayMode(window, &fullscreen_mode); 500 501 SDL_zero(pparams); 502 pparams.hDeviceWindow = windowinfo.info.win.window; 503 pparams.BackBufferWidth = w; 504 pparams.BackBufferHeight = h; 505 pparams.BackBufferCount = 1; 506 pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; 507 508 if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) { 509 pparams.Windowed = FALSE; 510 pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format); 511 pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate; 512 } else { 513 pparams.Windowed = TRUE; 514 pparams.BackBufferFormat = D3DFMT_UNKNOWN; 515 pparams.FullScreen_RefreshRateInHz = 0; 516 } 517 if (flags & SDL_RENDERER_PRESENTVSYNC) { 518 pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; 519 } else { 520 pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; 521 } 522 523 /* Get the adapter for the display that the window is on */ 524 displayIndex = SDL_GetWindowDisplayIndex(window); 525 data->adapter = SDL_Direct3D9GetAdapterIndex(displayIndex); 526 527 IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps); 528 529 device_flags = D3DCREATE_FPU_PRESERVE; 530 if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { 531 device_flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; 532 } else { 533 device_flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; 534 } 535 536 if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_FALSE)) { 537 device_flags |= D3DCREATE_MULTITHREADED; 538 } 539 540 result = IDirect3D9_CreateDevice(data->d3d, data->adapter, 541 D3DDEVTYPE_HAL, 542 pparams.hDeviceWindow, 543 device_flags, 544 &pparams, &data->device); 545 if (FAILED(result)) { 546 D3D_DestroyRenderer(renderer); 547 D3D_SetError("CreateDevice()", result); 548 return NULL; 549 } 550 551 /* Get presentation parameters to fill info */ 552 result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain); 553 if (FAILED(result)) { 554 D3D_DestroyRenderer(renderer); 555 D3D_SetError("GetSwapChain()", result); 556 return NULL; 557 } 558 result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams); 559 if (FAILED(result)) { 560 IDirect3DSwapChain9_Release(chain); 561 D3D_DestroyRenderer(renderer); 562 D3D_SetError("GetPresentParameters()", result); 563 return NULL; 564 } 565 IDirect3DSwapChain9_Release(chain); 566 if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { 567 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; 568 } 569 data->pparams = pparams; 570 571 IDirect3DDevice9_GetDeviceCaps(data->device, &caps); 572 renderer->info.max_texture_width = caps.MaxTextureWidth; 573 renderer->info.max_texture_height = caps.MaxTextureHeight; 574 if (caps.NumSimultaneousRTs >= 2) { 575 renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE; 576 } 577 578 if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) { 579 data->enableSeparateAlphaBlend = SDL_TRUE; 580 } 581 582 /* Store the default render target */ 583 IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget); 584 data->currentRenderTarget = NULL; 585 586 /* Set up parameters for rendering */ 587 D3D_InitRenderState(data); 588 589 if (caps.MaxSimultaneousTextures >= 3) { 590 int i; 591 for (i = 0; i < SDL_arraysize(data->shaders); ++i) { 592 result = D3D9_CreatePixelShader(data->device, (D3D9_Shader)i, &data->shaders[i]); 593 if (FAILED(result)) { 594 D3D_SetError("CreatePixelShader()", result); 595 } 596 } 597 if (data->shaders[SHADER_YUV_JPEG] && data->shaders[SHADER_YUV_BT601] && data->shaders[SHADER_YUV_BT709]) { 598 renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12; 599 renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV; 600 } 601 } 602 return renderer; 603} 604 605static void 606D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) 607{ 608 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 609 610 if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) { 611 data->updateSize = SDL_TRUE; 612 } 613} 614 615static D3DBLEND GetBlendFunc(SDL_BlendFactor factor) 616{ 617 switch (factor) { 618 case SDL_BLENDFACTOR_ZERO: 619 return D3DBLEND_ZERO; 620 case SDL_BLENDFACTOR_ONE: 621 return D3DBLEND_ONE; 622 case SDL_BLENDFACTOR_SRC_COLOR: 623 return D3DBLEND_SRCCOLOR; 624 case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR: 625 return D3DBLEND_INVSRCCOLOR; 626 case SDL_BLENDFACTOR_SRC_ALPHA: 627 return D3DBLEND_SRCALPHA; 628 case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: 629 return D3DBLEND_INVSRCALPHA; 630 case SDL_BLENDFACTOR_DST_COLOR: 631 return D3DBLEND_DESTCOLOR; 632 case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR: 633 return D3DBLEND_INVDESTCOLOR; 634 case SDL_BLENDFACTOR_DST_ALPHA: 635 return D3DBLEND_DESTALPHA; 636 case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA: 637 return D3DBLEND_INVDESTALPHA; 638 default: 639 return (D3DBLEND)0; 640 } 641} 642 643static SDL_bool 644D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode) 645{ 646 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 647 SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode); 648 SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode); 649 SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode); 650 SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode); 651 SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode); 652 SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode); 653 654 if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) || 655 !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor)) { 656 return SDL_FALSE; 657 } 658 if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->enableSeparateAlphaBlend) { 659 return SDL_FALSE; 660 } 661 if (colorOperation != SDL_BLENDOPERATION_ADD || alphaOperation != SDL_BLENDOPERATION_ADD) { 662 return SDL_FALSE; 663 } 664 return SDL_TRUE; 665} 666 667static int 668D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, D3DFORMAT d3dfmt, int w, int h) 669{ 670 HRESULT result; 671 672 texture->dirty = SDL_FALSE; 673 texture->w = w; 674 texture->h = h; 675 texture->usage = usage; 676 texture->format = format; 677 texture->d3dfmt = d3dfmt; 678 679 result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage, 680 PixelFormatToD3DFMT(format), 681 D3DPOOL_DEFAULT, &texture->texture, NULL); 682 if (FAILED(result)) { 683 return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); 684 } 685 return 0; 686} 687 688 689static int 690D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *texture) 691{ 692 HRESULT result; 693 694 if (texture->staging == NULL) { 695 result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, 0, 696 texture->d3dfmt, D3DPOOL_SYSTEMMEM, &texture->staging, NULL); 697 if (FAILED(result)) { 698 return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result); 699 } 700 } 701 return 0; 702} 703 704static int 705D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler) 706{ 707 HRESULT result; 708 709 if (texture->dirty && texture->staging) { 710 if (!texture->texture) { 711 result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage, 712 PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL); 713 if (FAILED(result)) { 714 return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); 715 } 716 } 717 718 result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture); 719 if (FAILED(result)) { 720 return D3D_SetError("UpdateTexture()", result); 721 } 722 texture->dirty = SDL_FALSE; 723 } 724 result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture); 725 if (FAILED(result)) { 726 return D3D_SetError("SetTexture()", result); 727 } 728 return 0; 729} 730 731static int 732D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture) 733{ 734 if (texture->texture) { 735 IDirect3DTexture9_Release(texture->texture); 736 texture->texture = NULL; 737 } 738 if (texture->staging) { 739 IDirect3DTexture9_AddDirtyRect(texture->staging, NULL); 740 texture->dirty = SDL_TRUE; 741 } 742 return 0; 743} 744 745static int 746D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, int x, int y, int w, int h, const void *pixels, int pitch) 747{ 748 RECT d3drect; 749 D3DLOCKED_RECT locked; 750 const Uint8 *src; 751 Uint8 *dst; 752 int row, length; 753 HRESULT result; 754 755 if (D3D_CreateStagingTexture(device, texture) < 0) { 756 return -1; 757 } 758 759 d3drect.left = x; 760 d3drect.right = x + w; 761 d3drect.top = y; 762 d3drect.bottom = y + h; 763 764 result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0); 765 if (FAILED(result)) { 766 return D3D_SetError("LockRect()", result); 767 } 768 769 src = (const Uint8 *)pixels; 770 dst = (Uint8 *)locked.pBits; 771 length = w * SDL_BYTESPERPIXEL(texture->format); 772 if (length == pitch && length == locked.Pitch) { 773 SDL_memcpy(dst, src, length*h); 774 } else { 775 if (length > pitch) { 776 length = pitch; 777 } 778 if (length > locked.Pitch) { 779 length = locked.Pitch; 780 } 781 for (row = 0; row < h; ++row) { 782 SDL_memcpy(dst, src, length); 783 src += pitch; 784 dst += locked.Pitch; 785 } 786 } 787 result = IDirect3DTexture9_UnlockRect(texture->staging, 0); 788 if (FAILED(result)) { 789 return D3D_SetError("UnlockRect()", result); 790 } 791 texture->dirty = SDL_TRUE; 792 793 return 0; 794} 795 796static void 797D3D_DestroyTextureRep(D3D_TextureRep *texture) 798{ 799 if (texture->texture) { 800 IDirect3DTexture9_Release(texture->texture); 801 texture->texture = NULL; 802 } 803 if (texture->staging) { 804 IDirect3DTexture9_Release(texture->staging); 805 texture->staging = NULL; 806 } 807} 808 809static int 810D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) 811{ 812 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 813 D3D_TextureData *texturedata; 814 DWORD usage; 815 816 texturedata = (D3D_TextureData *) SDL_calloc(1, sizeof(*texturedata)); 817 if (!texturedata) { 818 return SDL_OutOfMemory(); 819 } 820 texturedata->scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? D3DTEXF_POINT : D3DTEXF_LINEAR; 821 822 texture->driverdata = texturedata; 823 824 if (texture->access == SDL_TEXTUREACCESS_TARGET) { 825 usage = D3DUSAGE_RENDERTARGET; 826 } else { 827 usage = 0; 828 } 829 830 if (D3D_CreateTextureRep(data->device, &texturedata->texture, usage, texture->format, PixelFormatToD3DFMT(texture->format), texture->w, texture->h) < 0) { 831 return -1; 832 } 833 834 if (texture->format == SDL_PIXELFORMAT_YV12 || 835 texture->format == SDL_PIXELFORMAT_IYUV) { 836 texturedata->yuv = SDL_TRUE; 837 838 if (D3D_CreateTextureRep(data->device, &texturedata->utexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), (texture->w + 1) / 2, (texture->h + 1) / 2) < 0) { 839 return -1; 840 } 841 842 if (D3D_CreateTextureRep(data->device, &texturedata->vtexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), (texture->w + 1) / 2, (texture->h + 1) / 2) < 0) { 843 return -1; 844 } 845 } 846 return 0; 847} 848 849static int 850D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) 851{ 852 D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; 853 D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; 854 855 if (!texturedata) { 856 return 0; 857 } 858 859 if (D3D_RecreateTextureRep(data->device, &texturedata->texture) < 0) { 860 return -1; 861 } 862 863 if (texturedata->yuv) { 864 if (D3D_RecreateTextureRep(data->device, &texturedata->utexture) < 0) { 865 return -1; 866 } 867 868 if (D3D_RecreateTextureRep(data->device, &texturedata->vtexture) < 0) { 869 return -1; 870 } 871 } 872 return 0; 873} 874 875static int 876D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 877 const SDL_Rect * rect, const void *pixels, int pitch) 878{ 879 D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; 880 D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata; 881 882 if (!texturedata) { 883 SDL_SetError("Texture is not currently available"); 884 return -1; 885 } 886 887 if (D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) { 888 return -1; 889 } 890 891 if (texturedata->yuv) { 892 /* Skip to the correct offset into the next texture */ 893 pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); 894 895 if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2) < 0) { 896 return -1; 897 } 898 899 /* Skip to the correct offset into the next texture */ 900 pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2)); 901 if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, rect->x / 2, (rect->y + 1) / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2) < 0) { 902 return -1; 903 } 904 } 905 return 0; 906} 907 908static int 909D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, 910 const SDL_Rect * rect, 911 const Uint8 *Yplane, int Ypitch, 912 const Uint8 *Uplane, int Upitch, 913 const Uint8 *Vplane, int Vpitch) 914{ 915 D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; 916 D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata; 917 918 if (!texturedata) { 919 SDL_SetError("Texture is not currently available"); 920 return -1; 921 } 922 923 if (D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) { 924 return -1; 925 } 926 if (D3D_UpdateTextureRep(data->device, &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch) < 0) { 927 return -1; 928 } 929 if (D3D_UpdateTextureRep(data->device, &texturedata->vtexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch) < 0) { 930 return -1; 931 } 932 return 0; 933} 934 935static int 936D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 937 const SDL_Rect * rect, void **pixels, int *pitch) 938{ 939 D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; 940 D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; 941 IDirect3DDevice9 *device = data->device; 942 943 if (!texturedata) { 944 SDL_SetError("Texture is not currently available"); 945 return -1; 946 } 947 948 texturedata->locked_rect = *rect; 949 950 if (texturedata->yuv) { 951 /* It's more efficient to upload directly... */ 952 if (!texturedata->pixels) { 953 texturedata->pitch = texture->w; 954 texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2); 955 if (!texturedata->pixels) { 956 return SDL_OutOfMemory(); 957 } 958 } 959 *pixels = 960 (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch + 961 rect->x * SDL_BYTESPERPIXEL(texture->format)); 962 *pitch = texturedata->pitch; 963 } else { 964 RECT d3drect; 965 D3DLOCKED_RECT locked; 966 HRESULT result; 967 968 if (D3D_CreateStagingTexture(device, &texturedata->texture) < 0) { 969 return -1; 970 } 971 972 d3drect.left = rect->x; 973 d3drect.right = rect->x + rect->w; 974 d3drect.top = rect->y; 975 d3drect.bottom = rect->y + rect->h; 976 977 result = IDirect3DTexture9_LockRect(texturedata->texture.staging, 0, &locked, &d3drect, 0); 978 if (FAILED(result)) { 979 return D3D_SetError("LockRect()", result); 980 } 981 *pixels = locked.pBits; 982 *pitch = locked.Pitch; 983 } 984 return 0; 985} 986 987static void 988D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) 989{ 990 /*D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;*/ 991 D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; 992 993 if (!texturedata) { 994 return; 995 } 996 997 if (texturedata->yuv) { 998 const SDL_Rect *rect = &texturedata->locked_rect; 999 void *pixels = 1000 (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch + 1001 rect->x * SDL_BYTESPERPIXEL(texture->format)); 1002 D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch); 1003 } else { 1004 IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0); 1005 texturedata->texture.dirty = SDL_TRUE; 1006 } 1007} 1008 1009static int 1010D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture) 1011{ 1012 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1013 D3D_TextureData *texturedata; 1014 D3D_TextureRep *texturerep; 1015 HRESULT result; 1016 IDirect3DDevice9 *device = data->device; 1017 1018 /* Release the previous render target if it wasn't the default one */ 1019 if (data->currentRenderTarget != NULL) { 1020 IDirect3DSurface9_Release(data->currentRenderTarget); 1021 data->currentRenderTarget = NULL; 1022 } 1023 1024 if (texture == NULL) { 1025 IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget); 1026 return 0; 1027 } 1028 1029 texturedata = (D3D_TextureData *)texture->driverdata; 1030 if (!texturedata) { 1031 SDL_SetError("Texture is not currently available"); 1032 return -1; 1033 } 1034 1035 /* Make sure the render target is updated if it was locked and written to */ 1036 texturerep = &texturedata->texture; 1037 if (texturerep->dirty && texturerep->staging) { 1038 if (!texturerep->texture) { 1039 result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h, 1, texturerep->usage, 1040 PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL); 1041 if (FAILED(result)) { 1042 return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); 1043 } 1044 } 1045 1046 result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texturerep->staging, (IDirect3DBaseTexture9 *)texturerep->texture); 1047 if (FAILED(result)) { 1048 return D3D_SetError("UpdateTexture()", result); 1049 } 1050 texturerep->dirty = SDL_FALSE; 1051 } 1052 1053 result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture.texture, 0, &data->currentRenderTarget); 1054 if(FAILED(result)) { 1055 return D3D_SetError("GetSurfaceLevel()", result); 1056 } 1057 result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget); 1058 if(FAILED(result)) { 1059 return D3D_SetError("SetRenderTarget()", result); 1060 } 1061 1062 return 0; 1063} 1064 1065static int 1066D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) 1067{ 1068 if (D3D_ActivateRenderer(renderer) < 0) { 1069 return -1; 1070 } 1071 1072 return D3D_SetRenderTargetInternal(renderer, texture); 1073} 1074 1075static int 1076D3D_UpdateViewport(SDL_Renderer * renderer) 1077{ 1078 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1079 D3DVIEWPORT9 viewport; 1080 D3DMATRIX matrix; 1081 1082 /* Set the viewport */ 1083 viewport.X = renderer->viewport.x; 1084 viewport.Y = renderer->viewport.y; 1085 viewport.Width = renderer->viewport.w; 1086 viewport.Height = renderer->viewport.h; 1087 viewport.MinZ = 0.0f; 1088 viewport.MaxZ = 1.0f; 1089 IDirect3DDevice9_SetViewport(data->device, &viewport); 1090 1091 /* Set an orthographic projection matrix */ 1092 if (renderer->viewport.w && renderer->viewport.h) { 1093 matrix.m[0][0] = 2.0f / renderer->viewport.w; 1094 matrix.m[0][1] = 0.0f; 1095 matrix.m[0][2] = 0.0f; 1096 matrix.m[0][3] = 0.0f; 1097 matrix.m[1][0] = 0.0f; 1098 matrix.m[1][1] = -2.0f / renderer->viewport.h; 1099 matrix.m[1][2] = 0.0f; 1100 matrix.m[1][3] = 0.0f; 1101 matrix.m[2][0] = 0.0f; 1102 matrix.m[2][1] = 0.0f; 1103 matrix.m[2][2] = 1.0f; 1104 matrix.m[2][3] = 0.0f; 1105 matrix.m[3][0] = -1.0f; 1106 matrix.m[3][1] = 1.0f; 1107 matrix.m[3][2] = 0.0f; 1108 matrix.m[3][3] = 1.0f; 1109 IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix); 1110 } 1111 1112 return 0; 1113} 1114 1115static int 1116D3D_UpdateClipRect(SDL_Renderer * renderer) 1117{ 1118 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1119 1120 if (renderer->clipping_enabled) { 1121 const SDL_Rect *rect = &renderer->clip_rect; 1122 RECT r; 1123 HRESULT result; 1124 1125 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE); 1126 r.left = renderer->viewport.x + rect->x; 1127 r.top = renderer->viewport.y + rect->y; 1128 r.right = renderer->viewport.x + rect->x + rect->w; 1129 r.bottom = renderer->viewport.y + rect->y + rect->h; 1130 1131 result = IDirect3DDevice9_SetScissorRect(data->device, &r); 1132 if (result != D3D_OK) { 1133 D3D_SetError("SetScissor()", result); 1134 return -1; 1135 } 1136 } else { 1137 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE); 1138 } 1139 return 0; 1140} 1141 1142static int 1143D3D_RenderClear(SDL_Renderer * renderer) 1144{ 1145 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1146 DWORD color; 1147 HRESULT result; 1148 int BackBufferWidth, BackBufferHeight; 1149 1150 if (D3D_ActivateRenderer(renderer) < 0) { 1151 return -1; 1152 } 1153 1154 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b); 1155 1156 if (renderer->target) { 1157 BackBufferWidth = renderer->target->w; 1158 BackBufferHeight = renderer->target->h; 1159 } else { 1160 BackBufferWidth = data->pparams.BackBufferWidth; 1161 BackBufferHeight = data->pparams.BackBufferHeight; 1162 } 1163 1164 if (renderer->clipping_enabled) { 1165 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE); 1166 } 1167 1168 /* Don't reset the viewport if we don't have to! */ 1169 if (!renderer->viewport.x && !renderer->viewport.y && 1170 renderer->viewport.w == BackBufferWidth && 1171 renderer->viewport.h == BackBufferHeight) { 1172 result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0); 1173 } else { 1174 D3DVIEWPORT9 viewport; 1175 1176 /* Clear is defined to clear the entire render target */ 1177 viewport.X = 0; 1178 viewport.Y = 0; 1179 viewport.Width = BackBufferWidth; 1180 viewport.Height = BackBufferHeight; 1181 viewport.MinZ = 0.0f; 1182 viewport.MaxZ = 1.0f; 1183 IDirect3DDevice9_SetViewport(data->device, &viewport); 1184 1185 result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0); 1186 1187 /* Reset the viewport */ 1188 viewport.X = renderer->viewport.x; 1189 viewport.Y = renderer->viewport.y; 1190 viewport.Width = renderer->viewport.w; 1191 viewport.Height = renderer->viewport.h; 1192 viewport.MinZ = 0.0f; 1193 viewport.MaxZ = 1.0f; 1194 IDirect3DDevice9_SetViewport(data->device, &viewport); 1195 } 1196 1197 if (renderer->clipping_enabled) { 1198 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE); 1199 } 1200 1201 if (FAILED(result)) { 1202 return D3D_SetError("Clear()", result); 1203 } 1204 return 0; 1205} 1206 1207static void 1208D3D_SetBlendMode(D3D_RenderData * data, SDL_BlendMode blendMode) 1209{ 1210 if (blendMode == SDL_BLENDMODE_NONE) { 1211 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, FALSE); 1212 } else { 1213 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, TRUE); 1214 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND, 1215 GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode))); 1216 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND, 1217 GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode))); 1218 if (data->enableSeparateAlphaBlend) { 1219 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA, 1220 GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode))); 1221 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA, 1222 GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode))); 1223 } 1224 } 1225} 1226 1227static int 1228D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points, 1229 int count) 1230{ 1231 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1232 DWORD color; 1233 Vertex *vertices; 1234 int i; 1235 HRESULT result; 1236 1237 if (D3D_ActivateRenderer(renderer) < 0) { 1238 return -1; 1239 } 1240 1241 D3D_SetBlendMode(data, renderer->blendMode); 1242 1243 result = 1244 IDirect3DDevice9_SetTexture(data->device, 0, 1245 (IDirect3DBaseTexture9 *) 0); 1246 if (FAILED(result)) { 1247 return D3D_SetError("SetTexture()", result); 1248 } 1249 1250 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b); 1251 1252 vertices = SDL_stack_alloc(Vertex, count); 1253 for (i = 0; i < count; ++i) { 1254 vertices[i].x = points[i].x; 1255 vertices[i].y = points[i].y; 1256 vertices[i].z = 0.0f; 1257 vertices[i].color = color; 1258 vertices[i].u = 0.0f; 1259 vertices[i].v = 0.0f; 1260 } 1261 result = 1262 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count, 1263 vertices, sizeof(*vertices)); 1264 SDL_stack_free(vertices); 1265 if (FAILED(result)) { 1266 return D3D_SetError("DrawPrimitiveUP()", result); 1267 } 1268 return 0; 1269} 1270 1271static int 1272D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points, 1273 int count) 1274{ 1275 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1276 DWORD color; 1277 Vertex *vertices; 1278 int i; 1279 HRESULT result; 1280 1281 if (D3D_ActivateRenderer(renderer) < 0) { 1282 return -1; 1283 } 1284 1285 D3D_SetBlendMode(data, renderer->blendMode); 1286 1287 result = 1288 IDirect3DDevice9_SetTexture(data->device, 0, 1289 (IDirect3DBaseTexture9 *) 0); 1290 if (FAILED(result)) { 1291 return D3D_SetError("SetTexture()", result); 1292 } 1293 1294 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b); 1295 1296 vertices = SDL_stack_alloc(Vertex, count); 1297 for (i = 0; i < count; ++i) { 1298 vertices[i].x = points[i].x; 1299 vertices[i].y = points[i].y; 1300 vertices[i].z = 0.0f; 1301 vertices[i].color = color; 1302 vertices[i].u = 0.0f; 1303 vertices[i].v = 0.0f; 1304 } 1305 result = 1306 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1, 1307 vertices, sizeof(*vertices)); 1308 1309 /* DirectX 9 has the same line rasterization semantics as GDI, 1310 so we need to close the endpoint of the line */ 1311 if (count == 2 || 1312 points[0].x != points[count-1].x || points[0].y != points[count-1].y) { 1313 vertices[0].x = points[count-1].x; 1314 vertices[0].y = points[count-1].y; 1315 result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices)); 1316 } 1317 1318 SDL_stack_free(vertices); 1319 if (FAILED(result)) { 1320 return D3D_SetError("DrawPrimitiveUP()", result); 1321 } 1322 return 0; 1323} 1324 1325static int 1326D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, 1327 int count) 1328{ 1329 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1330 DWORD color; 1331 int i; 1332 float minx, miny, maxx, maxy; 1333 Vertex vertices[4]; 1334 HRESULT result; 1335 1336 if (D3D_ActivateRenderer(renderer) < 0) { 1337 return -1; 1338 } 1339 1340 D3D_SetBlendMode(data, renderer->blendMode); 1341 1342 result = 1343 IDirect3DDevice9_SetTexture(data->device, 0, 1344 (IDirect3DBaseTexture9 *) 0); 1345 if (FAILED(result)) { 1346 return D3D_SetError("SetTexture()", result); 1347 } 1348 1349 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b); 1350 1351 for (i = 0; i < count; ++i) { 1352 const SDL_FRect *rect = &rects[i]; 1353 1354 minx = rect->x; 1355 miny = rect->y; 1356 maxx = rect->x + rect->w; 1357 maxy = rect->y + rect->h; 1358 1359 vertices[0].x = minx; 1360 vertices[0].y = miny; 1361 vertices[0].z = 0.0f; 1362 vertices[0].color = color; 1363 vertices[0].u = 0.0f; 1364 vertices[0].v = 0.0f; 1365 1366 vertices[1].x = maxx; 1367 vertices[1].y = miny; 1368 vertices[1].z = 0.0f; 1369 vertices[1].color = color; 1370 vertices[1].u = 0.0f; 1371 vertices[1].v = 0.0f; 1372 1373 vertices[2].x = maxx; 1374 vertices[2].y = maxy; 1375 vertices[2].z = 0.0f; 1376 vertices[2].color = color; 1377 vertices[2].u = 0.0f; 1378 vertices[2].v = 0.0f; 1379 1380 vertices[3].x = minx; 1381 vertices[3].y = maxy; 1382 vertices[3].z = 0.0f; 1383 vertices[3].color = color; 1384 vertices[3].u = 0.0f; 1385 vertices[3].v = 0.0f; 1386 1387 result = 1388 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 1389 2, vertices, sizeof(*vertices)); 1390 if (FAILED(result)) { 1391 return D3D_SetError("DrawPrimitiveUP()", result); 1392 } 1393 } 1394 return 0; 1395} 1396 1397static void 1398D3D_UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index) 1399{ 1400 if (texturedata->scaleMode != data->scaleMode[index]) { 1401 IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, 1402 texturedata->scaleMode); 1403 IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, 1404 texturedata->scaleMode); 1405 IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, 1406 D3DTADDRESS_CLAMP); 1407 IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, 1408 D3DTADDRESS_CLAMP); 1409 data->scaleMode[index] = texturedata->scaleMode; 1410 } 1411} 1412 1413static int 1414D3D_RenderSetupTextureState(SDL_Renderer * renderer, SDL_Texture * texture, LPDIRECT3DPIXELSHADER9 *shader) 1415{ 1416 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1417 D3D_TextureData *texturedata; 1418 1419 *shader = NULL; 1420 1421 texturedata = (D3D_TextureData *)texture->driverdata; 1422 if (!texturedata) { 1423 SDL_SetError("Texture is not currently available"); 1424 return -1; 1425 } 1426 1427 D3D_UpdateTextureScaleMode(data, texturedata, 0); 1428 1429 if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) { 1430 return -1; 1431 } 1432 1433 if (texturedata->yuv) { 1434 switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) { 1435 case SDL_YUV_CONVERSION_JPEG: 1436 *shader = data->shaders[SHADER_YUV_JPEG]; 1437 break; 1438 case SDL_YUV_CONVERSION_BT601: 1439 *shader = data->shaders[SHADER_YUV_BT601]; 1440 break; 1441 case SDL_YUV_CONVERSION_BT709: 1442 *shader = data->shaders[SHADER_YUV_BT709]; 1443 break; 1444 default: 1445 return SDL_SetError("Unsupported YUV conversion mode"); 1446 } 1447 1448 D3D_UpdateTextureScaleMode(data, texturedata, 1); 1449 D3D_UpdateTextureScaleMode(data, texturedata, 2); 1450 1451 if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) { 1452 return -1; 1453 } 1454 if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) { 1455 return -1; 1456 } 1457 } 1458 return 0; 1459} 1460 1461static int 1462D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 1463 const SDL_Rect * srcrect, const SDL_FRect * dstrect) 1464{ 1465 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1466 LPDIRECT3DPIXELSHADER9 shader; 1467 float minx, miny, maxx, maxy; 1468 float minu, maxu, minv, maxv; 1469 DWORD color; 1470 Vertex vertices[4]; 1471 HRESULT result; 1472 1473 if (D3D_ActivateRenderer(renderer) < 0) { 1474 return -1; 1475 } 1476 1477 minx = dstrect->x - 0.5f; 1478 miny = dstrect->y - 0.5f; 1479 maxx = dstrect->x + dstrect->w - 0.5f; 1480 maxy = dstrect->y + dstrect->h - 0.5f; 1481 1482 minu = (float) srcrect->x / texture->w; 1483 maxu = (float) (srcrect->x + srcrect->w) / texture->w; 1484 minv = (float) srcrect->y / texture->h; 1485 maxv = (float) (srcrect->y + srcrect->h) / texture->h; 1486 1487 color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b); 1488 1489 vertices[0].x = minx; 1490 vertices[0].y = miny; 1491 vertices[0].z = 0.0f; 1492 vertices[0].color = color; 1493 vertices[0].u = minu; 1494 vertices[0].v = minv; 1495 1496 vertices[1].x = maxx; 1497 vertices[1].y = miny; 1498 vertices[1].z = 0.0f; 1499 vertices[1].color = color; 1500 vertices[1].u = maxu; 1501 vertices[1].v = minv; 1502 1503 vertices[2].x = maxx; 1504 vertices[2].y = maxy; 1505 vertices[2].z = 0.0f; 1506 vertices[2].color = color; 1507 vertices[2].u = maxu; 1508 vertices[2].v = maxv; 1509 1510 vertices[3].x = minx; 1511 vertices[3].y = maxy; 1512 vertices[3].z = 0.0f; 1513 vertices[3].color = color; 1514 vertices[3].u = minu; 1515 vertices[3].v = maxv; 1516 1517 D3D_SetBlendMode(data, texture->blendMode); 1518 1519 if (D3D_RenderSetupTextureState(renderer, texture, &shader) < 0) { 1520 return -1; 1521 } 1522 1523 if (shader) { 1524 result = IDirect3DDevice9_SetPixelShader(data->device, shader); 1525 if (FAILED(result)) { 1526 return D3D_SetError("SetShader()", result); 1527 } 1528 } 1529 result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2, 1530 vertices, sizeof(*vertices)); 1531 if (FAILED(result)) { 1532 D3D_SetError("DrawPrimitiveUP()", result); 1533 } 1534 if (shader) { 1535 IDirect3DDevice9_SetPixelShader(data->device, NULL); 1536 } 1537 return FAILED(result) ? -1 : 0; 1538} 1539 1540 1541static int 1542D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, 1543 const SDL_Rect * srcrect, const SDL_FRect * dstrect, 1544 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) 1545{ 1546 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1547 LPDIRECT3DPIXELSHADER9 shader = NULL; 1548 float minx, miny, maxx, maxy; 1549 float minu, maxu, minv, maxv; 1550 float centerx, centery; 1551 DWORD color; 1552 Vertex vertices[4]; 1553 Float4X4 modelMatrix; 1554 HRESULT result; 1555 1556 if (D3D_ActivateRenderer(renderer) < 0) { 1557 return -1; 1558 } 1559 1560 centerx = center->x; 1561 centery = center->y; 1562 1563 minx = -centerx; 1564 maxx = dstrect->w - centerx; 1565 miny = -centery; 1566 maxy = dstrect->h - centery; 1567 1568 minu = (float) srcrect->x / texture->w; 1569 maxu = (float) (srcrect->x + srcrect->w) / texture->w; 1570 minv = (float) srcrect->y / texture->h; 1571 maxv = (float) (srcrect->y + srcrect->h) / texture->h; 1572 1573 if (flip & SDL_FLIP_HORIZONTAL) { 1574 float tmp = maxu; 1575 maxu = minu; 1576 minu = tmp; 1577 } 1578 if (flip & SDL_FLIP_VERTICAL) { 1579 float tmp = maxv; 1580 maxv = minv; 1581 minv = tmp; 1582 } 1583 1584 color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b); 1585 1586 vertices[0].x = minx; 1587 vertices[0].y = miny; 1588 vertices[0].z = 0.0f; 1589 vertices[0].color = color; 1590 vertices[0].u = minu; 1591 vertices[0].v = minv; 1592 1593 vertices[1].x = maxx; 1594 vertices[1].y = miny; 1595 vertices[1].z = 0.0f; 1596 vertices[1].color = color; 1597 vertices[1].u = maxu; 1598 vertices[1].v = minv; 1599 1600 vertices[2].x = maxx; 1601 vertices[2].y = maxy; 1602 vertices[2].z = 0.0f; 1603 vertices[2].color = color; 1604 vertices[2].u = maxu; 1605 vertices[2].v = maxv; 1606 1607 vertices[3].x = minx; 1608 vertices[3].y = maxy; 1609 vertices[3].z = 0.0f; 1610 vertices[3].color = color; 1611 vertices[3].u = minu; 1612 vertices[3].v = maxv; 1613 1614 D3D_SetBlendMode(data, texture->blendMode); 1615 1616 if (D3D_RenderSetupTextureState(renderer, texture, &shader) < 0) { 1617 return -1; 1618 } 1619 1620 /* Rotate and translate */ 1621 modelMatrix = MatrixMultiply( 1622 MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)), 1623 MatrixTranslation(dstrect->x + center->x - 0.5f, dstrect->y + center->y - 0.5f, 0)); 1624 IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix); 1625 1626 if (shader) { 1627 result = IDirect3DDevice9_SetPixelShader(data->device, shader); 1628 if (FAILED(result)) { 1629 D3D_SetError("SetShader()", result); 1630 goto done; 1631 } 1632 } 1633 result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2, 1634 vertices, sizeof(*vertices)); 1635 if (FAILED(result)) { 1636 D3D_SetError("DrawPrimitiveUP()", result); 1637 } 1638done: 1639 if (shader) { 1640 IDirect3DDevice9_SetPixelShader(data->device, NULL); 1641 } 1642 1643 modelMatrix = MatrixIdentity(); 1644 IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix); 1645 1646 return FAILED(result) ? -1 : 0; 1647} 1648 1649static int 1650D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, 1651 Uint32 format, void * pixels, int pitch) 1652{ 1653 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1654 D3DSURFACE_DESC desc; 1655 LPDIRECT3DSURFACE9 backBuffer; 1656 LPDIRECT3DSURFACE9 surface; 1657 RECT d3drect; 1658 D3DLOCKED_RECT locked; 1659 HRESULT result; 1660 1661 if (data->currentRenderTarget) { 1662 backBuffer = data->currentRenderTarget; 1663 } else { 1664 backBuffer = data->defaultRenderTarget; 1665 } 1666 1667 result = IDirect3DSurface9_GetDesc(backBuffer, &desc); 1668 if (FAILED(result)) { 1669 IDirect3DSurface9_Release(backBuffer); 1670 return D3D_SetError("GetDesc()", result); 1671 } 1672 1673 result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL); 1674 if (FAILED(result)) { 1675 IDirect3DSurface9_Release(backBuffer); 1676 return D3D_SetError("CreateOffscreenPlainSurface()", result); 1677 } 1678 1679 result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface); 1680 if (FAILED(result)) { 1681 IDirect3DSurface9_Release(surface); 1682 IDirect3DSurface9_Release(backBuffer); 1683 return D3D_SetError("GetRenderTargetData()", result); 1684 } 1685 1686 d3drect.left = rect->x; 1687 d3drect.right = rect->x + rect->w; 1688 d3drect.top = rect->y; 1689 d3drect.bottom = rect->y + rect->h; 1690 1691 result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY); 1692 if (FAILED(result)) { 1693 IDirect3DSurface9_Release(surface); 1694 IDirect3DSurface9_Release(backBuffer); 1695 return D3D_SetError("LockRect()", result); 1696 } 1697 1698 SDL_ConvertPixels(rect->w, rect->h, 1699 D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch, 1700 format, pixels, pitch); 1701 1702 IDirect3DSurface9_UnlockRect(surface); 1703 1704 IDirect3DSurface9_Release(surface); 1705 1706 return 0; 1707} 1708 1709static void 1710D3D_RenderPresent(SDL_Renderer * renderer) 1711{ 1712 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1713 HRESULT result; 1714 1715 if (!data->beginScene) { 1716 IDirect3DDevice9_EndScene(data->device); 1717 data->beginScene = SDL_TRUE; 1718 } 1719 1720 result = IDirect3DDevice9_TestCooperativeLevel(data->device); 1721 if (result == D3DERR_DEVICELOST) { 1722 /* We'll reset later */ 1723 return; 1724 } 1725 if (result == D3DERR_DEVICENOTRESET) { 1726 D3D_Reset(renderer); 1727 } 1728 result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL); 1729 if (FAILED(result)) { 1730 D3D_SetError("Present()", result); 1731 } 1732} 1733 1734static void 1735D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) 1736{ 1737 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata; 1738 1739 if (!data) { 1740 return; 1741 } 1742 D3D_DestroyTextureRep(&data->texture); 1743 D3D_DestroyTextureRep(&data->utexture); 1744 D3D_DestroyTextureRep(&data->vtexture); 1745 SDL_free(data->pixels); 1746 SDL_free(data); 1747 texture->driverdata = NULL; 1748} 1749 1750static void 1751D3D_DestroyRenderer(SDL_Renderer * renderer) 1752{ 1753 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1754 1755 if (data) { 1756 int i; 1757 1758 /* Release the render target */ 1759 if (data->defaultRenderTarget) { 1760 IDirect3DSurface9_Release(data->defaultRenderTarget); 1761 data->defaultRenderTarget = NULL; 1762 } 1763 if (data->currentRenderTarget != NULL) { 1764 IDirect3DSurface9_Release(data->currentRenderTarget); 1765 data->currentRenderTarget = NULL; 1766 } 1767 for (i = 0; i < SDL_arraysize(data->shaders); ++i) { 1768 if (data->shaders[i]) { 1769 IDirect3DPixelShader9_Release(data->shaders[i]); 1770 data->shaders[i] = NULL; 1771 } 1772 } 1773 if (data->device) { 1774 IDirect3DDevice9_Release(data->device); 1775 data->device = NULL; 1776 } 1777 if (data->d3d) { 1778 IDirect3D9_Release(data->d3d); 1779 SDL_UnloadObject(data->d3dDLL); 1780 } 1781 SDL_free(data); 1782 } 1783 SDL_free(renderer); 1784} 1785#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */ 1786 1787#ifdef __WIN32__ 1788/* This function needs to always exist on Windows, for the Dynamic API. */ 1789IDirect3DDevice9 * 1790SDL_RenderGetD3D9Device(SDL_Renderer * renderer) 1791{ 1792 IDirect3DDevice9 *device = NULL; 1793 1794#if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED 1795 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; 1796 1797 /* Make sure that this is a D3D renderer */ 1798 if (renderer->DestroyRenderer != D3D_DestroyRenderer) { 1799 SDL_SetError("Renderer is not a D3D renderer"); 1800 return NULL; 1801 } 1802 1803 device = data->device; 1804 if (device) { 1805 IDirect3DDevice9_AddRef(device); 1806 } 1807#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */ 1808 1809 return device; 1810} 1811#endif /* __WIN32__ */ 1812 1813/* vi: set ts=4 sw=4 expandtab: */ 1814[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.