This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_d3drender.c
926 lines (836 loc) · 29.6 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2009 Sam Lantinga
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
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
#if 1 /* This takes more memory but you won't lose your texture data */
31
32
33
34
35
36
37
#define D3DPOOL_SDL D3DPOOL_MANAGED
#define SDL_MEMORY_POOL_MANAGED
#else
#define D3DPOOL_SDL D3DPOOL_DEFAULT
#define SDL_MEMORY_POOL_DEFAULT
#endif
38
static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
39
static int D3D_DisplayModeChanged(SDL_Renderer * renderer);
40
41
42
43
44
45
46
47
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);
48
49
50
51
52
53
54
55
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);
56
57
58
59
60
61
62
63
64
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);
65
66
static int D3D_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
Uint8 a, const SDL_Rect * rect);
67
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
68
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
69
70
71
72
73
74
75
76
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,
77
78
{
"d3d",
79
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
80
SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
81
82
SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC |
SDL_RENDERER_ACCELERATED),
83
84
(SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
SDL_TEXTUREMODULATE_ALPHA),
85
86
(SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
87
88
(SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST),
89
12,
90
{
91
92
93
94
95
96
97
98
99
100
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,
101
SDL_PIXELFORMAT_YUY2,
102
SDL_PIXELFORMAT_UYVY},
103
104
105
106
107
108
109
0,
0}
};
typedef struct
{
IDirect3DDevice9 *device;
110
D3DPRESENT_PARAMETERS pparams;
111
SDL_bool beginScene;
112
} D3D_RenderData;
113
114
115
typedef struct
{
116
IDirect3DTexture9 *texture;
117
} D3D_TextureData;
118
119
120
121
typedef struct
{
float x, y, z;
122
float rhw;
123
DWORD color;
124
float u, v;
125
126
} Vertex;
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
199
200
201
202
203
204
205
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);
}
206
207
static D3DFORMAT
PixelFormatToD3DFMT(Uint32 format)
208
{
209
switch (format) {
210
case SDL_PIXELFORMAT_INDEX8:
211
return D3DFMT_P8;
212
case SDL_PIXELFORMAT_RGB332:
213
return D3DFMT_R3G3B2;
214
case SDL_PIXELFORMAT_RGB444:
215
return D3DFMT_X4R4G4B4;
216
case SDL_PIXELFORMAT_RGB555:
217
return D3DFMT_X1R5G5B5;
218
case SDL_PIXELFORMAT_ARGB4444:
219
return D3DFMT_A4R4G4B4;
220
case SDL_PIXELFORMAT_ARGB1555:
221
return D3DFMT_A1R5G5B5;
222
case SDL_PIXELFORMAT_RGB565:
223
return D3DFMT_R5G6B5;
224
case SDL_PIXELFORMAT_RGB888:
225
return D3DFMT_X8R8G8B8;
226
case SDL_PIXELFORMAT_ARGB8888:
227
return D3DFMT_A8R8G8B8;
228
case SDL_PIXELFORMAT_ARGB2101010:
229
return D3DFMT_A2R10G10B10;
230
case SDL_PIXELFORMAT_UYVY:
231
return D3DFMT_UYVY;
232
case SDL_PIXELFORMAT_YUY2:
233
234
235
236
return D3DFMT_YUY2;
default:
return D3DFMT_UNKNOWN;
}
237
238
239
240
241
242
243
244
}
void
D3D_AddRenderDriver(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
if (data->d3d) {
245
SDL_AddRenderDriver(0, &D3D_RenderDriver);
246
247
248
249
}
}
SDL_Renderer *
250
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
251
252
253
254
255
{
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
SDL_Renderer *renderer;
256
D3D_RenderData *data;
257
258
HRESULT result;
D3DPRESENT_PARAMETERS pparams;
259
IDirect3DSwapChain9 *chain;
260
D3DCAPS9 caps;
261
262
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
263
264
265
266
267
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
268
data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
269
if (!data) {
270
D3D_DestroyRenderer(renderer);
271
272
273
274
SDL_OutOfMemory();
return NULL;
}
275
renderer->DisplayModeChanged = D3D_DisplayModeChanged;
276
277
278
renderer->CreateTexture = D3D_CreateTexture;
renderer->SetTexturePalette = D3D_SetTexturePalette;
renderer->GetTexturePalette = D3D_GetTexturePalette;
279
280
281
282
renderer->SetTextureColorMod = D3D_SetTextureColorMod;
renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod;
renderer->SetTextureBlendMode = D3D_SetTextureBlendMode;
renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
283
284
285
286
287
288
289
290
291
292
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;
293
294
295
renderer->window = window->id;
renderer->driverdata = data;
296
renderer->info.flags = SDL_RENDERER_ACCELERATED;
297
298
299
300
SDL_zero(pparams);
pparams.BackBufferWidth = window->w;
pparams.BackBufferHeight = window->h;
301
302
if (window->flags & SDL_WINDOW_FULLSCREEN) {
pparams.BackBufferFormat =
303
PixelFormatToD3DFMT(display->fullscreen_mode.format);
304
305
306
} else {
pparams.BackBufferFormat = D3DFMT_UNKNOWN;
}
307
if (flags & SDL_RENDERER_PRESENTFLIP2) {
308
309
pparams.BackBufferCount = 2;
pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
310
} else if (flags & SDL_RENDERER_PRESENTFLIP3) {
311
312
pparams.BackBufferCount = 3;
pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
313
} else if (flags & SDL_RENDERER_PRESENTCOPY) {
314
315
316
317
318
319
320
321
pparams.BackBufferCount = 1;
pparams.SwapEffect = D3DSWAPEFFECT_COPY;
} else {
pparams.BackBufferCount = 1;
pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
}
if (window->flags & SDL_WINDOW_FULLSCREEN) {
pparams.Windowed = FALSE;
322
pparams.FullScreen_RefreshRateInHz =
323
display->fullscreen_mode.refresh_rate;
324
325
} else {
pparams.Windowed = TRUE;
326
pparams.FullScreen_RefreshRateInHz = 0;
327
}
328
if (flags & SDL_RENDERER_PRESENTVSYNC) {
329
330
331
332
pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
} else {
pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}
333
334
335
336
337
338
339
result = IDirect3D9_CreateDevice(videodata->d3d, D3DADAPTER_DEFAULT, /* FIXME */
D3DDEVTYPE_HAL,
windowdata->hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&pparams, &data->device);
if (FAILED(result)) {
340
D3D_DestroyRenderer(renderer);
341
342
343
344
345
D3D_SetError("CreateDevice()", result);
return NULL;
}
data->beginScene = SDL_TRUE;
346
347
348
/* Get presentation parameters to fill info */
result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
if (FAILED(result)) {
349
D3D_DestroyRenderer(renderer);
350
351
352
353
354
355
D3D_SetError("GetSwapChain()", result);
return NULL;
}
result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
if (FAILED(result)) {
IDirect3DSwapChain9_Release(chain);
356
D3D_DestroyRenderer(renderer);
357
358
359
360
361
362
D3D_SetError("GetPresentParameters()", result);
return NULL;
}
IDirect3DSwapChain9_Release(chain);
switch (pparams.SwapEffect) {
case D3DSWAPEFFECT_COPY:
363
renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
364
365
366
367
break;
case D3DSWAPEFFECT_FLIP:
switch (pparams.BackBufferCount) {
case 2:
368
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
369
370
break;
case 3:
371
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
372
373
374
375
break;
}
break;
case D3DSWAPEFFECT_DISCARD:
376
renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD;
377
378
379
break;
}
if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
380
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
381
}
382
data->pparams = pparams;
383
384
385
386
IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
renderer->info.max_texture_width = caps.MaxTextureWidth;
renderer->info.max_texture_height = caps.MaxTextureHeight;
387
388
/* Set up parameters for rendering */
389
IDirect3DDevice9_SetVertexShader(data->device, NULL);
390
391
IDirect3DDevice9_SetFVF(data->device,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
392
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
393
394
IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
D3DCULL_NONE);
395
IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
396
397
398
399
400
401
402
403
404
405
406
407
408
409
/* Enable color modulation by diffuse color */
IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
D3DTOP_MODULATE);
IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
D3DTA_DIFFUSE);
/* Enable alpha modulation by diffuse alpha */
IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
D3DTOP_MODULATE);
IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
D3DTA_DIFFUSE);
410
411
412
413
414
/* Disable second texture stage, since we're done */
IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
D3DTOP_DISABLE);
IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
D3DTOP_DISABLE);
415
416
417
418
return renderer;
}
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
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);
436
437
IDirect3DDevice9_SetFVF(data->device,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
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);
}
462
static int
463
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
464
{
465
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
466
467
SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
468
D3D_TextureData *data;
469
HRESULT result;
470
471
data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
472
473
474
475
476
477
478
if (!data) {
SDL_OutOfMemory();
return -1;
}
texture->driverdata = data;
479
480
481
482
result =
IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
texture->h, 1, 0,
PixelFormatToD3DFMT(texture->format),
483
D3DPOOL_SDL, &data->texture, NULL);
484
485
486
487
488
489
if (FAILED(result)) {
D3D_SetError("CreateTexture()", result);
return -1;
}
return 0;
490
491
492
}
static int
493
494
D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Color * colors, int firstcolor, int ncolors)
495
{
496
497
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
498
499
return 0;
500
501
502
}
static int
503
504
D3D_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
SDL_Color * colors, int firstcolor, int ncolors)
505
{
506
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
507
508
return 0;
509
510
}
511
512
513
static int
D3D_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
514
return 0;
515
516
517
518
519
}
static int
D3D_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
520
return 0;
521
522
523
524
525
526
}
static int
D3D_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
switch (texture->blendMode) {
527
528
529
530
531
case SDL_BLENDMODE_NONE:
case SDL_BLENDMODE_MASK:
case SDL_BLENDMODE_BLEND:
case SDL_BLENDMODE_ADD:
case SDL_BLENDMODE_MOD:
532
533
534
return 0;
default:
SDL_Unsupported();
535
texture->blendMode = SDL_BLENDMODE_NONE;
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
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;
}
557
#ifdef SDL_MEMORY_POOL_DEFAULT
558
static int
559
560
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
561
{
562
563
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
564
565
566
567
568
569
570
IDirect3DTexture9 *temp;
RECT d3drect;
D3DLOCKED_RECT locked;
const Uint8 *src;
Uint8 *dst;
int row, length;
HRESULT result;
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
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;
}
593
594
595
596
597
598
599
600
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;
601
}
602
603
604
605
606
IDirect3DTexture9_UnlockRect(temp, 0);
result =
IDirect3DDevice9_UpdateTexture(renderdata->device,
(IDirect3DBaseTexture9 *) temp,
607
608
(IDirect3DBaseTexture9 *)
data->texture);
609
610
611
612
613
614
IDirect3DTexture9_Release(temp);
if (FAILED(result)) {
D3D_SetError("UpdateTexture()", result);
return -1;
}
return 0;
615
}
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
#else
static int
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
{
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
RECT d3drect;
D3DLOCKED_RECT locked;
const Uint8 *src;
Uint8 *dst;
int row, length;
HRESULT result;
d3drect.left = rect->x;
d3drect.right = rect->x + rect->w;
d3drect.top = rect->y;
d3drect.bottom = rect->y + rect->h;
635
636
result =
IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
if (FAILED(result)) {
D3D_SetError("LockRect()", result);
return -1;
}
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;
}
IDirect3DTexture9_UnlockRect(data->texture, 0);
return 0;
}
#endif // SDL_MEMORY_POOL_DEFAULT
654
655
static int
656
657
658
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty, void **pixels,
int *pitch)
659
{
660
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
661
662
663
RECT d3drect;
D3DLOCKED_RECT locked;
HRESULT result;
664
665
666
667
668
669
670
671
672
673
674
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);
675
return -1;
676
}
677
678
679
*pixels = locked.pBits;
*pitch = locked.Pitch;
return 0;
680
681
682
}
static void
683
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
684
{
685
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
686
687
IDirect3DTexture9_UnlockRect(data->texture, 0);
688
689
690
}
static void
691
692
D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
const SDL_Rect * rects)
693
{
694
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
695
696
697
698
699
700
701
702
703
704
705
706
707
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);
}
708
709
710
}
static int
711
712
D3D_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
const SDL_Rect * rect)
713
{
714
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
715
D3DRECT d3drect;
716
HRESULT result;
717
718
719
720
721
if (data->beginScene) {
IDirect3DDevice9_BeginScene(data->device);
data->beginScene = SDL_FALSE;
}
722
723
d3drect.x1 = rect->x;
724
d3drect.x2 = rect->x + rect->w;
725
d3drect.y1 = rect->y;
726
d3drect.y2 = rect->y + rect->h;
727
728
729
result =
IDirect3DDevice9_Clear(data->device, 1, &d3drect, D3DCLEAR_TARGET,
730
D3DCOLOR_ARGB(a, r, g, b), 1.0f, 0);
731
732
733
734
if (FAILED(result)) {
D3D_SetError("Clear()", result);
return -1;
}
735
736
737
738
return 0;
}
static int
739
D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
740
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
741
{
742
743
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
744
float minx, miny, maxx, maxy;
745
float minu, maxu, minv, maxv;
746
DWORD color;
747
748
Vertex vertices[4];
HRESULT result;
749
750
751
752
753
if (data->beginScene) {
IDirect3DDevice9_BeginScene(data->device);
data->beginScene = SDL_FALSE;
}
754
755
756
757
758
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;
759
760
761
762
763
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;
764
765
766
color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
767
768
769
vertices[0].x = minx;
vertices[0].y = miny;
vertices[0].z = 0.0f;
770
vertices[0].rhw = 1.0f;
771
vertices[0].color = color;
772
773
774
vertices[0].u = minu;
vertices[0].v = minv;
775
776
777
vertices[1].x = maxx;
vertices[1].y = miny;
vertices[1].z = 0.0f;
778
vertices[1].rhw = 1.0f;
779
vertices[1].color = color;
780
781
782
vertices[1].u = maxu;
vertices[1].v = minv;
783
784
785
vertices[2].x = maxx;
vertices[2].y = maxy;
vertices[2].z = 0.0f;
786
vertices[2].rhw = 1.0f;
787
vertices[2].color = color;
788
789
790
vertices[2].u = maxu;
vertices[2].v = maxv;
791
792
793
vertices[3].x = minx;
vertices[3].y = maxy;
vertices[3].z = 0.0f;
794
vertices[3].rhw = 1.0f;
795
vertices[3].color = color;
796
797
vertices[3].u = minu;
vertices[3].v = maxv;
798
799
switch (texture->blendMode) {
800
case SDL_BLENDMODE_NONE:
801
802
803
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
FALSE);
break;
804
805
case SDL_BLENDMODE_MASK:
case SDL_BLENDMODE_BLEND:
806
807
808
809
810
811
812
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
TRUE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
D3DBLEND_SRCALPHA);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
D3DBLEND_INVSRCALPHA);
break;
813
case SDL_BLENDMODE_ADD:
814
815
816
817
818
819
820
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
TRUE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
D3DBLEND_SRCALPHA);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
D3DBLEND_ONE);
break;
821
case SDL_BLENDMODE_MOD:
822
823
824
825
826
827
828
829
830
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
TRUE);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
D3DBLEND_ZERO);
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
D3DBLEND_SRCCOLOR);
break;
}
831
switch (texture->scaleMode) {
832
833
case SDL_TEXTURESCALEMODE_NONE:
case SDL_TEXTURESCALEMODE_FAST:
834
835
836
837
838
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_POINT);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_POINT);
break;
839
case SDL_TEXTURESCALEMODE_SLOW:
840
841
842
843
844
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_LINEAR);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_LINEAR);
break;
845
case SDL_TEXTURESCALEMODE_BEST:
846
847
848
849
850
851
852
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
D3DTEXF_GAUSSIANQUAD);
IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
D3DTEXF_GAUSSIANQUAD);
break;
}
853
result =
854
855
IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
texturedata->texture);
856
857
858
859
860
861
862
863
864
865
866
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;
}
867
868
869
870
return 0;
}
static void
871
D3D_RenderPresent(SDL_Renderer * renderer)
872
{
873
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
874
875
876
877
878
879
880
HRESULT result;
if (!data->beginScene) {
IDirect3DDevice9_EndScene(data->device);
data->beginScene = SDL_TRUE;
}
881
882
883
884
885
886
887
888
result = IDirect3DDevice9_TestCooperativeLevel(data->device);
if (result == D3DERR_DEVICELOST) {
/* We'll reset later */
return;
}
if (result == D3DERR_DEVICENOTRESET) {
D3D_Reset(renderer);
}
889
890
891
892
result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
if (FAILED(result)) {
D3D_SetError("Present()", result);
}
893
894
895
}
static void
896
D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
897
{
898
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
899
900
901
902
if (!data) {
return;
}
903
904
905
if (data->texture) {
IDirect3DTexture9_Release(data->texture);
}
906
907
908
909
SDL_free(data);
texture->driverdata = NULL;
}
910
static void
911
D3D_DestroyRenderer(SDL_Renderer * renderer)
912
{
913
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
914
915
if (data) {
916
917
918
if (data->device) {
IDirect3DDevice9_Release(data->device);
}
919
920
921
922
923
924
925
926
SDL_free(data);
}
SDL_free(renderer);
}
#endif /* SDL_VIDEO_RENDER_D3D */
/* vi: set ts=4 sw=4 expandtab: */