This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_d3drender.c
878 lines (791 loc) · 27.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#if SDL_VIDEO_RENDER_D3D
#include "SDL_win32video.h"
/* Direct3D renderer implementation */
30
static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
31
static int D3D_DisplayModeChanged(SDL_Renderer * renderer);
32
33
34
35
36
37
38
39
static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int D3D_SetTexturePalette(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Color * colors, int firstcolor,
int ncolors);
static int D3D_GetTexturePalette(SDL_Renderer * renderer,
SDL_Texture * texture, SDL_Color * colors,
int firstcolor, int ncolors);
40
41
42
43
44
45
46
47
static int D3D_SetTextureColorMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int D3D_SetTextureAlphaMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int D3D_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int D3D_SetTextureScaleMode(SDL_Renderer * renderer,
SDL_Texture * texture);
48
49
50
51
52
53
54
55
56
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty,
void **pixels, int *pitch);
static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static void D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
int numrects, const SDL_Rect * rects);
57
58
static int D3D_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
Uint8 a, const SDL_Rect * rect);
59
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
60
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
61
62
63
64
65
66
67
68
static void D3D_RenderPresent(SDL_Renderer * renderer);
static void D3D_DestroyTexture(SDL_Renderer * renderer,
SDL_Texture * texture);
static void D3D_DestroyRenderer(SDL_Renderer * renderer);
SDL_RenderDriver D3D_RenderDriver = {
D3D_CreateRenderer,
69
70
{
"d3d",
71
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
72
SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
73
74
SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC |
SDL_RENDERER_ACCELERATED),
75
76
(SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
SDL_TEXTUREMODULATE_ALPHA),
77
78
79
80
81
(SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK |
SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD |
SDL_TEXTUREBLENDMODE_MOD),
(SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST),
82
12,
83
{
84
85
86
87
88
89
90
91
92
93
94
95
SDL_PIXELFORMAT_INDEX8,
SDL_PIXELFORMAT_RGB332,
SDL_PIXELFORMAT_RGB444,
SDL_PIXELFORMAT_RGB555,
SDL_PIXELFORMAT_ARGB4444,
SDL_PIXELFORMAT_ARGB1555,
SDL_PIXELFORMAT_RGB565,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ARGB2101010,
SDL_PIXELFORMAT_UYVY,
SDL_PIXELFORMAT_YUY2},
96
97
98
99
100
101
102
0,
0}
};
typedef struct
{
IDirect3DDevice9 *device;
103
D3DPRESENT_PARAMETERS pparams;
104
SDL_bool beginScene;
105
} D3D_RenderData;
106
107
108
typedef struct
{
109
IDirect3DTexture9 *texture;
110
} D3D_TextureData;
111
112
113
114
typedef struct
{
float x, y, z;
115
float rhw;
116
DWORD color;
117
float u, v;
118
119
} Vertex;
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
static void
D3D_SetError(const char *prefix, HRESULT result)
{
const char *error;
switch (result) {
case D3DERR_WRONGTEXTUREFORMAT:
error = "WRONGTEXTUREFORMAT";
break;
case D3DERR_UNSUPPORTEDCOLOROPERATION:
error = "UNSUPPORTEDCOLOROPERATION";
break;
case D3DERR_UNSUPPORTEDCOLORARG:
error = "UNSUPPORTEDCOLORARG";
break;
case D3DERR_UNSUPPORTEDALPHAOPERATION:
error = "UNSUPPORTEDALPHAOPERATION";
break;
case D3DERR_UNSUPPORTEDALPHAARG:
error = "UNSUPPORTEDALPHAARG";
break;
case D3DERR_TOOMANYOPERATIONS:
error = "TOOMANYOPERATIONS";
break;
case D3DERR_CONFLICTINGTEXTUREFILTER:
error = "CONFLICTINGTEXTUREFILTER";
break;
case D3DERR_UNSUPPORTEDFACTORVALUE:
error = "UNSUPPORTEDFACTORVALUE";
break;
case D3DERR_CONFLICTINGRENDERSTATE:
error = "CONFLICTINGRENDERSTATE";
break;
case D3DERR_UNSUPPORTEDTEXTUREFILTER:
error = "UNSUPPORTEDTEXTUREFILTER";
break;
case D3DERR_CONFLICTINGTEXTUREPALETTE:
error = "CONFLICTINGTEXTUREPALETTE";
break;
case D3DERR_DRIVERINTERNALERROR:
error = "DRIVERINTERNALERROR";
break;
case D3DERR_NOTFOUND:
error = "NOTFOUND";
break;
case D3DERR_MOREDATA:
error = "MOREDATA";
break;
case D3DERR_DEVICELOST:
error = "DEVICELOST";
break;
case D3DERR_DEVICENOTRESET:
error = "DEVICENOTRESET";
break;
case D3DERR_NOTAVAILABLE:
error = "NOTAVAILABLE";
break;
case D3DERR_OUTOFVIDEOMEMORY:
error = "OUTOFVIDEOMEMORY";
break;
case D3DERR_INVALIDDEVICE:
error = "INVALIDDEVICE";
break;
case D3DERR_INVALIDCALL:
error = "INVALIDCALL";
break;
case D3DERR_DRIVERINVALIDCALL:
error = "DRIVERINVALIDCALL";
break;
case D3DERR_WASSTILLDRAWING:
error = "WASSTILLDRAWING";
break;
default:
error = "UNKNOWN";
break;
}
SDL_SetError("%s: %s", prefix, error);
}
199
200
static D3DFORMAT
PixelFormatToD3DFMT(Uint32 format)
201
{
202
switch (format) {
203
case SDL_PIXELFORMAT_INDEX8:
204
return D3DFMT_P8;
205
case SDL_PIXELFORMAT_RGB332:
206
return D3DFMT_R3G3B2;
207
case SDL_PIXELFORMAT_RGB444:
208
return D3DFMT_X4R4G4B4;
209
case SDL_PIXELFORMAT_RGB555:
210
return D3DFMT_X1R5G5B5;
211
case SDL_PIXELFORMAT_ARGB4444:
212
return D3DFMT_A4R4G4B4;
213
case SDL_PIXELFORMAT_ARGB1555:
214
return D3DFMT_A1R5G5B5;
215
case SDL_PIXELFORMAT_RGB565:
216
return D3DFMT_R5G6B5;
217
case SDL_PIXELFORMAT_RGB888:
218
return D3DFMT_X8R8G8B8;
219
case SDL_PIXELFORMAT_ARGB8888:
220
return D3DFMT_A8R8G8B8;
221
case SDL_PIXELFORMAT_ARGB2101010:
222
return D3DFMT_A2R10G10B10;
223
case SDL_PIXELFORMAT_UYVY:
224
return D3DFMT_UYVY;
225
case SDL_PIXELFORMAT_YUY2:
226
227
228
229
return D3DFMT_YUY2;
default:
return D3DFMT_UNKNOWN;
}
230
231
232
233
234
235
236
237
}
void
D3D_AddRenderDriver(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
if (data->d3d) {
238
SDL_AddRenderDriver(0, &D3D_RenderDriver);
239
240
241
242
}
}
SDL_Renderer *
243
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
244
245
246
247
248
{
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
SDL_Renderer *renderer;
249
D3D_RenderData *data;
250
251
HRESULT result;
D3DPRESENT_PARAMETERS pparams;
252
IDirect3DSwapChain9 *chain;
253
D3DCAPS9 caps;
254
255
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
256
257
258
259
260
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
261
data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
262
if (!data) {
263
D3D_DestroyRenderer(renderer);
264
265
266
267
SDL_OutOfMemory();
return NULL;
}
268
renderer->DisplayModeChanged = D3D_DisplayModeChanged;
269
270
271
renderer->CreateTexture = D3D_CreateTexture;
renderer->SetTexturePalette = D3D_SetTexturePalette;
renderer->GetTexturePalette = D3D_GetTexturePalette;
272
273
274
275
renderer->SetTextureColorMod = D3D_SetTextureColorMod;
renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod;
renderer->SetTextureBlendMode = D3D_SetTextureBlendMode;
renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
276
277
278
279
280
281
282
283
284
285
renderer->UpdateTexture = D3D_UpdateTexture;
renderer->LockTexture = D3D_LockTexture;
renderer->UnlockTexture = D3D_UnlockTexture;
renderer->DirtyTexture = D3D_DirtyTexture;
renderer->RenderFill = D3D_RenderFill;
renderer->RenderCopy = D3D_RenderCopy;
renderer->RenderPresent = D3D_RenderPresent;
renderer->DestroyTexture = D3D_DestroyTexture;
renderer->DestroyRenderer = D3D_DestroyRenderer;
renderer->info = D3D_RenderDriver.info;
286
287
288
renderer->window = window->id;
renderer->driverdata = data;
289
renderer->info.flags = SDL_RENDERER_ACCELERATED;
290
291
292
293
SDL_zero(pparams);
pparams.BackBufferWidth = window->w;
pparams.BackBufferHeight = window->h;
294
295
if (window->flags & SDL_WINDOW_FULLSCREEN) {
pparams.BackBufferFormat =
296
PixelFormatToD3DFMT(display->fullscreen_mode.format);
297
298
299
} else {
pparams.BackBufferFormat = D3DFMT_UNKNOWN;
}
300
if (flags & SDL_RENDERER_PRESENTFLIP2) {
301
302
pparams.BackBufferCount = 2;
pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
303
} else if (flags & SDL_RENDERER_PRESENTFLIP3) {
304
305
pparams.BackBufferCount = 3;
pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
306
} else if (flags & SDL_RENDERER_PRESENTCOPY) {
307
308
309
310
311
312
313
314
pparams.BackBufferCount = 1;
pparams.SwapEffect = D3DSWAPEFFECT_COPY;
} else {
pparams.BackBufferCount = 1;
pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
}
if (window->flags & SDL_WINDOW_FULLSCREEN) {
pparams.Windowed = FALSE;
315
pparams.FullScreen_RefreshRateInHz =
316
display->fullscreen_mode.refresh_rate;
317
318
} else {
pparams.Windowed = TRUE;
319
pparams.FullScreen_RefreshRateInHz = 0;
320
}
321
if (flags & SDL_RENDERER_PRESENTVSYNC) {
322
323
324
325
pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
} else {
pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}
326
327
328
329
330
331
332
result = IDirect3D9_CreateDevice(videodata->d3d, D3DADAPTER_DEFAULT, /* FIXME */
D3DDEVTYPE_HAL,
windowdata->hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&pparams, &data->device);
if (FAILED(result)) {
333
D3D_DestroyRenderer(renderer);
334
335
336
337
338
D3D_SetError("CreateDevice()", result);
return NULL;
}
data->beginScene = SDL_TRUE;
339
340
341
/* Get presentation parameters to fill info */
result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
if (FAILED(result)) {
342
D3D_DestroyRenderer(renderer);
343
344
345
346
347
348
D3D_SetError("GetSwapChain()", result);
return NULL;
}
result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
if (FAILED(result)) {
IDirect3DSwapChain9_Release(chain);
349
D3D_DestroyRenderer(renderer);
350
351
352
353
354
355
D3D_SetError("GetPresentParameters()", result);
return NULL;
}
IDirect3DSwapChain9_Release(chain);
switch (pparams.SwapEffect) {
case D3DSWAPEFFECT_COPY:
356
renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
357
358
359
360
break;
case D3DSWAPEFFECT_FLIP:
switch (pparams.BackBufferCount) {
case 2:
361
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
362
363
break;
case 3:
364
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
365
366
367
368
break;
}
break;
case D3DSWAPEFFECT_DISCARD:
369
renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD;
370
371
372
break;
}
if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
373
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
374
}
375
data->pparams = pparams;
376
377
378
379
IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
renderer->info.max_texture_width = caps.MaxTextureWidth;
renderer->info.max_texture_height = caps.MaxTextureHeight;
380
381
/* Set up parameters for rendering */
382
IDirect3DDevice9_SetVertexShader(data->device, NULL);
383
384
IDirect3DDevice9_SetFVF(data->device,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
385
386
IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
D3DCULL_NONE);
387
IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
388
389
390
391
return renderer;
}
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
static int
D3D_Reset(SDL_Renderer * renderer)
{
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
HRESULT result;
result = IDirect3DDevice9_Reset(data->device, &data->pparams);
if (FAILED(result)) {
if (result == D3DERR_DEVICELOST) {
/* Don't worry about it, we'll reset later... */
return 0;
} else {
D3D_SetError("Reset()", result);
return -1;
}
}
IDirect3DDevice9_SetVertexShader(data->device, NULL);
409
410
IDirect3DDevice9_SetFVF(data->device,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
D3DCULL_NONE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
return 0;
}
static int
D3D_DisplayModeChanged(SDL_Renderer * renderer)
{
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
data->pparams.BackBufferWidth = window->w;
data->pparams.BackBufferHeight = window->h;
if (window->flags & SDL_WINDOW_FULLSCREEN) {
data->pparams.BackBufferFormat =
PixelFormatToD3DFMT(display->fullscreen_mode.format);
} else {
data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
}
return D3D_Reset(renderer);
}
435
static int
436
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
437
{
438
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
439
440
SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
441
D3D_TextureData *data;
442
443
D3DPOOL pool;
HRESULT result;
444
445
data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
446
447
448
449
450
451
452
if (!data) {
SDL_OutOfMemory();
return -1;
}
texture->driverdata = data;
453
454
455
456
457
458
#if 1
/* FIXME: Do we want non-managed textures?
They need to be freed on device reset and then reloaded by the app...
*/
texture->access = SDL_TEXTUREACCESS_LOCAL;
#endif
459
if (texture->access == SDL_TEXTUREACCESS_LOCAL) {
460
pool = D3DPOOL_MANAGED;
461
} else {
462
pool = D3DPOOL_DEFAULT;
463
}
464
465
466
467
468
469
470
471
472
473
474
result =
IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
texture->h, 1, 0,
PixelFormatToD3DFMT(texture->format),
pool, &data->texture, NULL);
if (FAILED(result)) {
D3D_SetError("CreateTexture()", result);
return -1;
}
return 0;
475
476
477
}
static int
478
479
D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Color * colors, int firstcolor, int ncolors)
480
{
481
482
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
483
484
return 0;
485
486
487
}
static int
488
489
D3D_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
SDL_Color * colors, int firstcolor, int ncolors)
490
{
491
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
492
493
return 0;
494
495
}
496
497
498
static int
D3D_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
499
return 0;
500
501
502
503
504
}
static int
D3D_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
505
return 0;
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
}
static int
D3D_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
switch (texture->blendMode) {
case SDL_TEXTUREBLENDMODE_NONE:
case SDL_TEXTUREBLENDMODE_MASK:
case SDL_TEXTUREBLENDMODE_BLEND:
case SDL_TEXTUREBLENDMODE_ADD:
case SDL_TEXTUREBLENDMODE_MOD:
return 0;
default:
SDL_Unsupported();
texture->blendMode = SDL_TEXTUREBLENDMODE_NONE;
return -1;
}
}
static int
D3D_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
switch (texture->scaleMode) {
case SDL_TEXTURESCALEMODE_NONE:
case SDL_TEXTURESCALEMODE_FAST:
case SDL_TEXTURESCALEMODE_SLOW:
case SDL_TEXTURESCALEMODE_BEST:
return 0;
default:
SDL_Unsupported();
texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
return -1;
}
return 0;
}
542
static int
543
544
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
545
{
546
547
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
548
549
550
551
552
553
554
IDirect3DTexture9 *temp;
RECT d3drect;
D3DLOCKED_RECT locked;
const Uint8 *src;
Uint8 *dst;
int row, length;
HRESULT result;
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
result =
IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
texture->h, 1, 0,
PixelFormatToD3DFMT(texture->format),
D3DPOOL_SYSTEMMEM, &temp, NULL);
if (FAILED(result)) {
D3D_SetError("CreateTexture()", result);
return -1;
}
d3drect.left = rect->x;
d3drect.right = rect->x + rect->w;
d3drect.top = rect->y;
d3drect.bottom = rect->y + rect->h;
result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
if (FAILED(result)) {
IDirect3DTexture9_Release(temp);
D3D_SetError("LockRect()", result);
return -1;
}
577
578
579
580
581
582
583
584
src = pixels;
dst = locked.pBits;
length = rect->w * SDL_BYTESPERPIXEL(texture->format);
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, src, length);
src += pitch;
dst += locked.Pitch;
585
}
586
587
588
589
590
591
592
593
594
595
596
597
598
IDirect3DTexture9_UnlockRect(temp, 0);
result =
IDirect3DDevice9_UpdateTexture(renderdata->device,
(IDirect3DBaseTexture9 *) temp,
(IDirect3DBaseTexture9 *) data->
texture);
IDirect3DTexture9_Release(temp);
if (FAILED(result)) {
D3D_SetError("UpdateTexture()", result);
return -1;
}
return 0;
599
600
601
}
static int
602
603
604
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty, void **pixels,
int *pitch)
605
{
606
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
607
608
609
RECT d3drect;
D3DLOCKED_RECT locked;
HRESULT result;
610
611
if (texture->access != SDL_TEXTUREACCESS_LOCAL) {
612
613
614
615
616
617
618
619
620
621
622
623
624
625
SDL_SetError("Can't lock remote video memory");
return -1;
}
d3drect.left = rect->x;
d3drect.right = rect->x + rect->w;
d3drect.top = rect->y;
d3drect.bottom = rect->y + rect->h;
result =
IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
markDirty ? 0 : D3DLOCK_NO_DIRTY_UPDATE);
if (FAILED(result)) {
D3D_SetError("LockRect()", result);
626
return -1;
627
}
628
629
630
*pixels = locked.pBits;
*pitch = locked.Pitch;
return 0;
631
632
633
}
static void
634
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
635
{
636
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
637
638
IDirect3DTexture9_UnlockRect(data->texture, 0);
639
640
641
}
static void
642
643
D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
const SDL_Rect * rects)
644
{
645
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
646
647
648
649
650
651
652
653
654
655
656
657
658
RECT d3drect;
int i;
for (i = 0; i < numrects; ++i) {
const SDL_Rect *rect = &rects[i];
d3drect.left = rect->x;
d3drect.right = rect->x + rect->w;
d3drect.top = rect->y;
d3drect.bottom = rect->y + rect->h;
IDirect3DTexture9_AddDirtyRect(data->texture, &d3drect);
}
659
660
661
}
static int
662
663
D3D_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
const SDL_Rect * rect)
664
{
665
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
666
D3DRECT d3drect;
667
HRESULT result;
668
669
670
671
672
if (data->beginScene) {
IDirect3DDevice9_BeginScene(data->device);
data->beginScene = SDL_FALSE;
}
673
674
d3drect.x1 = rect->x;
675
d3drect.x2 = rect->x + rect->w;
676
d3drect.y1 = rect->y;
677
d3drect.y2 = rect->y + rect->h;
678
679
680
result =
IDirect3DDevice9_Clear(data->device, 1, &d3drect, D3DCLEAR_TARGET,
681
D3DCOLOR_ARGB(a, r, g, b), 1.0f, 0);
682
683
684
685
if (FAILED(result)) {
D3D_SetError("Clear()", result);
return -1;
}
686
687
688
689
return 0;
}
static int
690
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
691
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
692
{
693
694
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
695
float minx, miny, maxx, maxy;
696
float minu, maxu, minv, maxv;
697
DWORD color;
698
699
Vertex vertices[4];
HRESULT result;
700
701
702
703
704
if (data->beginScene) {
IDirect3DDevice9_BeginScene(data->device);
data->beginScene = SDL_FALSE;
}
705
706
707
708
709
minx = (float) dstrect->x - 0.5f;
miny = (float) dstrect->y - 0.5f;
maxx = (float) dstrect->x + dstrect->w - 0.5f;
maxy = (float) dstrect->y + dstrect->h - 0.5f;
710
711
712
713
714
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;
715
716
717
color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
718
719
720
vertices[0].x = minx;
vertices[0].y = miny;
vertices[0].z = 0.0f;
721
vertices[0].rhw = 1.0f;
722
vertices[0].color = color;
723
724
725
vertices[0].u = minu;
vertices[0].v = minv;
726
727
728
vertices[1].x = maxx;
vertices[1].y = miny;
vertices[1].z = 0.0f;
729
vertices[1].rhw = 1.0f;
730
vertices[1].color = color;
731
732
733
vertices[1].u = maxu;
vertices[1].v = minv;
734
735
736
vertices[2].x = maxx;
vertices[2].y = maxy;
vertices[2].z = 0.0f;
737
vertices[2].rhw = 1.0f;
738
vertices[2].color = color;
739
740
741
vertices[2].u = maxu;
vertices[2].v = maxv;
742
743
744
vertices[3].x = minx;
vertices[3].y = maxy;
vertices[3].z = 0.0f;
745
vertices[3].rhw = 1.0f;
746
vertices[3].color = color;
747
748
vertices[3].u = minu;
vertices[3].v = maxv;
749
750
switch (texture->blendMode) {
751
case SDL_TEXTUREBLENDMODE_NONE:
752
753
754
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
FALSE);
break;
755
756
case SDL_TEXTUREBLENDMODE_MASK:
case SDL_TEXTUREBLENDMODE_BLEND:
757
758
759
760
761
762
763
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
TRUE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
D3DBLEND_SRCALPHA);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
D3DBLEND_INVSRCALPHA);
break;
764
case SDL_TEXTUREBLENDMODE_ADD:
765
766
767
768
769
770
771
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
TRUE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
D3DBLEND_SRCALPHA);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
D3DBLEND_ONE);
break;
772
case SDL_TEXTUREBLENDMODE_MOD:
773
774
775
776
777
778
779
780
781
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
TRUE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
D3DBLEND_ZERO);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
D3DBLEND_SRCCOLOR);
break;
}
782
switch (texture->scaleMode) {
783
784
case SDL_TEXTURESCALEMODE_NONE:
case SDL_TEXTURESCALEMODE_FAST:
785
786
787
788
789
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_POINT);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_POINT);
break;
790
case SDL_TEXTURESCALEMODE_SLOW:
791
792
793
794
795
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_LINEAR);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_LINEAR);
break;
796
case SDL_TEXTURESCALEMODE_BEST:
797
798
799
800
801
802
803
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_GAUSSIANQUAD);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_GAUSSIANQUAD);
break;
}
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
result =
IDirect3DDevice9_SetTexture(data->device, 0,
(IDirect3DBaseTexture9 *) texturedata->
texture);
if (FAILED(result)) {
D3D_SetError("SetTexture()", result);
return -1;
}
result =
IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
vertices, sizeof(*vertices));
if (FAILED(result)) {
D3D_SetError("DrawPrimitiveUP()", result);
return -1;
}
819
820
821
822
return 0;
}
static void
823
D3D_RenderPresent(SDL_Renderer * renderer)
824
{
825
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
826
827
828
829
830
831
832
HRESULT result;
if (!data->beginScene) {
IDirect3DDevice9_EndScene(data->device);
data->beginScene = SDL_TRUE;
}
833
834
835
836
837
838
839
840
result = IDirect3DDevice9_TestCooperativeLevel(data->device);
if (result == D3DERR_DEVICELOST) {
/* We'll reset later */
return;
}
if (result == D3DERR_DEVICENOTRESET) {
D3D_Reset(renderer);
}
841
842
843
844
result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
if (FAILED(result)) {
D3D_SetError("Present()", result);
}
845
846
847
}
static void
848
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
849
{
850
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
851
852
853
854
if (!data) {
return;
}
855
856
857
if (data->texture) {
IDirect3DTexture9_Release(data->texture);
}
858
859
860
861
SDL_free(data);
texture->driverdata = NULL;
}
862
static void
863
D3D_DestroyRenderer(SDL_Renderer * renderer)
864
{
865
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
866
867
if (data) {
868
869
870
if (data->device) {
IDirect3DDevice9_Release(data->device);
}
871
872
873
874
875
876
877
878
SDL_free(data);
}
SDL_free(renderer);
}
#endif /* SDL_VIDEO_RENDER_D3D */
/* vi: set ts=4 sw=4 expandtab: */