1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * DirectX implementation of some of the primitive routines.
12 *
13 *
14 * By Pavel Sountsov.
15 *
16 * See readme.txt for copyright information.
17 */
18
19 #include "allegro5/allegro.h"
20 #include "allegro5/allegro_primitives.h"
21 #include "allegro5/internal/aintern_bitmap.h"
22 #include "allegro5/internal/aintern_prim_directx.h"
23 #include "allegro5/internal/aintern_prim_soft.h"
24 #include "allegro5/internal/aintern_prim.h"
25 #include "allegro5/internal/aintern_display.h"
26
27 #include "allegro5/platform/alplatf.h"
28
29 #ifdef ALLEGRO_CFG_D3D
30
31 #include "allegro5/allegro_direct3d.h"
32 #include "allegro5/internal/aintern_direct3d.h"
33
34 ALLEGRO_DEBUG_CHANNEL("d3d_primitives")
35
36 static ALLEGRO_MUTEX *d3d_mutex;
37 /*
38 * In the context of this file, legacy cards pretty much refer to older Intel cards.
39 * They are distinguished by three misfeatures:
40 * 1. They don't support shaders
41 * 2. They don't support custom vertices
42 * 3. DrawIndexedPrimitiveUP is broken
43 *
44 * Since shaders are used 100% of the time, this means that for these cards
45 * the incoming vertices are first converted into the vertex type that these cards
46 * can handle.
47 */
48 static bool legacy_card = false;
49 static bool know_card_type = false;
50
is_legacy_card(void)51 static bool is_legacy_card(void)
52 {
53 if (!know_card_type) {
54 ALLEGRO_CONFIG* sys_cfg = al_get_system_config();
55 const char* detection_setting = al_get_config_value(sys_cfg, "graphics", "prim_d3d_legacy_detection");
56 detection_setting = detection_setting ? detection_setting : "default";
57 if (strcmp(detection_setting, "default") == 0) {
58 D3DCAPS9 caps;
59 LPDIRECT3DDEVICE9 device = al_get_d3d_device(al_get_current_display());
60 device->GetDeviceCaps(&caps);
61 if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
62 legacy_card = true;
63 } else if(strcmp(detection_setting, "force_legacy") == 0) {
64 legacy_card = true;
65 } else if(strcmp(detection_setting, "force_modern") == 0) {
66 legacy_card = false;
67 } else {
68 ALLEGRO_WARN("Invalid setting for prim_d3d_legacy_detection.\n");
69 legacy_card = false;
70 }
71 if (legacy_card) {
72 ALLEGRO_WARN("Your GPU is considered legacy! Some of the features of the primitives addon will be slower/disabled.\n");
73 }
74 know_card_type = true;
75 }
76 return legacy_card;
77 }
78
79 typedef struct LEGACY_VERTEX
80 {
81 float x, y, z;
82 DWORD color;
83 float u, v;
84 } LEGACY_VERTEX;
85
86 static uint8_t* legacy_buffer;
87 static size_t legacy_buffer_size = 0;
88 #define A5V_FVF (D3DFVF_XYZ | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE4(1))
89 #define A5V_LEGACY_FVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
90
91 typedef struct DISPLAY_LOCAL_DATA
92 {
93 LPDIRECT3DDEVICE9 device;
94 LPDIRECT3DVERTEXSHADER9 shader;
95 ALLEGRO_INDEX_BUFFER* loop_index_buffer;
96 } DISPLAY_LOCAL_DATA;
97
98 static DISPLAY_LOCAL_DATA* display_local_data;
99 static int display_local_data_size = 0;
100
display_invalidated(ALLEGRO_DISPLAY * display)101 static void display_invalidated(ALLEGRO_DISPLAY* display)
102 {
103 int ii;
104 LPDIRECT3DDEVICE9 device = al_get_d3d_device(display);
105 /*
106 * If there is no mutex, the addon has been shutdown earlier
107 */
108 if(!d3d_mutex)
109 return;
110
111 al_lock_mutex(d3d_mutex);
112
113 for(ii = 0; ii < display_local_data_size; ii++)
114 {
115 if(display_local_data[ii].device == device) {
116 display_local_data[ii].shader->Release();
117 display_local_data[ii] = display_local_data[display_local_data_size - 1];
118 display_local_data_size--;
119 break;
120 }
121 }
122
123 al_unlock_mutex(d3d_mutex);
124 }
125
get_display_local_data(ALLEGRO_DISPLAY * display)126 static DISPLAY_LOCAL_DATA get_display_local_data(ALLEGRO_DISPLAY* display)
127 {
128 LPDIRECT3DDEVICE9 device = al_get_d3d_device(display);
129 DISPLAY_LOCAL_DATA ret;
130 bool create_new = false;
131
132 /*
133 * Lock the mutex so that the entries are not messed up by a
134 * display blowing up/being created
135 */
136 al_lock_mutex(d3d_mutex);
137
138 if (display_local_data_size == 0) {
139 display_local_data = (DISPLAY_LOCAL_DATA*)al_malloc(sizeof(DISPLAY_LOCAL_DATA));
140 display_local_data_size = 1;
141 create_new = true;
142 }
143 else if (display_local_data[0].device != device) {
144 int ii;
145 bool found = false;
146 for(ii = 1; ii < display_local_data_size; ii++)
147 {
148 if(display_local_data[ii].device == device) {
149 /*
150 * Move this entry to the front, so the search goes faster
151 * next time - presumably the al_draw_prim will be called
152 * several times for each display before switching again
153 */
154 DISPLAY_LOCAL_DATA t = display_local_data[0];
155 display_local_data[0] = display_local_data[ii];
156 display_local_data[ii] = t;
157
158 found = true;
159
160 break;
161 }
162 }
163
164 if (!found) {
165 DISPLAY_LOCAL_DATA t = display_local_data[0];
166
167 display_local_data_size++;
168 display_local_data = (DISPLAY_LOCAL_DATA *)al_realloc(display_local_data, sizeof(DISPLAY_LOCAL_DATA) * display_local_data_size);
169
170 display_local_data[display_local_data_size - 1] = t;
171 create_new = true;
172 }
173 }
174
175 if (create_new) {
176 int initial_indices[2] = {0, 0};
177 display_local_data[0].device = device;
178 display_local_data[0].shader = (LPDIRECT3DVERTEXSHADER9)_al_create_default_primitives_shader(device);
179 display_local_data[0].loop_index_buffer = al_create_index_buffer(sizeof(int), initial_indices, 2, 0);
180
181 _al_add_display_invalidated_callback(display, &display_invalidated);
182 }
183
184 ret = display_local_data[0];
185
186 al_unlock_mutex(d3d_mutex);
187
188 return ret;
189 }
190
destroy_display_local_data(void)191 static void destroy_display_local_data(void)
192 {
193 int ii;
194 for(ii = 0; ii < display_local_data_size; ii++)
195 {
196 display_local_data[ii].shader->Release();
197 al_destroy_index_buffer(display_local_data[ii].loop_index_buffer);
198 }
199 display_local_data_size = 0;
200 al_free(display_local_data);
201 display_local_data = NULL;
202 }
203
204 #endif
205
_al_init_d3d_driver(void)206 bool _al_init_d3d_driver(void)
207 {
208 #ifdef ALLEGRO_CFG_D3D
209 d3d_mutex = al_create_mutex();
210 #endif
211 return true;
212 }
213
_al_shutdown_d3d_driver(void)214 void _al_shutdown_d3d_driver(void)
215 {
216 #ifdef ALLEGRO_CFG_D3D
217 al_destroy_mutex(d3d_mutex);
218 al_free(legacy_buffer);
219 d3d_mutex = NULL;
220 legacy_buffer = NULL;
221
222 destroy_display_local_data();
223
224 legacy_card = false;
225 know_card_type = false;
226 legacy_buffer_size = 0;
227 #endif
228 }
229
230 #ifdef ALLEGRO_CFG_D3D
231
convert_to_legacy_vertices(const void * vtxs,int num_vertices,const int * indices,bool loop,bool pp)232 static void* convert_to_legacy_vertices(const void* vtxs, int num_vertices, const int* indices, bool loop, bool pp)
233 {
234 const ALLEGRO_VERTEX* vtx = (const ALLEGRO_VERTEX *)vtxs;
235 int ii;
236 int num_needed_vertices = num_vertices;
237 size_t needed_size;
238
239 if (pp && !indices && !loop) {
240 return (void *)vtxs;
241 }
242
243 if(loop)
244 num_needed_vertices++;
245
246 needed_size = num_needed_vertices * (pp ? sizeof(ALLEGRO_VERTEX) : sizeof(LEGACY_VERTEX));
247
248 if(legacy_buffer == 0) {
249 legacy_buffer = (uint8_t *)al_malloc(needed_size);
250 legacy_buffer_size = needed_size;
251 } else if (needed_size > legacy_buffer_size) {
252 size_t new_size = needed_size * 1.5;
253 legacy_buffer = (uint8_t *)al_realloc(legacy_buffer, new_size);
254 legacy_buffer_size = new_size;
255 }
256
257 if (pp) {
258 ALLEGRO_VERTEX *buffer = (ALLEGRO_VERTEX *)legacy_buffer;
259 for(ii = 0; ii < num_vertices; ii++) {
260 if(indices)
261 buffer[ii] = vtx[indices[ii]];
262 else
263 buffer[ii] = vtx[ii];
264 }
265 if(loop)
266 buffer[num_vertices] = buffer[0];
267 }
268 else {
269 LEGACY_VERTEX *buffer = (LEGACY_VERTEX *)legacy_buffer;
270 for(ii = 0; ii < num_vertices; ii++) {
271 ALLEGRO_VERTEX vertex;
272
273 if(indices)
274 vertex = vtx[indices[ii]];
275 else
276 vertex = vtx[ii];
277
278 buffer[ii].x = vertex.x;
279 buffer[ii].y = vertex.y;
280 buffer[ii].z = vertex.z;
281
282 buffer[ii].u = vertex.u;
283 buffer[ii].v = vertex.v;
284
285 buffer[ii].color = D3DCOLOR_COLORVALUE(vertex.color.r, vertex.color.g, vertex.color.b, vertex.color.a);
286 }
287 if(loop)
288 buffer[num_vertices] = buffer[0];
289 }
290
291 return legacy_buffer;
292 }
293
294 struct D3D_STATE
295 {
296 DWORD old_wrap_state[2];
297 DWORD old_ttf_state;
298 IDirect3DVertexShader9* old_vtx_shader;
299 };
300
setup_state(LPDIRECT3DDEVICE9 device,const ALLEGRO_VERTEX_DECL * decl,ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,DISPLAY_LOCAL_DATA data)301 static D3D_STATE setup_state(LPDIRECT3DDEVICE9 device, const ALLEGRO_VERTEX_DECL* decl, ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, DISPLAY_LOCAL_DATA data)
302 {
303 D3D_STATE state;
304 ALLEGRO_DISPLAY *disp = _al_get_bitmap_display(target);
305 ALLEGRO_DISPLAY_D3D *d3d_disp = (ALLEGRO_DISPLAY_D3D *)disp;
306
307 if (!(disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) {
308 IDirect3DPixelShader9* old_pix_shader;
309 device->GetVertexShader(&state.old_vtx_shader);
310 device->GetPixelShader(&old_pix_shader);
311
312 if(!old_pix_shader) {
313 _al_d3d_set_blender(d3d_disp);
314 }
315
316 if(!state.old_vtx_shader) {
317 /* Prepare the default shader */
318 if(!is_legacy_card()) {
319 if(decl)
320 _al_setup_primitives_shader(device, decl);
321 else
322 _al_setup_default_primitives_shader(device, data.shader);
323 }
324 }
325 }
326 else {
327 state.old_vtx_shader = NULL;
328 _al_d3d_set_blender(d3d_disp);
329 }
330
331 /* Set the vertex declarations */
332 if(is_legacy_card() && !(disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) {
333 device->SetFVF(A5V_LEGACY_FVF);
334 } else {
335 if(decl) {
336 device->SetVertexDeclaration((IDirect3DVertexDeclaration9*)decl->d3d_decl);
337 } else {
338 device->SetFVF(A5V_FVF);
339 }
340 }
341
342 if(!state.old_vtx_shader || (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) {
343 /* Set up the texture */
344 if (texture) {
345 LPDIRECT3DTEXTURE9 d3d_texture;
346 int tex_x, tex_y;
347 D3DSURFACE_DESC desc;
348 float mat[4][4] = {
349 {1, 0, 0, 0},
350 {0, 1, 0, 0},
351 {0, 0, 1, 0},
352 {0, 0, 0, 1}
353 };
354
355 d3d_texture = al_get_d3d_video_texture(texture);
356
357 d3d_texture->GetLevelDesc(0, &desc);
358 al_get_d3d_texture_position(texture, &tex_x, &tex_y);
359
360 if(decl) {
361 if(decl->elements[ALLEGRO_PRIM_TEX_COORD_PIXEL].attribute) {
362 mat[0][0] = 1.0f / desc.Width;
363 mat[1][1] = 1.0f / desc.Height;
364 } else {
365 mat[0][0] = (float)al_get_bitmap_width(texture) / desc.Width;
366 mat[1][1] = (float)al_get_bitmap_height(texture) / desc.Height;
367 }
368 } else {
369 mat[0][0] = 1.0f / desc.Width;
370 mat[1][1] = 1.0f / desc.Height;
371 }
372 mat[2][0] = (float)tex_x / desc.Width;
373 mat[2][1] = (float)tex_y / desc.Height;
374
375
376 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
377 #ifdef ALLEGRO_CFG_SHADER_HLSL
378 d3d_disp->effect->SetMatrix(ALLEGRO_SHADER_VAR_TEX_MATRIX, (D3DXMATRIX *)mat);
379 d3d_disp->effect->SetBool(ALLEGRO_SHADER_VAR_USE_TEX_MATRIX, true);
380 d3d_disp->effect->SetBool(ALLEGRO_SHADER_VAR_USE_TEX, true);
381 d3d_disp->effect->SetTexture(ALLEGRO_SHADER_VAR_TEX, d3d_texture);
382 #endif
383 }
384 else {
385 if(is_legacy_card()) {
386 device->GetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, &state.old_ttf_state);
387 device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
388 device->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX *)&mat);
389 } else {
390 _al_set_texture_matrix(device, mat[0]);
391 }
392 }
393
394 device->SetTexture(0, d3d_texture);
395
396 } else {
397 /* Don't unbind the texture here if shaders are used, since the user may
398 * have set the 0'th texture unit manually via the shader API. */
399 if (!(disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) {
400 device->SetTexture(0, NULL);
401 }
402 }
403 }
404
405 device->GetSamplerState(0, D3DSAMP_ADDRESSU, &state.old_wrap_state[0]);
406 device->GetSamplerState(0, D3DSAMP_ADDRESSV, &state.old_wrap_state[1]);
407
408 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
409 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
410
411 if (texture) {
412 int texture_flags = al_get_bitmap_flags(texture);
413 if (texture_flags & ALLEGRO_MIN_LINEAR) {
414 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
415 }
416 else {
417 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
418 }
419 if (texture_flags & ALLEGRO_MAG_LINEAR) {
420 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
421 }
422 else {
423 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
424 }
425 if (texture_flags & ALLEGRO_MIPMAP) {
426 device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
427 }
428 else {
429 device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
430 }
431 }
432
433 return state;
434 }
435
revert_state(D3D_STATE state,LPDIRECT3DDEVICE9 device,ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture)436 static void revert_state(D3D_STATE state, LPDIRECT3DDEVICE9 device, ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture)
437 {
438 ALLEGRO_DISPLAY *disp = _al_get_bitmap_display(target);
439 ALLEGRO_DISPLAY_D3D *d3d_disp = (ALLEGRO_DISPLAY_D3D *)disp;
440 (void)d3d_disp;
441 #ifdef ALLEGRO_CFG_SHADER_HLSL
442 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
443 d3d_disp->effect->End();
444 d3d_disp->effect->SetBool(ALLEGRO_SHADER_VAR_USE_TEX_MATRIX, false);
445 d3d_disp->effect->SetBool(ALLEGRO_SHADER_VAR_USE_TEX, false);
446 }
447 #endif
448
449 device->SetSamplerState(0, D3DSAMP_ADDRESSU, state.old_wrap_state[0]);
450 device->SetSamplerState(0, D3DSAMP_ADDRESSV, state.old_wrap_state[1]);
451
452 if(!state.old_vtx_shader && is_legacy_card() && texture) {
453 device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, state.old_ttf_state);
454 }
455
456 if (!(disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) {
457 if(!state.old_vtx_shader)
458 device->SetVertexShader(0);
459 }
460 }
461
draw_prim_raw(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,const void * vtx,const ALLEGRO_VERTEX_DECL * decl,const int * indices,int num_vtx,int type)462 static int draw_prim_raw(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture,
463 const void* vtx, const ALLEGRO_VERTEX_DECL* decl,
464 const int* indices, int num_vtx, int type)
465 {
466 int stride;
467 int num_primitives = 0;
468 LPDIRECT3DDEVICE9 device;
469 int min_idx = 0, max_idx = num_vtx - 1;
470 ALLEGRO_DISPLAY *disp = _al_get_bitmap_display(target);
471 ALLEGRO_DISPLAY_D3D *d3d_disp = (ALLEGRO_DISPLAY_D3D *)disp;
472 UINT required_passes = 1;
473 unsigned int i;
474 D3D_STATE state;
475 DISPLAY_LOCAL_DATA data;
476 (void)d3d_disp;
477
478 if (al_is_d3d_device_lost(disp)) {
479 return 0;
480 }
481
482 if (is_legacy_card() && !(disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) {
483 stride = (int)sizeof(LEGACY_VERTEX);
484 }
485 else {
486 stride = (decl ? decl->stride : (int)sizeof(ALLEGRO_VERTEX));
487 }
488
489 /* Check for early exit */
490 if((is_legacy_card() && decl) || (decl && decl->d3d_decl == 0)) {
491 if(!indices)
492 return _al_draw_prim_soft(texture, vtx, decl, 0, num_vtx, type);
493 else
494 return _al_draw_prim_indexed_soft(texture, vtx, decl, indices, num_vtx, type);
495 }
496
497 int num_idx = num_vtx;
498 if(indices)
499 {
500 int ii;
501 for(ii = 0; ii < num_vtx; ii++)
502 {
503 int idx = indices[ii];
504 if(ii == 0) {
505 min_idx = idx;
506 max_idx = idx;
507 } else if (idx < min_idx) {
508 min_idx = idx;
509 } else if (idx > max_idx) {
510 max_idx = idx;
511 }
512 }
513 num_idx = max_idx + 1 - min_idx;
514 }
515
516 device = al_get_d3d_device(disp);
517
518 data = get_display_local_data(disp);
519
520 state = setup_state(device, decl, target, texture, data);
521
522 /* Convert vertices for legacy cards */
523 if(is_legacy_card()) {
524 al_lock_mutex(d3d_mutex);
525 vtx = convert_to_legacy_vertices(vtx, num_vtx, indices, type == ALLEGRO_PRIM_LINE_LOOP,
526 disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE);
527 }
528
529 #ifdef ALLEGRO_CFG_SHADER_HLSL
530 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
531 d3d_disp->effect->Begin(&required_passes, 0);
532 }
533 #endif
534
535 for (i = 0; i < required_passes; i++) {
536 #ifdef ALLEGRO_CFG_SHADER_HLSL
537 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
538 d3d_disp->effect->BeginPass(i);
539 }
540 #endif
541
542 if (!indices || is_legacy_card())
543 {
544 switch (type) {
545 case ALLEGRO_PRIM_LINE_LIST: {
546 num_primitives = num_vtx / 2;
547 device->DrawPrimitiveUP(D3DPT_LINELIST, num_primitives, vtx, stride);
548 break;
549 };
550 case ALLEGRO_PRIM_LINE_STRIP: {
551 num_primitives = num_vtx - 1;
552 device->DrawPrimitiveUP(D3DPT_LINESTRIP, num_primitives, vtx, stride);
553 break;
554 };
555 case ALLEGRO_PRIM_LINE_LOOP: {
556 num_primitives = num_vtx - 1;
557 device->DrawPrimitiveUP(D3DPT_LINESTRIP, num_primitives, vtx, stride);
558 if(!is_legacy_card()) {
559 int in[2];
560 in[0] = 0;
561 in[1] = num_vtx-1;
562
563 device->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, num_vtx, 1, in, D3DFMT_INDEX32, vtx, stride);
564 } else {
565 device->DrawPrimitiveUP(D3DPT_LINELIST, 1, (char*)vtx + stride * (num_vtx - 1), stride);
566 }
567 break;
568 };
569 case ALLEGRO_PRIM_TRIANGLE_LIST: {
570 num_primitives = num_vtx / 3;
571 device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, num_primitives, vtx, stride);
572 break;
573 };
574 case ALLEGRO_PRIM_TRIANGLE_STRIP: {
575 num_primitives = num_vtx - 2;
576 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, num_primitives, vtx, stride);
577 break;
578 };
579 case ALLEGRO_PRIM_TRIANGLE_FAN: {
580 num_primitives = num_vtx - 2;
581 device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, num_primitives, vtx, stride);
582 break;
583 };
584 case ALLEGRO_PRIM_POINT_LIST: {
585 num_primitives = num_vtx;
586 device->DrawPrimitiveUP(D3DPT_POINTLIST, num_primitives, vtx, stride);
587 break;
588 };
589 }
590 } else {
591 switch (type) {
592 case ALLEGRO_PRIM_LINE_LIST: {
593 num_primitives = num_vtx / 2;
594 device->DrawIndexedPrimitiveUP(D3DPT_LINELIST, min_idx, num_idx, num_primitives, indices, D3DFMT_INDEX32, vtx, stride);
595 break;
596 };
597 case ALLEGRO_PRIM_LINE_STRIP: {
598 num_primitives = num_vtx - 1;
599 device->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, min_idx, num_idx, num_primitives, indices, D3DFMT_INDEX32, vtx, stride);
600 break;
601 };
602 case ALLEGRO_PRIM_LINE_LOOP: {
603 int in[2];
604 num_primitives = num_vtx - 1;
605 device->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, min_idx, num_idx, num_primitives, indices, D3DFMT_INDEX32, vtx, stride);
606
607 in[0] = indices[0];
608 in[1] = indices[num_vtx-1];
609 min_idx = in[0] > in[1] ? in[1] : in[0];
610 max_idx = in[0] > in[1] ? in[0] : in[1];
611 num_idx = max_idx - min_idx + 1;
612 device->DrawIndexedPrimitiveUP(D3DPT_LINELIST, min_idx, num_idx, 1, in, D3DFMT_INDEX32, vtx, stride);
613 break;
614 };
615 case ALLEGRO_PRIM_TRIANGLE_LIST: {
616 num_primitives = num_vtx / 3;
617 device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, min_idx, num_idx, num_primitives, indices, D3DFMT_INDEX32, vtx, stride);
618 break;
619 };
620 case ALLEGRO_PRIM_TRIANGLE_STRIP: {
621 num_primitives = num_vtx - 2;
622 device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, min_idx, num_idx, num_primitives, indices, D3DFMT_INDEX32, vtx, stride);
623 break;
624 };
625 case ALLEGRO_PRIM_TRIANGLE_FAN: {
626 num_primitives = num_vtx - 2;
627 device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, min_idx, num_idx, num_primitives, indices, D3DFMT_INDEX32, vtx, stride);
628 break;
629 };
630 case ALLEGRO_PRIM_POINT_LIST: {
631 /*
632 * D3D does not support point lists in indexed mode, so we draw them using the non-indexed mode. To gain at least a semblance
633 * of speed, we detect consecutive runs of vertices and draw them using a single DrawPrimitiveUP call
634 */
635 int ii = 0;
636 int start_idx = indices[0];
637 int run_length = 0;
638 for(ii = 0; ii < num_vtx; ii++)
639 {
640 run_length++;
641 if(indices[ii] + 1 != indices[ii + 1] || ii == num_vtx - 1) {
642 device->DrawPrimitiveUP(D3DPT_POINTLIST, run_length, (const char*)vtx + start_idx * stride, stride);
643 if(ii != num_vtx - 1)
644 start_idx = indices[ii + 1];
645 run_length = 0;
646 }
647 }
648 break;
649 };
650 }
651 }
652
653 #ifdef ALLEGRO_CFG_SHADER_HLSL
654 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
655 d3d_disp->effect->EndPass();
656 }
657 #endif
658 }
659
660 if(is_legacy_card())
661 al_unlock_mutex(d3d_mutex);
662
663 revert_state(state, device, target, texture);
664
665 return num_primitives;
666 }
667
668 #endif
669
_al_draw_prim_directx(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,const void * vtxs,const ALLEGRO_VERTEX_DECL * decl,int start,int end,int type)670 int _al_draw_prim_directx(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, const void* vtxs, const ALLEGRO_VERTEX_DECL* decl, int start, int end, int type)
671 {
672 #ifdef ALLEGRO_CFG_D3D
673 int stride = decl ? decl->stride : (int)sizeof(ALLEGRO_VERTEX);
674 return draw_prim_raw(target, texture, (const char*)vtxs + start * stride, decl, 0, end - start, type);
675 #else
676 (void)target;
677 (void)texture;
678 (void)vtxs;
679 (void)start;
680 (void)end;
681 (void)type;
682 (void)decl;
683
684 return 0;
685 #endif
686 }
687
_al_draw_prim_indexed_directx(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,const void * vtxs,const ALLEGRO_VERTEX_DECL * decl,const int * indices,int num_vtx,int type)688 int _al_draw_prim_indexed_directx(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, const void* vtxs, const ALLEGRO_VERTEX_DECL* decl, const int* indices, int num_vtx, int type)
689 {
690 #ifdef ALLEGRO_CFG_D3D
691 return draw_prim_raw(target, texture, vtxs, decl, indices, num_vtx, type);
692 #else
693 (void)target;
694 (void)texture;
695 (void)vtxs;
696 (void)indices;
697 (void)num_vtx;
698 (void)type;
699 (void)decl;
700
701 return 0;
702 #endif
703 }
704
705 #ifdef ALLEGRO_CFG_D3D
draw_buffer_raw(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,ALLEGRO_VERTEX_BUFFER * vertex_buffer,ALLEGRO_INDEX_BUFFER * index_buffer,int start,int end,int type)706 static int draw_buffer_raw(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, ALLEGRO_VERTEX_BUFFER* vertex_buffer, ALLEGRO_INDEX_BUFFER* index_buffer, int start, int end, int type)
707 {
708 int num_primitives = 0;
709 int num_vtx = end - start;
710 LPDIRECT3DDEVICE9 device;
711 ALLEGRO_DISPLAY *disp = _al_get_bitmap_display(target);
712 ALLEGRO_DISPLAY_D3D *d3d_disp = (ALLEGRO_DISPLAY_D3D *)disp;
713 UINT required_passes = 1;
714 unsigned int i;
715 D3D_STATE state;
716 DISPLAY_LOCAL_DATA data;
717 (void)d3d_disp;
718
719 if (al_is_d3d_device_lost(disp)) {
720 return 0;
721 }
722
723 /* Check for early exit for legacy cards */
724 if (vertex_buffer->decl && vertex_buffer->decl->d3d_decl == 0) {
725 return _al_draw_buffer_common_soft(vertex_buffer, texture, index_buffer, start, end, type);
726 }
727
728 device = al_get_d3d_device(disp);
729
730 data = get_display_local_data(disp);
731
732 state = setup_state(device, vertex_buffer->decl, target, texture, data);
733
734 device->SetStreamSource(0, (IDirect3DVertexBuffer9*)vertex_buffer->common.handle, 0, vertex_buffer->decl ? vertex_buffer->decl->stride : (int)sizeof(ALLEGRO_VERTEX));
735
736 if (index_buffer) {
737 device->SetIndices((IDirect3DIndexBuffer9*)index_buffer->common.handle);
738 }
739
740 #ifdef ALLEGRO_CFG_SHADER_HLSL
741 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
742 d3d_disp->effect->Begin(&required_passes, 0);
743 }
744 #endif
745
746 for (i = 0; i < required_passes; i++) {
747 #ifdef ALLEGRO_CFG_SHADER_HLSL
748 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
749 d3d_disp->effect->BeginPass(i);
750 }
751 #endif
752
753 if (!index_buffer) {
754 switch (type) {
755 case ALLEGRO_PRIM_LINE_LIST: {
756 num_primitives = num_vtx / 2;
757 device->DrawPrimitive(D3DPT_LINELIST, start, num_primitives);
758 break;
759 };
760 case ALLEGRO_PRIM_LINE_STRIP: {
761 num_primitives = num_vtx - 1;
762 device->DrawPrimitive(D3DPT_LINESTRIP, start, num_primitives);
763 break;
764 };
765 case ALLEGRO_PRIM_LINE_LOOP: {
766 int* indices;
767 num_primitives = num_vtx - 1;
768 device->DrawPrimitive(D3DPT_LINESTRIP, start, num_primitives);
769
770 if (data.loop_index_buffer) {
771 al_lock_mutex(d3d_mutex);
772 indices = (int*)al_lock_index_buffer(data.loop_index_buffer, 0, 2, ALLEGRO_LOCK_WRITEONLY);
773 ASSERT(indices);
774 indices[0] = start;
775 indices[1] = start + num_vtx - 1;
776 al_unlock_index_buffer(data.loop_index_buffer);
777 device->SetIndices((IDirect3DIndexBuffer9*)data.loop_index_buffer->common.handle);
778 device->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 0, al_get_vertex_buffer_size(vertex_buffer), 0, 1);
779 al_unlock_mutex(d3d_mutex);
780 }
781 break;
782 };
783 case ALLEGRO_PRIM_TRIANGLE_LIST: {
784 num_primitives = num_vtx / 3;
785 device->DrawPrimitive(D3DPT_TRIANGLELIST, start, num_primitives);
786 break;
787 };
788 case ALLEGRO_PRIM_TRIANGLE_STRIP: {
789 num_primitives = num_vtx - 2;
790 device->DrawPrimitive(D3DPT_TRIANGLESTRIP, start, num_primitives);
791 break;
792 };
793 case ALLEGRO_PRIM_TRIANGLE_FAN: {
794 num_primitives = num_vtx - 2;
795 device->DrawPrimitive(D3DPT_TRIANGLEFAN, start, num_primitives);
796 break;
797 };
798 case ALLEGRO_PRIM_POINT_LIST: {
799 num_primitives = num_vtx;
800 device->DrawPrimitive(D3DPT_POINTLIST, start, num_primitives);
801 break;
802 };
803 }
804 }
805 else {
806 int vbuff_size = al_get_vertex_buffer_size(vertex_buffer);
807 switch (type) {
808 case ALLEGRO_PRIM_LINE_LIST: {
809 num_primitives = num_vtx / 2;
810 device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vbuff_size, start, num_primitives);
811 break;
812 };
813 case ALLEGRO_PRIM_LINE_STRIP: {
814 num_primitives = num_vtx - 1;
815 device->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 0, vbuff_size, start, num_primitives);
816 break;
817 };
818 case ALLEGRO_PRIM_LINE_LOOP: {
819 /* Unimplemented, too hard to do in a consistent fashion. */
820 break;
821 };
822 case ALLEGRO_PRIM_TRIANGLE_LIST: {
823 num_primitives = num_vtx / 3;
824 device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vbuff_size, start, num_primitives);
825 break;
826 };
827 case ALLEGRO_PRIM_TRIANGLE_STRIP: {
828 num_primitives = num_vtx - 2;
829 device->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, vbuff_size, start, num_primitives);
830 break;
831 };
832 case ALLEGRO_PRIM_TRIANGLE_FAN: {
833 num_primitives = num_vtx - 2;
834 device->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, vbuff_size, start, num_primitives);
835 break;
836 };
837 case ALLEGRO_PRIM_POINT_LIST: {
838 /* Unimplemented, too hard to do in a consistent fashion. */
839 break;
840 };
841 }
842 }
843
844 #ifdef ALLEGRO_CFG_SHADER_HLSL
845 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
846 d3d_disp->effect->EndPass();
847 }
848 #endif
849 }
850
851 if (is_legacy_card())
852 al_unlock_mutex(d3d_mutex);
853
854 revert_state(state, device, target, texture);
855
856 return num_primitives;
857 }
858 #endif
859
_al_draw_vertex_buffer_directx(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,ALLEGRO_VERTEX_BUFFER * vertex_buffer,int start,int end,int type)860 int _al_draw_vertex_buffer_directx(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, ALLEGRO_VERTEX_BUFFER* vertex_buffer, int start, int end, int type)
861 {
862 #ifdef ALLEGRO_CFG_D3D
863 return draw_buffer_raw(target, texture, vertex_buffer, NULL, start, end, type);
864 #else
865 (void)target;
866 (void)texture;
867 (void)vertex_buffer;
868 (void)start;
869 (void)end;
870 (void)type;
871
872 return 0;
873 #endif
874 }
875
_al_draw_indexed_buffer_directx(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,ALLEGRO_VERTEX_BUFFER * vertex_buffer,ALLEGRO_INDEX_BUFFER * index_buffer,int start,int end,int type)876 int _al_draw_indexed_buffer_directx(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, ALLEGRO_VERTEX_BUFFER* vertex_buffer, ALLEGRO_INDEX_BUFFER* index_buffer, int start, int end, int type)
877 {
878 #ifdef ALLEGRO_CFG_D3D
879 return draw_buffer_raw(target, texture, vertex_buffer, index_buffer, start, end, type);
880 #else
881 (void)target;
882 (void)texture;
883 (void)vertex_buffer;
884 (void)index_buffer;
885 (void)start;
886 (void)end;
887 (void)type;
888
889 return 0;
890 #endif
891 }
892
893 #ifdef ALLEGRO_CFG_D3D
convert_storage(int storage)894 static int convert_storage(int storage)
895 {
896 switch(storage) {
897 case ALLEGRO_PRIM_FLOAT_2:
898 return D3DDECLTYPE_FLOAT2;
899 break;
900 case ALLEGRO_PRIM_FLOAT_3:
901 return D3DDECLTYPE_FLOAT3;
902 break;
903 case ALLEGRO_PRIM_SHORT_2:
904 return D3DDECLTYPE_SHORT2;
905 break;
906 case ALLEGRO_PRIM_FLOAT_1:
907 return D3DDECLTYPE_FLOAT1;
908 break;
909 case ALLEGRO_PRIM_FLOAT_4:
910 return D3DDECLTYPE_FLOAT4;
911 break;
912 case ALLEGRO_PRIM_UBYTE_4:
913 return D3DDECLTYPE_UBYTE4;
914 break;
915 case ALLEGRO_PRIM_SHORT_4:
916 return D3DDECLTYPE_SHORT4;
917 break;
918 case ALLEGRO_PRIM_NORMALIZED_UBYTE_4:
919 return D3DDECLTYPE_UBYTE4N;
920 break;
921 case ALLEGRO_PRIM_NORMALIZED_SHORT_2:
922 return D3DDECLTYPE_SHORT2N;
923 break;
924 case ALLEGRO_PRIM_NORMALIZED_SHORT_4:
925 return D3DDECLTYPE_SHORT4N;
926 break;
927 case ALLEGRO_PRIM_NORMALIZED_USHORT_2:
928 return D3DDECLTYPE_USHORT2N;
929 break;
930 case ALLEGRO_PRIM_NORMALIZED_USHORT_4:
931 return D3DDECLTYPE_USHORT4N;
932 break;
933 case ALLEGRO_PRIM_HALF_FLOAT_2:
934 return D3DDECLTYPE_FLOAT16_2;
935 break;
936 case ALLEGRO_PRIM_HALF_FLOAT_4:
937 return D3DDECLTYPE_FLOAT16_4;
938 break;
939 default:
940 ASSERT(0);
941 return D3DDECLTYPE_UNUSED;
942 }
943 }
944 #endif
945
_al_set_d3d_decl(ALLEGRO_DISPLAY * display,ALLEGRO_VERTEX_DECL * ret)946 void _al_set_d3d_decl(ALLEGRO_DISPLAY* display, ALLEGRO_VERTEX_DECL* ret)
947 {
948 #ifdef ALLEGRO_CFG_D3D
949 {
950 LPDIRECT3DDEVICE9 device;
951 D3DVERTEXELEMENT9 d3delements[ALLEGRO_PRIM_ATTR_NUM + 1];
952 int idx = 0;
953 ALLEGRO_VERTEX_ELEMENT* e;
954 D3DCAPS9 caps;
955
956 device = al_get_d3d_device(display);
957
958 device->GetDeviceCaps(&caps);
959 if(caps.PixelShaderVersion < D3DPS_VERSION(3, 0)) {
960 ret->d3d_decl = 0;
961 } else {
962 int i;
963 e = &ret->elements[ALLEGRO_PRIM_POSITION];
964 if(e->attribute) {
965 d3delements[idx].Stream = 0;
966 d3delements[idx].Offset = e->offset;
967 d3delements[idx].Type = convert_storage(e->storage);
968 d3delements[idx].Method = D3DDECLMETHOD_DEFAULT;
969 d3delements[idx].Usage = D3DDECLUSAGE_POSITION;
970 d3delements[idx].UsageIndex = 0;
971 idx++;
972 }
973
974 e = &ret->elements[ALLEGRO_PRIM_TEX_COORD];
975 if(!e->attribute)
976 e = &ret->elements[ALLEGRO_PRIM_TEX_COORD_PIXEL];
977 if(e->attribute) {
978 d3delements[idx].Stream = 0;
979 d3delements[idx].Offset = e->offset;
980 d3delements[idx].Type = convert_storage(e->storage);
981 d3delements[idx].Method = D3DDECLMETHOD_DEFAULT;
982 d3delements[idx].Usage = D3DDECLUSAGE_TEXCOORD;
983 d3delements[idx].UsageIndex = 0;
984 idx++;
985 }
986
987 e = &ret->elements[ALLEGRO_PRIM_COLOR_ATTR];
988 if(e->attribute) {
989 d3delements[idx].Stream = 0;
990 d3delements[idx].Offset = e->offset;
991 d3delements[idx].Type = D3DDECLTYPE_FLOAT4;
992 d3delements[idx].Method = D3DDECLMETHOD_DEFAULT;
993 d3delements[idx].Usage = D3DDECLUSAGE_TEXCOORD;
994 d3delements[idx].UsageIndex = 1;
995 idx++;
996 }
997
998 for (i = 0; i < _ALLEGRO_PRIM_MAX_USER_ATTR; i++) {
999 e = &ret->elements[ALLEGRO_PRIM_USER_ATTR + i];
1000 if (e->attribute) {
1001 d3delements[idx].Stream = 0;
1002 d3delements[idx].Offset = e->offset;
1003 d3delements[idx].Type = convert_storage(e->storage);
1004 d3delements[idx].Method = D3DDECLMETHOD_DEFAULT;
1005 d3delements[idx].Usage = D3DDECLUSAGE_TEXCOORD;
1006 d3delements[idx].UsageIndex = 2 + i;
1007 idx++;
1008 }
1009 }
1010
1011 d3delements[idx].Stream = 0xFF;
1012 d3delements[idx].Offset = 0;
1013 d3delements[idx].Type = D3DDECLTYPE_UNUSED;
1014 d3delements[idx].Method = 0;
1015 d3delements[idx].Usage = 0;
1016 d3delements[idx].UsageIndex = 0;
1017
1018 device->CreateVertexDeclaration(d3delements, (IDirect3DVertexDeclaration9**)&ret->d3d_decl);
1019 }
1020
1021 _al_create_primitives_shader(device, ret);
1022 }
1023 #else
1024 (void)display;
1025 ret->d3d_decl = 0;
1026 #endif
1027 }
1028
_al_create_vertex_buffer_directx(ALLEGRO_VERTEX_BUFFER * buf,const void * initial_data,size_t num_vertices,int flags)1029 bool _al_create_vertex_buffer_directx(ALLEGRO_VERTEX_BUFFER* buf, const void* initial_data, size_t num_vertices, int flags)
1030 {
1031 #ifdef ALLEGRO_CFG_D3D
1032 LPDIRECT3DDEVICE9 device;
1033 IDirect3DVertexBuffer9* d3d_vbuff;
1034 DWORD fvf = A5V_FVF;
1035 int stride = buf->decl ? buf->decl->stride : (int)sizeof(ALLEGRO_VERTEX);
1036 HRESULT res;
1037 void* locked_memory;
1038
1039 /* There's just no point */
1040 if (is_legacy_card()) {
1041 ALLEGRO_WARN("Cannot create vertex buffer for a legacy card.\n");
1042 return false;
1043 }
1044
1045 device = al_get_d3d_device(al_get_current_display());
1046
1047 if (buf->decl) {
1048 device->SetVertexDeclaration((IDirect3DVertexDeclaration9*)buf->decl->d3d_decl);
1049 fvf = 0;
1050 }
1051
1052 res = device->CreateVertexBuffer(stride * num_vertices, !(flags & ALLEGRO_PRIM_BUFFER_READWRITE) ? D3DUSAGE_WRITEONLY : 0,
1053 fvf, D3DPOOL_MANAGED, &d3d_vbuff, 0);
1054 if (res != D3D_OK) {
1055 ALLEGRO_WARN("CreateVertexBuffer failed: %ld.\n", res);
1056 return false;
1057 }
1058
1059 if (initial_data != NULL) {
1060 d3d_vbuff->Lock(0, 0, &locked_memory, 0);
1061 memcpy(locked_memory, initial_data, stride * num_vertices);
1062 d3d_vbuff->Unlock();
1063 }
1064
1065 buf->common.handle = (uintptr_t)d3d_vbuff;
1066
1067 return true;
1068 #else
1069 (void)buf;
1070 (void)initial_data;
1071 (void)num_vertices;
1072 (void)flags;
1073
1074 return false;
1075 #endif
1076 }
1077
_al_create_index_buffer_directx(ALLEGRO_INDEX_BUFFER * buf,const void * initial_data,size_t num_indices,int flags)1078 bool _al_create_index_buffer_directx(ALLEGRO_INDEX_BUFFER* buf, const void* initial_data, size_t num_indices, int flags)
1079 {
1080 #ifdef ALLEGRO_CFG_D3D
1081 LPDIRECT3DDEVICE9 device;
1082 IDirect3DIndexBuffer9* d3d_ibuff;
1083 HRESULT res;
1084 void* locked_memory;
1085
1086 /* There's just no point */
1087 if (is_legacy_card()) {
1088 ALLEGRO_WARN("Cannot create index buffer for a legacy card.\n");
1089 return false;
1090 }
1091
1092 device = al_get_d3d_device(al_get_current_display());
1093
1094 res = device->CreateIndexBuffer(num_indices * buf->index_size, !(flags & ALLEGRO_PRIM_BUFFER_READWRITE) ? D3DUSAGE_WRITEONLY : 0,
1095 buf->index_size == 4 ? D3DFMT_INDEX32 : D3DFMT_INDEX16, D3DPOOL_MANAGED, &d3d_ibuff, 0);
1096 if (res != D3D_OK) {
1097 ALLEGRO_WARN("CreateIndexBuffer failed: %ld.\n", res);
1098 return false;
1099 }
1100
1101 if (initial_data != NULL) {
1102 d3d_ibuff->Lock(0, 0, &locked_memory, 0);
1103 memcpy(locked_memory, initial_data, num_indices * buf->index_size);
1104 d3d_ibuff->Unlock();
1105 }
1106
1107 buf->common.handle = (uintptr_t)d3d_ibuff;
1108
1109 return true;
1110 #else
1111 (void)buf;
1112 (void)initial_data;
1113 (void)num_indices;
1114 (void)flags;
1115
1116 return false;
1117 #endif
1118 }
1119
_al_destroy_vertex_buffer_directx(ALLEGRO_VERTEX_BUFFER * buf)1120 void _al_destroy_vertex_buffer_directx(ALLEGRO_VERTEX_BUFFER* buf)
1121 {
1122 #ifdef ALLEGRO_CFG_D3D
1123 ((IDirect3DVertexBuffer9*)buf->common.handle)->Release();
1124 #else
1125 (void)buf;
1126 #endif
1127 }
1128
_al_destroy_index_buffer_directx(ALLEGRO_INDEX_BUFFER * buf)1129 void _al_destroy_index_buffer_directx(ALLEGRO_INDEX_BUFFER* buf)
1130 {
1131 #ifdef ALLEGRO_CFG_D3D
1132 ((IDirect3DIndexBuffer9*)buf->common.handle)->Release();
1133 #else
1134 (void)buf;
1135 #endif
1136 }
1137
_al_lock_vertex_buffer_directx(ALLEGRO_VERTEX_BUFFER * buf)1138 void* _al_lock_vertex_buffer_directx(ALLEGRO_VERTEX_BUFFER* buf)
1139 {
1140 #ifdef ALLEGRO_CFG_D3D
1141 DWORD flags = buf->common.lock_flags == ALLEGRO_LOCK_READONLY ? D3DLOCK_READONLY : 0;
1142 HRESULT res;
1143
1144 res = ((IDirect3DVertexBuffer9*)buf->common.handle)->Lock((UINT)buf->common.lock_offset, (UINT)buf->common.lock_length, &buf->common.locked_memory, flags);
1145 if (res != D3D_OK) {
1146 ALLEGRO_WARN("Locking vertex buffer failed: %ld.\n", res);
1147 return 0;
1148 }
1149
1150 return buf->common.locked_memory;
1151 #else
1152 (void)buf;
1153
1154 return 0;
1155 #endif
1156 }
1157
_al_lock_index_buffer_directx(ALLEGRO_INDEX_BUFFER * buf)1158 void* _al_lock_index_buffer_directx(ALLEGRO_INDEX_BUFFER* buf)
1159 {
1160 #ifdef ALLEGRO_CFG_D3D
1161 DWORD flags = buf->common.lock_flags == ALLEGRO_LOCK_READONLY ? D3DLOCK_READONLY : 0;
1162 HRESULT res;
1163
1164 res = ((IDirect3DIndexBuffer9*)buf->common.handle)->Lock((UINT)buf->common.lock_offset, (UINT)buf->common.lock_length, &buf->common.locked_memory, flags);
1165
1166 if (res != D3D_OK) {
1167 ALLEGRO_WARN("Locking index buffer failed: %ld.\n", res);
1168 return 0;
1169 }
1170
1171 return buf->common.locked_memory;
1172 #else
1173 (void)buf;
1174
1175 return 0;
1176 #endif
1177 }
1178
_al_unlock_vertex_buffer_directx(ALLEGRO_VERTEX_BUFFER * buf)1179 void _al_unlock_vertex_buffer_directx(ALLEGRO_VERTEX_BUFFER* buf)
1180 {
1181 #ifdef ALLEGRO_CFG_D3D
1182 ((IDirect3DVertexBuffer9*)buf->common.handle)->Unlock();
1183 #else
1184 (void)buf;
1185 #endif
1186 }
1187
_al_unlock_index_buffer_directx(ALLEGRO_INDEX_BUFFER * buf)1188 void _al_unlock_index_buffer_directx(ALLEGRO_INDEX_BUFFER* buf)
1189 {
1190 #ifdef ALLEGRO_CFG_D3D
1191 ((IDirect3DIndexBuffer9*)buf->common.handle)->Unlock();
1192 #else
1193 (void)buf;
1194 #endif
1195 }
1196