This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_d3drender.c
870 lines (784 loc) · 27.4 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
116
float rhw;
float u, v;
117
118
} Vertex;
119
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
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);
}
198
199
static D3DFORMAT
PixelFormatToD3DFMT(Uint32 format)
200
{
201
switch (format) {
202
case SDL_PIXELFORMAT_INDEX8:
203
return D3DFMT_P8;
204
case SDL_PIXELFORMAT_RGB332:
205
return D3DFMT_R3G3B2;
206
case SDL_PIXELFORMAT_RGB444:
207
return D3DFMT_X4R4G4B4;
208
case SDL_PIXELFORMAT_RGB555:
209
return D3DFMT_X1R5G5B5;
210
case SDL_PIXELFORMAT_ARGB4444:
211
return D3DFMT_A4R4G4B4;
212
case SDL_PIXELFORMAT_ARGB1555:
213
return D3DFMT_A1R5G5B5;
214
case SDL_PIXELFORMAT_RGB565:
215
return D3DFMT_R5G6B5;
216
case SDL_PIXELFORMAT_RGB888:
217
return D3DFMT_X8R8G8B8;
218
case SDL_PIXELFORMAT_ARGB8888:
219
return D3DFMT_A8R8G8B8;
220
case SDL_PIXELFORMAT_ARGB2101010:
221
return D3DFMT_A2R10G10B10;
222
case SDL_PIXELFORMAT_UYVY:
223
return D3DFMT_UYVY;
224
case SDL_PIXELFORMAT_YUY2:
225
226
227
228
return D3DFMT_YUY2;
default:
return D3DFMT_UNKNOWN;
}
229
230
231
232
233
234
235
236
}
void
D3D_AddRenderDriver(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
if (data->d3d) {
237
SDL_AddRenderDriver(0, &D3D_RenderDriver);
238
239
240
241
}
}
SDL_Renderer *
242
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
243
244
245
246
247
{
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
SDL_Renderer *renderer;
248
D3D_RenderData *data;
249
250
HRESULT result;
D3DPRESENT_PARAMETERS pparams;
251
IDirect3DSwapChain9 *chain;
252
D3DCAPS9 caps;
253
254
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
255
256
257
258
259
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
260
data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
261
if (!data) {
262
D3D_DestroyRenderer(renderer);
263
264
265
266
SDL_OutOfMemory();
return NULL;
}
267
renderer->DisplayModeChanged = D3D_DisplayModeChanged;
268
269
270
renderer->CreateTexture = D3D_CreateTexture;
renderer->SetTexturePalette = D3D_SetTexturePalette;
renderer->GetTexturePalette = D3D_GetTexturePalette;
271
272
273
274
renderer->SetTextureColorMod = D3D_SetTextureColorMod;
renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod;
renderer->SetTextureBlendMode = D3D_SetTextureBlendMode;
renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
275
276
277
278
279
280
281
282
283
284
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;
285
286
287
renderer->window = window->id;
renderer->driverdata = data;
288
renderer->info.flags = SDL_RENDERER_ACCELERATED;
289
290
291
292
SDL_zero(pparams);
pparams.BackBufferWidth = window->w;
pparams.BackBufferHeight = window->h;
293
294
if (window->flags & SDL_WINDOW_FULLSCREEN) {
pparams.BackBufferFormat =
295
PixelFormatToD3DFMT(display->fullscreen_mode.format);
296
297
298
} else {
pparams.BackBufferFormat = D3DFMT_UNKNOWN;
}
299
if (flags & SDL_RENDERER_PRESENTFLIP2) {
300
301
pparams.BackBufferCount = 2;
pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
302
} else if (flags & SDL_RENDERER_PRESENTFLIP3) {
303
304
pparams.BackBufferCount = 3;
pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
305
} else if (flags & SDL_RENDERER_PRESENTCOPY) {
306
307
308
309
310
311
312
313
pparams.BackBufferCount = 1;
pparams.SwapEffect = D3DSWAPEFFECT_COPY;
} else {
pparams.BackBufferCount = 1;
pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
}
if (window->flags & SDL_WINDOW_FULLSCREEN) {
pparams.Windowed = FALSE;
314
pparams.FullScreen_RefreshRateInHz =
315
display->fullscreen_mode.refresh_rate;
316
317
} else {
pparams.Windowed = TRUE;
318
pparams.FullScreen_RefreshRateInHz = 0;
319
}
320
if (flags & SDL_RENDERER_PRESENTVSYNC) {
321
322
323
324
pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
} else {
pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}
325
326
327
328
329
330
331
result = IDirect3D9_CreateDevice(videodata->d3d, D3DADAPTER_DEFAULT, /* FIXME */
D3DDEVTYPE_HAL,
windowdata->hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&pparams, &data->device);
if (FAILED(result)) {
332
D3D_DestroyRenderer(renderer);
333
334
335
336
337
D3D_SetError("CreateDevice()", result);
return NULL;
}
data->beginScene = SDL_TRUE;
338
339
340
/* Get presentation parameters to fill info */
result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
if (FAILED(result)) {
341
D3D_DestroyRenderer(renderer);
342
343
344
345
346
347
D3D_SetError("GetSwapChain()", result);
return NULL;
}
result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
if (FAILED(result)) {
IDirect3DSwapChain9_Release(chain);
348
D3D_DestroyRenderer(renderer);
349
350
351
352
353
354
D3D_SetError("GetPresentParameters()", result);
return NULL;
}
IDirect3DSwapChain9_Release(chain);
switch (pparams.SwapEffect) {
case D3DSWAPEFFECT_COPY:
355
renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
356
357
358
359
break;
case D3DSWAPEFFECT_FLIP:
switch (pparams.BackBufferCount) {
case 2:
360
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
361
362
break;
case 3:
363
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
364
365
366
367
break;
}
break;
case D3DSWAPEFFECT_DISCARD:
368
renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD;
369
370
371
break;
}
if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
372
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
373
}
374
data->pparams = pparams;
375
376
377
378
IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
renderer->info.max_texture_width = caps.MaxTextureWidth;
renderer->info.max_texture_height = caps.MaxTextureHeight;
379
380
/* Set up parameters for rendering */
381
382
IDirect3DDevice9_SetVertexShader(data->device, NULL);
IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZRHW | D3DFVF_TEX1);
383
384
IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
D3DCULL_NONE);
385
IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
386
387
388
389
return renderer;
}
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
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);
IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZRHW | D3DFVF_TEX1);
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);
}
432
static int
433
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
434
{
435
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
436
437
SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
438
D3D_TextureData *data;
439
440
D3DPOOL pool;
HRESULT result;
441
442
data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
443
444
445
446
447
448
449
if (!data) {
SDL_OutOfMemory();
return -1;
}
texture->driverdata = data;
450
451
452
453
454
455
#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
456
if (texture->access == SDL_TEXTUREACCESS_LOCAL) {
457
pool = D3DPOOL_MANAGED;
458
} else {
459
pool = D3DPOOL_DEFAULT;
460
}
461
462
463
464
465
466
467
468
469
470
471
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;
472
473
474
}
static int
475
476
D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Color * colors, int firstcolor, int ncolors)
477
{
478
479
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
480
481
return 0;
482
483
484
}
static int
485
486
D3D_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
SDL_Color * colors, int firstcolor, int ncolors)
487
{
488
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
489
490
return 0;
491
492
}
493
494
495
496
497
498
499
500
501
502
503
504
505
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
static int
D3D_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
/* FIXME: implement vertex coloring */
return -1;
}
static int
D3D_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
/* FIXME: implement vertex coloring */
return -1;
}
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;
}
541
static int
542
543
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
544
{
545
546
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
547
548
549
550
551
552
553
IDirect3DTexture9 *temp;
RECT d3drect;
D3DLOCKED_RECT locked;
const Uint8 *src;
Uint8 *dst;
int row, length;
HRESULT result;
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
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;
}
576
577
578
579
580
581
582
583
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;
584
}
585
586
587
588
589
590
591
592
593
594
595
596
597
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;
598
599
600
}
static int
601
602
603
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty, void **pixels,
int *pitch)
604
{
605
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
606
607
608
RECT d3drect;
D3DLOCKED_RECT locked;
HRESULT result;
609
610
if (texture->access != SDL_TEXTUREACCESS_LOCAL) {
611
612
613
614
615
616
617
618
619
620
621
622
623
624
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);
625
return -1;
626
}
627
628
629
*pixels = locked.pBits;
*pitch = locked.Pitch;
return 0;
630
631
632
}
static void
633
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
634
{
635
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
636
637
IDirect3DTexture9_UnlockRect(data->texture, 0);
638
639
640
}
static void
641
642
D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
const SDL_Rect * rects)
643
{
644
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
645
646
647
648
649
650
651
652
653
654
655
656
657
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);
}
658
659
660
}
static int
661
662
D3D_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
const SDL_Rect * rect)
663
{
664
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
665
D3DRECT d3drect;
666
HRESULT result;
667
668
669
670
671
if (data->beginScene) {
IDirect3DDevice9_BeginScene(data->device);
data->beginScene = SDL_FALSE;
}
672
673
d3drect.x1 = rect->x;
674
d3drect.x2 = rect->x + rect->w;
675
d3drect.y1 = rect->y;
676
d3drect.y2 = rect->y + rect->h;
677
678
679
result =
IDirect3DDevice9_Clear(data->device, 1, &d3drect, D3DCLEAR_TARGET,
680
D3DCOLOR_ARGB(a, r, g, b), 1.0f, 0);
681
682
683
684
if (FAILED(result)) {
D3D_SetError("Clear()", result);
return -1;
}
685
686
687
688
return 0;
}
static int
689
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
690
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
691
{
692
693
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
694
float minx, miny, maxx, maxy;
695
float minu, maxu, minv, maxv;
696
697
Vertex vertices[4];
HRESULT result;
698
699
700
701
702
if (data->beginScene) {
IDirect3DDevice9_BeginScene(data->device);
data->beginScene = SDL_FALSE;
}
703
704
705
706
707
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;
708
709
710
711
712
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;
713
714
715
716
vertices[0].x = minx;
vertices[0].y = miny;
vertices[0].z = 0.0f;
717
718
719
720
vertices[0].rhw = 1.0f;
vertices[0].u = minu;
vertices[0].v = minv;
721
722
723
vertices[1].x = maxx;
vertices[1].y = miny;
vertices[1].z = 0.0f;
724
725
726
727
vertices[1].rhw = 1.0f;
vertices[1].u = maxu;
vertices[1].v = minv;
728
729
730
vertices[2].x = maxx;
vertices[2].y = maxy;
vertices[2].z = 0.0f;
731
732
733
734
vertices[2].rhw = 1.0f;
vertices[2].u = maxu;
vertices[2].v = maxv;
735
736
737
vertices[3].x = minx;
vertices[3].y = maxy;
vertices[3].z = 0.0f;
738
739
740
vertices[3].rhw = 1.0f;
vertices[3].u = minu;
vertices[3].v = maxv;
741
742
switch (texture->blendMode) {
743
case SDL_TEXTUREBLENDMODE_NONE:
744
745
746
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
FALSE);
break;
747
748
case SDL_TEXTUREBLENDMODE_MASK:
case SDL_TEXTUREBLENDMODE_BLEND:
749
750
751
752
753
754
755
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
TRUE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
D3DBLEND_SRCALPHA);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
D3DBLEND_INVSRCALPHA);
break;
756
case SDL_TEXTUREBLENDMODE_ADD:
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_ONE);
break;
764
case SDL_TEXTUREBLENDMODE_MOD:
765
766
767
768
769
770
771
772
773
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
TRUE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
D3DBLEND_ZERO);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
D3DBLEND_SRCCOLOR);
break;
}
774
switch (texture->scaleMode) {
775
776
case SDL_TEXTURESCALEMODE_NONE:
case SDL_TEXTURESCALEMODE_FAST:
777
778
779
780
781
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_POINT);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_POINT);
break;
782
case SDL_TEXTURESCALEMODE_SLOW:
783
784
785
786
787
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_LINEAR);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_LINEAR);
break;
788
case SDL_TEXTURESCALEMODE_BEST:
789
790
791
792
793
794
795
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_GAUSSIANQUAD);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_GAUSSIANQUAD);
break;
}
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
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;
}
811
812
813
814
return 0;
}
static void
815
D3D_RenderPresent(SDL_Renderer * renderer)
816
{
817
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
818
819
820
821
822
823
824
HRESULT result;
if (!data->beginScene) {
IDirect3DDevice9_EndScene(data->device);
data->beginScene = SDL_TRUE;
}
825
826
827
828
829
830
831
832
result = IDirect3DDevice9_TestCooperativeLevel(data->device);
if (result == D3DERR_DEVICELOST) {
/* We'll reset later */
return;
}
if (result == D3DERR_DEVICENOTRESET) {
D3D_Reset(renderer);
}
833
834
835
836
result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
if (FAILED(result)) {
D3D_SetError("Present()", result);
}
837
838
839
}
static void
840
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
841
{
842
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
843
844
845
846
if (!data) {
return;
}
847
848
849
if (data->texture) {
IDirect3DTexture9_Release(data->texture);
}
850
851
852
853
SDL_free(data);
texture->driverdata = NULL;
}
854
static void
855
D3D_DestroyRenderer(SDL_Renderer * renderer)
856
{
857
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
858
859
if (data) {
860
861
862
if (data->device) {
IDirect3DDevice9_Release(data->device);
}
863
864
865
866
867
868
869
870
SDL_free(data);
}
SDL_free(renderer);
}
#endif /* SDL_VIDEO_RENDER_D3D */
/* vi: set ts=4 sw=4 expandtab: */