1 /* 2 * Copyright 2002 Lionel Ulmer 3 * Copyright 2002-2005 Jason Edmeades 4 * Copyright 2003-2004 Raphael Junqueira 5 * Copyright 2004 Christian Costa 6 * Copyright 2005 Oliver Stieber 7 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers 8 * Copyright 2006-2008 Henri Verbeet 9 * Copyright 2007 Andrew Riedi 10 * Copyright 2009-2011 Henri Verbeet for CodeWeavers 11 * 12 * This library is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU Lesser General Public 14 * License as published by the Free Software Foundation; either 15 * version 2.1 of the License, or (at your option) any later version. 16 * 17 * This library is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * Lesser General Public License for more details. 21 * 22 * You should have received a copy of the GNU Lesser General Public 23 * License along with this library; if not, write to the Free Software 24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 25 */ 26 27 #include "config.h" 28 #include "wine/port.h" 29 30 #include <stdio.h> 31 #ifdef HAVE_FLOAT_H 32 # include <float.h> 33 #endif 34 35 #include "wined3d_private.h" 36 37 WINE_DEFAULT_DEBUG_CHANNEL(d3d); 38 WINE_DECLARE_DEBUG_CHANNEL(winediag); 39 40 /* Define the default light parameters as specified by MSDN. */ 41 const struct wined3d_light WINED3D_default_light = 42 { 43 WINED3D_LIGHT_DIRECTIONAL, /* Type */ 44 { 1.0f, 1.0f, 1.0f, 0.0f }, /* Diffuse r,g,b,a */ 45 { 0.0f, 0.0f, 0.0f, 0.0f }, /* Specular r,g,b,a */ 46 { 0.0f, 0.0f, 0.0f, 0.0f }, /* Ambient r,g,b,a, */ 47 { 0.0f, 0.0f, 0.0f }, /* Position x,y,z */ 48 { 0.0f, 0.0f, 1.0f }, /* Direction x,y,z */ 49 0.0f, /* Range */ 50 0.0f, /* Falloff */ 51 0.0f, 0.0f, 0.0f, /* Attenuation 0,1,2 */ 52 0.0f, /* Theta */ 53 0.0f /* Phi */ 54 }; 55 56 /* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these 57 * actually have the same values in GL and D3D. */ 58 GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) 59 { 60 switch (primitive_type) 61 { 62 case WINED3D_PT_POINTLIST: 63 return GL_POINTS; 64 65 case WINED3D_PT_LINELIST: 66 return GL_LINES; 67 68 case WINED3D_PT_LINESTRIP: 69 return GL_LINE_STRIP; 70 71 case WINED3D_PT_TRIANGLELIST: 72 return GL_TRIANGLES; 73 74 case WINED3D_PT_TRIANGLESTRIP: 75 return GL_TRIANGLE_STRIP; 76 77 case WINED3D_PT_TRIANGLEFAN: 78 return GL_TRIANGLE_FAN; 79 80 case WINED3D_PT_LINELIST_ADJ: 81 return GL_LINES_ADJACENCY_ARB; 82 83 case WINED3D_PT_LINESTRIP_ADJ: 84 return GL_LINE_STRIP_ADJACENCY_ARB; 85 86 case WINED3D_PT_TRIANGLELIST_ADJ: 87 return GL_TRIANGLES_ADJACENCY_ARB; 88 89 case WINED3D_PT_TRIANGLESTRIP_ADJ: 90 return GL_TRIANGLE_STRIP_ADJACENCY_ARB; 91 92 case WINED3D_PT_PATCH: 93 return GL_PATCHES; 94 95 default: 96 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); 97 case WINED3D_PT_UNDEFINED: 98 return ~0u; 99 } 100 } 101 102 enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) 103 { 104 switch (primitive_type) 105 { 106 case GL_POINTS: 107 return WINED3D_PT_POINTLIST; 108 109 case GL_LINES: 110 return WINED3D_PT_LINELIST; 111 112 case GL_LINE_STRIP: 113 return WINED3D_PT_LINESTRIP; 114 115 case GL_TRIANGLES: 116 return WINED3D_PT_TRIANGLELIST; 117 118 case GL_TRIANGLE_STRIP: 119 return WINED3D_PT_TRIANGLESTRIP; 120 121 case GL_TRIANGLE_FAN: 122 return WINED3D_PT_TRIANGLEFAN; 123 124 case GL_LINES_ADJACENCY_ARB: 125 return WINED3D_PT_LINELIST_ADJ; 126 127 case GL_LINE_STRIP_ADJACENCY_ARB: 128 return WINED3D_PT_LINESTRIP_ADJ; 129 130 case GL_TRIANGLES_ADJACENCY_ARB: 131 return WINED3D_PT_TRIANGLELIST_ADJ; 132 133 case GL_TRIANGLE_STRIP_ADJACENCY_ARB: 134 return WINED3D_PT_TRIANGLESTRIP_ADJ; 135 136 case GL_PATCHES: 137 return WINED3D_PT_PATCH; 138 139 default: 140 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); 141 case ~0u: 142 return WINED3D_PT_UNDEFINED; 143 } 144 } 145 146 BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *context) 147 { 148 struct wined3d_context **new_array; 149 150 TRACE("Adding context %p.\n", context); 151 152 if (!(new_array = heap_realloc(device->contexts, sizeof(*new_array) * (device->context_count + 1)))) 153 { 154 ERR("Failed to grow the context array.\n"); 155 return FALSE; 156 } 157 158 new_array[device->context_count++] = context; 159 device->contexts = new_array; 160 return TRUE; 161 } 162 163 void device_context_remove(struct wined3d_device *device, struct wined3d_context *context) 164 { 165 struct wined3d_context **new_array; 166 BOOL found = FALSE; 167 UINT i; 168 169 TRACE("Removing context %p.\n", context); 170 171 for (i = 0; i < device->context_count; ++i) 172 { 173 if (device->contexts[i] == context) 174 { 175 found = TRUE; 176 break; 177 } 178 } 179 180 if (!found) 181 { 182 ERR("Context %p doesn't exist in context array.\n", context); 183 return; 184 } 185 186 if (!--device->context_count) 187 { 188 heap_free(device->contexts); 189 device->contexts = NULL; 190 return; 191 } 192 193 memmove(&device->contexts[i], &device->contexts[i + 1], (device->context_count - i) * sizeof(*device->contexts)); 194 if (!(new_array = heap_realloc(device->contexts, device->context_count * sizeof(*device->contexts)))) 195 { 196 ERR("Failed to shrink context array. Oh well.\n"); 197 return; 198 } 199 200 device->contexts = new_array; 201 } 202 203 static BOOL is_full_clear(const struct wined3d_texture *texture, unsigned int sub_resource_idx, 204 const RECT *draw_rect, const RECT *clear_rect) 205 { 206 unsigned int width, height, level; 207 208 level = sub_resource_idx % texture->level_count; 209 width = wined3d_texture_get_level_width(texture, level); 210 height = wined3d_texture_get_level_height(texture, level); 211 212 /* partial draw rect */ 213 if (draw_rect->left || draw_rect->top || draw_rect->right < width || draw_rect->bottom < height) 214 return FALSE; 215 216 /* partial clear rect */ 217 if (clear_rect && (clear_rect->left > 0 || clear_rect->top > 0 218 || clear_rect->right < width || clear_rect->bottom < height)) 219 return FALSE; 220 221 return TRUE; 222 } 223 224 void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, const struct wined3d_fb_state *fb, 225 UINT rect_count, const RECT *clear_rect, const RECT *draw_rect, DWORD flags, const struct wined3d_color *color, 226 float depth, DWORD stencil) 227 { 228 struct wined3d_rendertarget_view *rtv = rt_count ? fb->render_targets[0] : NULL; 229 struct wined3d_rendertarget_view *dsv = fb->depth_stencil; 230 const struct wined3d_state *state = &device->cs->state; 231 struct wined3d_texture *depth_stencil = NULL; 232 const struct wined3d_gl_info *gl_info; 233 struct wined3d_texture *target = NULL; 234 UINT drawable_width, drawable_height; 235 struct wined3d_color corrected_color; 236 struct wined3d_context *context; 237 GLbitfield clear_mask = 0; 238 BOOL render_offscreen; 239 unsigned int i; 240 241 if (rtv && rtv->resource->type != WINED3D_RTYPE_BUFFER) 242 { 243 target = texture_from_resource(rtv->resource); 244 context = context_acquire(device, target, rtv->sub_resource_idx); 245 } 246 else 247 { 248 context = context_acquire(device, NULL, 0); 249 } 250 251 if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER) 252 depth_stencil = texture_from_resource(dsv->resource); 253 254 if (!context->valid) 255 { 256 context_release(context); 257 WARN("Invalid context, skipping clear.\n"); 258 return; 259 } 260 gl_info = context->gl_info; 261 262 /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the 263 * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true 264 * for the cleared parts, and the untouched parts. 265 * 266 * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten 267 * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set 268 * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother 269 * checking all this if the dest surface is in the drawable anyway. */ 270 for (i = 0; i < rt_count; ++i) 271 { 272 struct wined3d_rendertarget_view *rtv = fb->render_targets[i]; 273 274 if (rtv && rtv->format->id != WINED3DFMT_NULL) 275 { 276 struct wined3d_texture *rt = wined3d_texture_from_resource(rtv->resource); 277 278 if (flags & WINED3DCLEAR_TARGET && !is_full_clear(rt, rtv->sub_resource_idx, 279 draw_rect, rect_count ? clear_rect : NULL)) 280 wined3d_texture_load_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding); 281 else 282 wined3d_texture_prepare_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding); 283 } 284 } 285 286 if (target) 287 { 288 render_offscreen = context->render_offscreen; 289 wined3d_rendertarget_view_get_drawable_size(rtv, context, &drawable_width, &drawable_height); 290 } 291 else 292 { 293 unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->level_count; 294 295 render_offscreen = TRUE; 296 drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil, ds_level); 297 drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil, ds_level); 298 } 299 300 if (depth_stencil) 301 { 302 DWORD ds_location = render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE; 303 struct wined3d_texture *ds = wined3d_texture_from_resource(dsv->resource); 304 305 if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) 306 && !is_full_clear(ds, dsv->sub_resource_idx, draw_rect, rect_count ? clear_rect : NULL)) 307 wined3d_texture_load_location(ds, dsv->sub_resource_idx, context, ds_location); 308 else 309 wined3d_texture_prepare_location(ds, dsv->sub_resource_idx, context, ds_location); 310 311 if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) 312 { 313 wined3d_texture_validate_location(ds, dsv->sub_resource_idx, ds_location); 314 wined3d_texture_invalidate_location(ds, dsv->sub_resource_idx, ~ds_location); 315 } 316 } 317 318 if (!context_apply_clear_state(context, state, rt_count, fb)) 319 { 320 context_release(context); 321 WARN("Failed to apply clear state, skipping clear.\n"); 322 return; 323 } 324 325 /* Only set the values up once, as they are not changing. */ 326 if (flags & WINED3DCLEAR_STENCIL) 327 { 328 if (gl_info->supported[EXT_STENCIL_TWO_SIDE]) 329 { 330 gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); 331 context_invalidate_state(context, STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE)); 332 } 333 gl_info->gl_ops.gl.p_glStencilMask(~0U); 334 context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK)); 335 gl_info->gl_ops.gl.p_glClearStencil(stencil); 336 checkGLcall("glClearStencil"); 337 clear_mask = clear_mask | GL_STENCIL_BUFFER_BIT; 338 } 339 340 if (flags & WINED3DCLEAR_ZBUFFER) 341 { 342 gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE); 343 context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZWRITEENABLE)); 344 gl_info->gl_ops.gl.p_glClearDepth(depth); 345 checkGLcall("glClearDepth"); 346 clear_mask = clear_mask | GL_DEPTH_BUFFER_BIT; 347 } 348 349 if (flags & WINED3DCLEAR_TARGET) 350 { 351 for (i = 0; i < rt_count; ++i) 352 { 353 struct wined3d_rendertarget_view *rtv = fb->render_targets[i]; 354 struct wined3d_texture *texture; 355 356 if (!rtv) 357 continue; 358 359 if (rtv->resource->type == WINED3D_RTYPE_BUFFER) 360 { 361 FIXME("Not supported on buffer resources.\n"); 362 continue; 363 } 364 365 texture = texture_from_resource(rtv->resource); 366 wined3d_texture_validate_location(texture, rtv->sub_resource_idx, rtv->resource->draw_binding); 367 wined3d_texture_invalidate_location(texture, rtv->sub_resource_idx, ~rtv->resource->draw_binding); 368 } 369 370 if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, state, fb)) 371 { 372 if (rt_count > 1) 373 WARN("Clearing multiple sRGB render targets with no GL_ARB_framebuffer_sRGB " 374 "support, this might cause graphical issues.\n"); 375 376 corrected_color.r = color->r < wined3d_srgb_const1[0] 377 ? color->r * wined3d_srgb_const0[3] 378 : pow(color->r, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] 379 - wined3d_srgb_const0[2]; 380 corrected_color.r = min(max(corrected_color.r, 0.0f), 1.0f); 381 corrected_color.g = color->g < wined3d_srgb_const1[0] 382 ? color->g * wined3d_srgb_const0[3] 383 : pow(color->g, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] 384 - wined3d_srgb_const0[2]; 385 corrected_color.g = min(max(corrected_color.g, 0.0f), 1.0f); 386 corrected_color.b = color->b < wined3d_srgb_const1[0] 387 ? color->b * wined3d_srgb_const0[3] 388 : pow(color->b, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] 389 - wined3d_srgb_const0[2]; 390 corrected_color.b = min(max(corrected_color.b, 0.0f), 1.0f); 391 color = &corrected_color; 392 } 393 394 gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 395 for (i = 0; i < MAX_RENDER_TARGETS; ++i) 396 context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITE(i))); 397 gl_info->gl_ops.gl.p_glClearColor(color->r, color->g, color->b, color->a); 398 checkGLcall("glClearColor"); 399 clear_mask = clear_mask | GL_COLOR_BUFFER_BIT; 400 } 401 402 if (!rect_count) 403 { 404 if (render_offscreen) 405 { 406 gl_info->gl_ops.gl.p_glScissor(draw_rect->left, draw_rect->top, 407 draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top); 408 } 409 else 410 { 411 gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom, 412 draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top); 413 } 414 gl_info->gl_ops.gl.p_glClear(clear_mask); 415 } 416 else 417 { 418 RECT current_rect; 419 420 /* Now process each rect in turn. */ 421 for (i = 0; i < rect_count; ++i) 422 { 423 /* Note that GL uses lower left, width/height. */ 424 IntersectRect(¤t_rect, draw_rect, &clear_rect[i]); 425 426 TRACE("clear_rect[%u] %s, current_rect %s.\n", i, 427 wine_dbgstr_rect(&clear_rect[i]), 428 wine_dbgstr_rect(¤t_rect)); 429 430 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently. 431 * The rectangle is not cleared, no error is returned, but further rectangles are 432 * still cleared if they are valid. */ 433 if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom) 434 { 435 TRACE("Rectangle with negative dimensions, ignoring.\n"); 436 continue; 437 } 438 439 if (render_offscreen) 440 { 441 gl_info->gl_ops.gl.p_glScissor(current_rect.left, current_rect.top, 442 current_rect.right - current_rect.left, current_rect.bottom - current_rect.top); 443 } 444 else 445 { 446 gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom, 447 current_rect.right - current_rect.left, current_rect.bottom - current_rect.top); 448 } 449 gl_info->gl_ops.gl.p_glClear(clear_mask); 450 } 451 } 452 context->scissor_rect_count = WINED3D_MAX_VIEWPORTS; 453 checkGLcall("clear"); 454 455 if (flags & WINED3DCLEAR_TARGET && target->swapchain && target->swapchain->front_buffer == target) 456 gl_info->gl_ops.gl.p_glFlush(); 457 458 context_release(context); 459 } 460 461 ULONG CDECL wined3d_device_incref(struct wined3d_device *device) 462 { 463 ULONG refcount = InterlockedIncrement(&device->ref); 464 465 TRACE("%p increasing refcount to %u.\n", device, refcount); 466 467 return refcount; 468 } 469 470 static void device_leftover_sampler(struct wine_rb_entry *entry, void *context) 471 { 472 struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry); 473 474 ERR("Leftover sampler %p.\n", sampler); 475 } 476 477 ULONG CDECL wined3d_device_decref(struct wined3d_device *device) 478 { 479 ULONG refcount = InterlockedDecrement(&device->ref); 480 481 TRACE("%p decreasing refcount to %u.\n", device, refcount); 482 483 if (!refcount) 484 { 485 UINT i; 486 487 wined3d_cs_destroy(device->cs); 488 489 if (device->recording && wined3d_stateblock_decref(device->recording)) 490 ERR("Something's still holding the recording stateblock.\n"); 491 device->recording = NULL; 492 493 state_cleanup(&device->state); 494 495 for (i = 0; i < ARRAY_SIZE(device->multistate_funcs); ++i) 496 { 497 heap_free(device->multistate_funcs[i]); 498 device->multistate_funcs[i] = NULL; 499 } 500 501 if (!list_empty(&device->resources)) 502 { 503 struct wined3d_resource *resource; 504 505 ERR("Device released with resources still bound.\n"); 506 507 LIST_FOR_EACH_ENTRY(resource, &device->resources, struct wined3d_resource, resource_list_entry) 508 { 509 ERR("Leftover resource %p with type %s (%#x).\n", 510 resource, debug_d3dresourcetype(resource->type), resource->type); 511 } 512 } 513 514 if (device->contexts) 515 ERR("Context array not freed!\n"); 516 if (device->hardwareCursor) 517 DestroyCursor(device->hardwareCursor); 518 device->hardwareCursor = 0; 519 520 wine_rb_destroy(&device->samplers, device_leftover_sampler, NULL); 521 522 wined3d_decref(device->wined3d); 523 device->wined3d = NULL; 524 heap_free(device); 525 TRACE("Freed device %p.\n", device); 526 } 527 528 return refcount; 529 } 530 531 UINT CDECL wined3d_device_get_swapchain_count(const struct wined3d_device *device) 532 { 533 TRACE("device %p.\n", device); 534 535 return device->swapchain_count; 536 } 537 538 struct wined3d_swapchain * CDECL wined3d_device_get_swapchain(const struct wined3d_device *device, UINT swapchain_idx) 539 { 540 TRACE("device %p, swapchain_idx %u.\n", device, swapchain_idx); 541 542 if (swapchain_idx >= device->swapchain_count) 543 { 544 WARN("swapchain_idx %u >= swapchain_count %u.\n", 545 swapchain_idx, device->swapchain_count); 546 return NULL; 547 } 548 549 return device->swapchains[swapchain_idx]; 550 } 551 552 static void device_load_logo(struct wined3d_device *device, const char *filename) 553 { 554 struct wined3d_color_key color_key; 555 struct wined3d_resource_desc desc; 556 HBITMAP hbm; 557 BITMAP bm; 558 HRESULT hr; 559 HDC dcb = NULL, dcs = NULL; 560 561 if (!(hbm = LoadImageA(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION))) 562 { 563 ERR_(winediag)("Failed to load logo %s.\n", wine_dbgstr_a(filename)); 564 return; 565 } 566 GetObjectA(hbm, sizeof(BITMAP), &bm); 567 568 if (!(dcb = CreateCompatibleDC(NULL))) 569 goto out; 570 SelectObject(dcb, hbm); 571 572 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 573 desc.format = WINED3DFMT_B5G6R5_UNORM; 574 desc.multisample_type = WINED3D_MULTISAMPLE_NONE; 575 desc.multisample_quality = 0; 576 desc.usage = WINED3DUSAGE_DYNAMIC; 577 desc.access = WINED3D_RESOURCE_ACCESS_GPU; 578 desc.width = bm.bmWidth; 579 desc.height = bm.bmHeight; 580 desc.depth = 1; 581 desc.size = 0; 582 if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 583 WINED3D_TEXTURE_CREATE_MAPPABLE | WINED3D_TEXTURE_CREATE_GET_DC, 584 NULL, NULL, &wined3d_null_parent_ops, &device->logo_texture))) 585 { 586 ERR("Wine logo requested, but failed to create texture, hr %#x.\n", hr); 587 goto out; 588 } 589 590 if (FAILED(hr = wined3d_texture_get_dc(device->logo_texture, 0, &dcs))) 591 { 592 wined3d_texture_decref(device->logo_texture); 593 device->logo_texture = NULL; 594 goto out; 595 } 596 BitBlt(dcs, 0, 0, bm.bmWidth, bm.bmHeight, dcb, 0, 0, SRCCOPY); 597 wined3d_texture_release_dc(device->logo_texture, 0, dcs); 598 599 color_key.color_space_low_value = 0; 600 color_key.color_space_high_value = 0; 601 wined3d_texture_set_color_key(device->logo_texture, WINED3D_CKEY_SRC_BLT, &color_key); 602 603 out: 604 if (dcb) DeleteDC(dcb); 605 if (hbm) DeleteObject(hbm); 606 } 607 608 /* Context activation is done by the caller. */ 609 static void create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) 610 { 611 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; 612 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; 613 struct wined3d_dummy_textures *textures = &device->dummy_textures; 614 unsigned int i; 615 DWORD color; 616 617 if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR) 618 color = 0x000000ff; 619 else 620 color = 0x00000000; 621 622 /* Under DirectX you can sample even if no texture is bound, whereas 623 * OpenGL will only allow that when a valid texture is bound. 624 * We emulate this by creating dummy textures and binding them 625 * to each texture stage when the currently set D3D texture is NULL. */ 626 context_active_texture(context, gl_info, 0); 627 628 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d); 629 TRACE("Dummy 1D texture given name %u.\n", textures->tex_1d); 630 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, textures->tex_1d); 631 gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, 1, 0, 632 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color); 633 634 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d); 635 TRACE("Dummy 2D texture given name %u.\n", textures->tex_2d); 636 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, textures->tex_2d); 637 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, 638 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color); 639 640 if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) 641 { 642 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_rect); 643 TRACE("Dummy rectangle texture given name %u.\n", textures->tex_rect); 644 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textures->tex_rect); 645 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 1, 1, 0, 646 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color); 647 } 648 649 if (gl_info->supported[EXT_TEXTURE3D]) 650 { 651 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_3d); 652 TRACE("Dummy 3D texture given name %u.\n", textures->tex_3d); 653 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, textures->tex_3d); 654 GL_EXTCALL(glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, 655 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color)); 656 } 657 658 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) 659 { 660 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_cube); 661 TRACE("Dummy cube texture given name %u.\n", textures->tex_cube); 662 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, textures->tex_cube); 663 for (i = GL_TEXTURE_CUBE_MAP_POSITIVE_X; i <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++i) 664 { 665 gl_info->gl_ops.gl.p_glTexImage2D(i, 0, GL_RGBA8, 1, 1, 0, 666 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color); 667 } 668 } 669 670 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) 671 { 672 DWORD cube_array_data[6]; 673 674 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_cube_array); 675 TRACE("Dummy cube array texture given name %u.\n", textures->tex_cube_array); 676 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures->tex_cube_array); 677 for (i = 0; i < ARRAY_SIZE(cube_array_data); ++i) 678 cube_array_data[i] = color; 679 GL_EXTCALL(glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA8, 1, 1, 6, 0, 680 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, cube_array_data)); 681 } 682 683 if (gl_info->supported[EXT_TEXTURE_ARRAY]) 684 { 685 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d_array); 686 TRACE("Dummy 1D array texture given name %u.\n", textures->tex_1d_array); 687 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY, textures->tex_1d_array); 688 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, GL_RGBA8, 1, 1, 0, 689 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color); 690 691 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_array); 692 TRACE("Dummy 2D array texture given name %u.\n", textures->tex_2d_array); 693 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_ARRAY, textures->tex_2d_array); 694 GL_EXTCALL(glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 1, 0, 695 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color)); 696 } 697 698 if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT]) 699 { 700 GLuint buffer; 701 702 GL_EXTCALL(glGenBuffers(1, &buffer)); 703 GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER, buffer)); 704 GL_EXTCALL(glBufferData(GL_TEXTURE_BUFFER, sizeof(color), &color, GL_STATIC_DRAW)); 705 GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER, 0)); 706 707 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_buffer); 708 TRACE("Dummy buffer texture given name %u.\n", textures->tex_buffer); 709 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_BUFFER, textures->tex_buffer); 710 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA8, buffer)); 711 GL_EXTCALL(glDeleteBuffers(1, &buffer)); 712 } 713 714 if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) 715 { 716 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_ms); 717 TRACE("Dummy multisample texture given name %u.\n", textures->tex_2d_ms); 718 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures->tex_2d_ms); 719 GL_EXTCALL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_TRUE)); 720 721 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_ms_array); 722 TRACE("Dummy multisample array texture given name %u.\n", textures->tex_2d_ms_array); 723 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures->tex_2d_ms_array); 724 GL_EXTCALL(glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 1, GL_RGBA8, 1, 1, 1, GL_TRUE)); 725 726 if (gl_info->supported[ARB_CLEAR_TEXTURE]) 727 { 728 GL_EXTCALL(glClearTexImage(textures->tex_2d_ms, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color)); 729 GL_EXTCALL(glClearTexImage(textures->tex_2d_ms_array, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color)); 730 } 731 else 732 { 733 WARN("ARB_clear_texture is currently required to clear dummy multisample textures.\n"); 734 } 735 } 736 737 checkGLcall("create dummy textures"); 738 739 context_bind_dummy_textures(device, context); 740 } 741 742 /* Context activation is done by the caller. */ 743 static void destroy_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) 744 { 745 struct wined3d_dummy_textures *dummy_textures = &device->dummy_textures; 746 const struct wined3d_gl_info *gl_info = context->gl_info; 747 748 if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) 749 { 750 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_ms); 751 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_ms_array); 752 } 753 754 if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT]) 755 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_buffer); 756 757 if (gl_info->supported[EXT_TEXTURE_ARRAY]) 758 { 759 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_array); 760 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d_array); 761 } 762 763 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) 764 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_cube_array); 765 766 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) 767 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_cube); 768 769 if (gl_info->supported[EXT_TEXTURE3D]) 770 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_3d); 771 772 if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) 773 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_rect); 774 775 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d); 776 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d); 777 778 checkGLcall("delete dummy textures"); 779 780 memset(dummy_textures, 0, sizeof(*dummy_textures)); 781 } 782 783 /* Context activation is done by the caller. */ 784 static void create_default_samplers(struct wined3d_device *device, struct wined3d_context *context) 785 { 786 struct wined3d_sampler_desc desc; 787 HRESULT hr; 788 789 desc.address_u = WINED3D_TADDRESS_WRAP; 790 desc.address_v = WINED3D_TADDRESS_WRAP; 791 desc.address_w = WINED3D_TADDRESS_WRAP; 792 memset(desc.border_color, 0, sizeof(desc.border_color)); 793 desc.mag_filter = WINED3D_TEXF_POINT; 794 desc.min_filter = WINED3D_TEXF_POINT; 795 desc.mip_filter = WINED3D_TEXF_NONE; 796 desc.lod_bias = 0.0f; 797 desc.min_lod = -1000.0f; 798 desc.max_lod = 1000.0f; 799 desc.mip_base_level = 0; 800 desc.max_anisotropy = 1; 801 desc.compare = FALSE; 802 desc.comparison_func = WINED3D_CMP_NEVER; 803 desc.srgb_decode = TRUE; 804 805 /* In SM4+ shaders there is a separation between resources and samplers. Some shader 806 * instructions allow access to resources without using samplers. 807 * In GLSL, resources are always accessed through sampler or image variables. The default 808 * sampler object is used to emulate the direct resource access when there is no sampler state 809 * to use. 810 */ 811 if (FAILED(hr = wined3d_sampler_create(device, &desc, NULL, &wined3d_null_parent_ops, &device->default_sampler))) 812 { 813 ERR("Failed to create default sampler, hr %#x.\n", hr); 814 device->default_sampler = NULL; 815 } 816 817 /* In D3D10+, a NULL sampler maps to the default sampler state. */ 818 desc.address_u = WINED3D_TADDRESS_CLAMP; 819 desc.address_v = WINED3D_TADDRESS_CLAMP; 820 desc.address_w = WINED3D_TADDRESS_CLAMP; 821 desc.mag_filter = WINED3D_TEXF_LINEAR; 822 desc.min_filter = WINED3D_TEXF_LINEAR; 823 desc.mip_filter = WINED3D_TEXF_LINEAR; 824 if (FAILED(hr = wined3d_sampler_create(device, &desc, NULL, &wined3d_null_parent_ops, &device->null_sampler))) 825 { 826 ERR("Failed to create null sampler, hr %#x.\n", hr); 827 device->null_sampler = NULL; 828 } 829 } 830 831 /* Context activation is done by the caller. */ 832 static void destroy_default_samplers(struct wined3d_device *device, struct wined3d_context *context) 833 { 834 wined3d_sampler_decref(device->default_sampler); 835 device->default_sampler = NULL; 836 wined3d_sampler_decref(device->null_sampler); 837 device->null_sampler = NULL; 838 } 839 840 static LONG fullscreen_style(LONG style) 841 { 842 /* Make sure the window is managed, otherwise we won't get keyboard input. */ 843 style |= WS_POPUP | WS_SYSMENU; 844 style &= ~(WS_CAPTION | WS_THICKFRAME); 845 846 return style; 847 } 848 849 static LONG fullscreen_exstyle(LONG exstyle) 850 { 851 /* Filter out window decorations. */ 852 exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE); 853 854 return exstyle; 855 } 856 857 void CDECL wined3d_device_setup_fullscreen_window(struct wined3d_device *device, HWND window, UINT w, UINT h) 858 { 859 BOOL filter_messages; 860 LONG style, exstyle; 861 862 TRACE("Setting up window %p for fullscreen mode.\n", window); 863 864 if (device->style || device->exStyle) 865 { 866 ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n", 867 window, device->style, device->exStyle); 868 } 869 870 device->style = GetWindowLongW(window, GWL_STYLE); 871 device->exStyle = GetWindowLongW(window, GWL_EXSTYLE); 872 873 style = fullscreen_style(device->style); 874 exstyle = fullscreen_exstyle(device->exStyle); 875 876 TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n", 877 device->style, device->exStyle, style, exstyle); 878 879 filter_messages = device->filter_messages; 880 device->filter_messages = TRUE; 881 882 SetWindowLongW(window, GWL_STYLE, style); 883 SetWindowLongW(window, GWL_EXSTYLE, exstyle); 884 SetWindowPos(window, HWND_TOPMOST, 0, 0, w, h, SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE); 885 886 device->filter_messages = filter_messages; 887 } 888 889 void CDECL wined3d_device_restore_fullscreen_window(struct wined3d_device *device, HWND window, 890 const RECT *window_rect) 891 { 892 unsigned int window_pos_flags = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE; 893 BOOL filter_messages; 894 LONG style, exstyle; 895 RECT rect = {0}; 896 897 if (!device->style && !device->exStyle) 898 return; 899 900 style = GetWindowLongW(window, GWL_STYLE); 901 exstyle = GetWindowLongW(window, GWL_EXSTYLE); 902 903 /* These flags are set by wined3d_device_setup_fullscreen_window, not the 904 * application, and we want to ignore them in the test below, since it's 905 * not the application's fault that they changed. Additionally, we want to 906 * preserve the current status of these flags (i.e. don't restore them) to 907 * more closely emulate the behavior of Direct3D, which leaves these flags 908 * alone when returning to windowed mode. */ 909 device->style ^= (device->style ^ style) & WS_VISIBLE; 910 device->exStyle ^= (device->exStyle ^ exstyle) & WS_EX_TOPMOST; 911 912 TRACE("Restoring window style of window %p to %08x, %08x.\n", 913 window, device->style, device->exStyle); 914 915 filter_messages = device->filter_messages; 916 device->filter_messages = TRUE; 917 918 /* Only restore the style if the application didn't modify it during the 919 * fullscreen phase. Some applications change it before calling Reset() 920 * when switching between windowed and fullscreen modes (HL2), some 921 * depend on the original style (Eve Online). */ 922 if (style == fullscreen_style(device->style) && exstyle == fullscreen_exstyle(device->exStyle)) 923 { 924 SetWindowLongW(window, GWL_STYLE, device->style); 925 SetWindowLongW(window, GWL_EXSTYLE, device->exStyle); 926 } 927 928 if (window_rect) 929 rect = *window_rect; 930 else 931 window_pos_flags |= (SWP_NOMOVE | SWP_NOSIZE); 932 SetWindowPos(window, 0, rect.left, rect.top, 933 rect.right - rect.left, rect.bottom - rect.top, window_pos_flags); 934 935 device->filter_messages = filter_messages; 936 937 /* Delete the old values. */ 938 device->style = 0; 939 device->exStyle = 0; 940 } 941 942 HRESULT CDECL wined3d_device_acquire_focus_window(struct wined3d_device *device, HWND window) 943 { 944 TRACE("device %p, window %p.\n", device, window); 945 946 if (!wined3d_register_window(window, device)) 947 { 948 ERR("Failed to register window %p.\n", window); 949 return E_FAIL; 950 } 951 952 InterlockedExchangePointer((void **)&device->focus_window, window); 953 SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 954 955 return WINED3D_OK; 956 } 957 958 void CDECL wined3d_device_release_focus_window(struct wined3d_device *device) 959 { 960 TRACE("device %p.\n", device); 961 962 if (device->focus_window) wined3d_unregister_window(device->focus_window); 963 InterlockedExchangePointer((void **)&device->focus_window, NULL); 964 } 965 966 static void device_init_swapchain_state(struct wined3d_device *device, struct wined3d_swapchain *swapchain) 967 { 968 BOOL ds_enable = swapchain->desc.enable_auto_depth_stencil; 969 unsigned int i; 970 971 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) 972 { 973 wined3d_device_set_rendertarget_view(device, i, NULL, FALSE); 974 } 975 if (device->back_buffer_view) 976 wined3d_device_set_rendertarget_view(device, 0, device->back_buffer_view, TRUE); 977 978 wined3d_device_set_depth_stencil_view(device, ds_enable ? device->auto_depth_stencil_view : NULL); 979 } 980 981 static void wined3d_device_delete_opengl_contexts_cs(void *object) 982 { 983 struct wined3d_resource *resource, *cursor; 984 struct wined3d_device *device = object; 985 struct wined3d_context *context; 986 struct wined3d_shader *shader; 987 988 LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) 989 { 990 TRACE("Unloading resource %p.\n", resource); 991 wined3d_cs_emit_unload_resource(device->cs, resource); 992 } 993 994 LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry) 995 { 996 device->shader_backend->shader_destroy(shader); 997 } 998 999 context = context_acquire(device, NULL, 0); 1000 device->blitter->ops->blitter_destroy(device->blitter, context); 1001 device->shader_backend->shader_free_private(device); 1002 destroy_dummy_textures(device, context); 1003 destroy_default_samplers(device, context); 1004 context_release(context); 1005 1006 while (device->context_count) 1007 { 1008 if (device->contexts[0]->swapchain) 1009 swapchain_destroy_contexts(device->contexts[0]->swapchain); 1010 else 1011 context_destroy(device, device->contexts[0]); 1012 } 1013 } 1014 1015 static void wined3d_device_delete_opengl_contexts(struct wined3d_device *device) 1016 { 1017 wined3d_cs_destroy_object(device->cs, wined3d_device_delete_opengl_contexts_cs, device); 1018 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); 1019 } 1020 1021 static void wined3d_device_create_primary_opengl_context_cs(void *object) 1022 { 1023 struct wined3d_device *device = object; 1024 struct wined3d_swapchain *swapchain; 1025 struct wined3d_context *context; 1026 struct wined3d_texture *target; 1027 HRESULT hr; 1028 1029 if (FAILED(hr = device->shader_backend->shader_alloc_private(device, 1030 device->adapter->vertex_pipe, device->adapter->fragment_pipe))) 1031 { 1032 ERR("Failed to allocate shader private data, hr %#x.\n", hr); 1033 return; 1034 } 1035 1036 if (!(device->blitter = wined3d_cpu_blitter_create())) 1037 { 1038 ERR("Failed to create CPU blitter.\n"); 1039 device->shader_backend->shader_free_private(device); 1040 return; 1041 } 1042 wined3d_ffp_blitter_create(&device->blitter, &device->adapter->gl_info); 1043 if (!wined3d_glsl_blitter_create(&device->blitter, device)) 1044 wined3d_arbfp_blitter_create(&device->blitter, device); 1045 wined3d_fbo_blitter_create(&device->blitter, &device->adapter->gl_info); 1046 wined3d_raw_blitter_create(&device->blitter, &device->adapter->gl_info); 1047 1048 swapchain = device->swapchains[0]; 1049 target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer; 1050 context = context_acquire(device, target, 0); 1051 create_dummy_textures(device, context); 1052 create_default_samplers(device, context); 1053 context_release(context); 1054 } 1055 1056 static HRESULT wined3d_device_create_primary_opengl_context(struct wined3d_device *device) 1057 { 1058 wined3d_cs_init_object(device->cs, wined3d_device_create_primary_opengl_context_cs, device); 1059 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); 1060 if (!device->swapchains[0]->num_contexts) 1061 return E_FAIL; 1062 1063 return WINED3D_OK; 1064 } 1065 1066 HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, 1067 struct wined3d_swapchain_desc *swapchain_desc) 1068 { 1069 static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f}; 1070 struct wined3d_swapchain *swapchain = NULL; 1071 DWORD clear_flags = 0; 1072 HRESULT hr; 1073 1074 TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc); 1075 1076 if (device->d3d_initialized) 1077 return WINED3DERR_INVALIDCALL; 1078 if (device->wined3d->flags & WINED3D_NO3D) 1079 return WINED3DERR_INVALIDCALL; 1080 1081 memset(device->fb.render_targets, 0, sizeof(device->fb.render_targets)); 1082 1083 /* Setup the implicit swapchain. This also initializes a context. */ 1084 TRACE("Creating implicit swapchain.\n"); 1085 if (FAILED(hr = device->device_parent->ops->create_swapchain(device->device_parent, 1086 swapchain_desc, &swapchain))) 1087 { 1088 WARN("Failed to create implicit swapchain.\n"); 1089 goto err_out; 1090 } 1091 1092 if (swapchain_desc->backbuffer_count && swapchain_desc->backbuffer_usage & WINED3DUSAGE_RENDERTARGET) 1093 { 1094 struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource; 1095 struct wined3d_view_desc view_desc; 1096 1097 view_desc.format_id = back_buffer->format->id; 1098 view_desc.flags = 0; 1099 view_desc.u.texture.level_idx = 0; 1100 view_desc.u.texture.level_count = 1; 1101 view_desc.u.texture.layer_idx = 0; 1102 view_desc.u.texture.layer_count = 1; 1103 if (FAILED(hr = wined3d_rendertarget_view_create(&view_desc, back_buffer, 1104 NULL, &wined3d_null_parent_ops, &device->back_buffer_view))) 1105 { 1106 ERR("Failed to create rendertarget view, hr %#x.\n", hr); 1107 goto err_out; 1108 } 1109 } 1110 1111 device->swapchain_count = 1; 1112 if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains)))) 1113 { 1114 ERR("Out of memory!\n"); 1115 goto err_out; 1116 } 1117 device->swapchains[0] = swapchain; 1118 1119 if (FAILED(hr = wined3d_device_create_primary_opengl_context(device))) 1120 goto err_out; 1121 device_init_swapchain_state(device, swapchain); 1122 1123 device->contexts[0]->last_was_rhw = 0; 1124 1125 TRACE("All defaults now set up.\n"); 1126 1127 /* Clear the screen */ 1128 if (device->back_buffer_view) 1129 clear_flags |= WINED3DCLEAR_TARGET; 1130 if (swapchain_desc->enable_auto_depth_stencil) 1131 clear_flags |= WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL; 1132 if (clear_flags) 1133 wined3d_device_clear(device, 0, NULL, clear_flags, &black, 1.0f, 0); 1134 1135 device->d3d_initialized = TRUE; 1136 1137 if (wined3d_settings.logo) 1138 device_load_logo(device, wined3d_settings.logo); 1139 return WINED3D_OK; 1140 1141 err_out: 1142 heap_free(device->swapchains); 1143 device->swapchain_count = 0; 1144 if (device->back_buffer_view) 1145 wined3d_rendertarget_view_decref(device->back_buffer_view); 1146 if (swapchain) 1147 wined3d_swapchain_decref(swapchain); 1148 1149 return hr; 1150 } 1151 1152 HRESULT CDECL wined3d_device_init_gdi(struct wined3d_device *device, 1153 struct wined3d_swapchain_desc *swapchain_desc) 1154 { 1155 struct wined3d_swapchain *swapchain = NULL; 1156 HRESULT hr; 1157 1158 TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc); 1159 1160 /* Setup the implicit swapchain */ 1161 TRACE("Creating implicit swapchain\n"); 1162 hr = device->device_parent->ops->create_swapchain(device->device_parent, 1163 swapchain_desc, &swapchain); 1164 if (FAILED(hr)) 1165 { 1166 WARN("Failed to create implicit swapchain\n"); 1167 goto err_out; 1168 } 1169 1170 device->swapchain_count = 1; 1171 if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains)))) 1172 { 1173 ERR("Out of memory!\n"); 1174 goto err_out; 1175 } 1176 device->swapchains[0] = swapchain; 1177 1178 if (!(device->blitter = wined3d_cpu_blitter_create())) 1179 { 1180 ERR("Failed to create CPU blitter.\n"); 1181 heap_free(device->swapchains); 1182 device->swapchain_count = 0; 1183 goto err_out; 1184 } 1185 1186 return WINED3D_OK; 1187 1188 err_out: 1189 wined3d_swapchain_decref(swapchain); 1190 return hr; 1191 } 1192 1193 static void device_free_sampler(struct wine_rb_entry *entry, void *context) 1194 { 1195 struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry); 1196 1197 wined3d_sampler_decref(sampler); 1198 } 1199 1200 HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) 1201 { 1202 unsigned int i; 1203 1204 TRACE("device %p.\n", device); 1205 1206 if (!device->d3d_initialized) 1207 return WINED3DERR_INVALIDCALL; 1208 1209 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); 1210 1211 if (device->logo_texture) 1212 wined3d_texture_decref(device->logo_texture); 1213 if (device->cursor_texture) 1214 wined3d_texture_decref(device->cursor_texture); 1215 1216 state_unbind_resources(&device->state); 1217 1218 wine_rb_clear(&device->samplers, device_free_sampler, NULL); 1219 1220 context_set_current(NULL); 1221 wined3d_device_delete_opengl_contexts(device); 1222 1223 if (device->fb.depth_stencil) 1224 { 1225 struct wined3d_rendertarget_view *view = device->fb.depth_stencil; 1226 1227 TRACE("Releasing depth/stencil view %p.\n", view); 1228 1229 device->fb.depth_stencil = NULL; 1230 wined3d_rendertarget_view_decref(view); 1231 } 1232 1233 if (device->auto_depth_stencil_view) 1234 { 1235 struct wined3d_rendertarget_view *view = device->auto_depth_stencil_view; 1236 1237 device->auto_depth_stencil_view = NULL; 1238 if (wined3d_rendertarget_view_decref(view)) 1239 ERR("Something's still holding the auto depth/stencil view (%p).\n", view); 1240 } 1241 1242 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) 1243 { 1244 wined3d_device_set_rendertarget_view(device, i, NULL, FALSE); 1245 } 1246 if (device->back_buffer_view) 1247 { 1248 wined3d_rendertarget_view_decref(device->back_buffer_view); 1249 device->back_buffer_view = NULL; 1250 } 1251 1252 for (i = 0; i < device->swapchain_count; ++i) 1253 { 1254 TRACE("Releasing the implicit swapchain %u.\n", i); 1255 if (wined3d_swapchain_decref(device->swapchains[i])) 1256 FIXME("Something's still holding the implicit swapchain.\n"); 1257 } 1258 1259 heap_free(device->swapchains); 1260 device->swapchains = NULL; 1261 device->swapchain_count = 0; 1262 1263 device->d3d_initialized = FALSE; 1264 1265 return WINED3D_OK; 1266 } 1267 1268 HRESULT CDECL wined3d_device_uninit_gdi(struct wined3d_device *device) 1269 { 1270 unsigned int i; 1271 1272 device->blitter->ops->blitter_destroy(device->blitter, NULL); 1273 1274 for (i = 0; i < device->swapchain_count; ++i) 1275 { 1276 TRACE("Releasing the implicit swapchain %u.\n", i); 1277 if (wined3d_swapchain_decref(device->swapchains[i])) 1278 FIXME("Something's still holding the implicit swapchain.\n"); 1279 } 1280 1281 heap_free(device->swapchains); 1282 device->swapchains = NULL; 1283 device->swapchain_count = 0; 1284 return WINED3D_OK; 1285 } 1286 1287 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw 1288 * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from 1289 * CreateDevice if D3DCREATE_MULTITHREADED is passed. 1290 * 1291 * There is no way to deactivate thread safety once it is enabled. 1292 */ 1293 void CDECL wined3d_device_set_multithreaded(struct wined3d_device *device) 1294 { 1295 TRACE("device %p.\n", device); 1296 1297 /* For now just store the flag (needed in case of ddraw). */ 1298 device->create_parms.flags |= WINED3DCREATE_MULTITHREADED; 1299 } 1300 1301 UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device *device) 1302 { 1303 /* const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; */ 1304 1305 TRACE("device %p.\n", device); 1306 1307 /* We can not acquire the context unless there is a swapchain. */ 1308 /* 1309 if (device->swapchains && gl_info->supported[NVX_GPU_MEMORY_INFO] && 1310 !wined3d_settings.emulated_textureram) 1311 { 1312 GLint vram_free_kb; 1313 UINT64 vram_free; 1314 1315 struct wined3d_context *context = context_acquire(device, NULL, 0); 1316 gl_info->gl_ops.gl.p_glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &vram_free_kb); 1317 vram_free = (UINT64)vram_free_kb * 1024; 1318 context_release(context); 1319 1320 TRACE("Total 0x%s bytes. emulation 0x%s left, driver 0x%s left.\n", 1321 wine_dbgstr_longlong(device->adapter->vram_bytes), 1322 wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used), 1323 wine_dbgstr_longlong(vram_free)); 1324 1325 vram_free = min(vram_free, device->adapter->vram_bytes - device->adapter->vram_bytes_used); 1326 return min(UINT_MAX, vram_free); 1327 } 1328 */ 1329 1330 TRACE("Emulating 0x%s bytes. 0x%s used, returning 0x%s left.\n", 1331 wine_dbgstr_longlong(device->adapter->vram_bytes), 1332 wine_dbgstr_longlong(device->adapter->vram_bytes_used), 1333 wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used)); 1334 1335 return min(UINT_MAX, device->adapter->vram_bytes - device->adapter->vram_bytes_used); 1336 } 1337 1338 void CDECL wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx, 1339 struct wined3d_buffer *buffer, UINT offset) 1340 { 1341 struct wined3d_stream_output *stream; 1342 struct wined3d_buffer *prev_buffer; 1343 1344 TRACE("device %p, idx %u, buffer %p, offset %u.\n", device, idx, buffer, offset); 1345 1346 if (idx >= WINED3D_MAX_STREAM_OUTPUT_BUFFERS) 1347 { 1348 WARN("Invalid stream output %u.\n", idx); 1349 return; 1350 } 1351 1352 stream = &device->update_state->stream_output[idx]; 1353 prev_buffer = stream->buffer; 1354 1355 if (buffer) 1356 wined3d_buffer_incref(buffer); 1357 stream->buffer = buffer; 1358 stream->offset = offset; 1359 if (!device->recording) 1360 wined3d_cs_emit_set_stream_output(device->cs, idx, buffer, offset); 1361 if (prev_buffer) 1362 wined3d_buffer_decref(prev_buffer); 1363 } 1364 1365 struct wined3d_buffer * CDECL wined3d_device_get_stream_output(struct wined3d_device *device, 1366 UINT idx, UINT *offset) 1367 { 1368 TRACE("device %p, idx %u, offset %p.\n", device, idx, offset); 1369 1370 if (idx >= WINED3D_MAX_STREAM_OUTPUT_BUFFERS) 1371 { 1372 WARN("Invalid stream output %u.\n", idx); 1373 return NULL; 1374 } 1375 1376 if (offset) 1377 *offset = device->state.stream_output[idx].offset; 1378 return device->state.stream_output[idx].buffer; 1379 } 1380 1381 HRESULT CDECL wined3d_device_set_stream_source(struct wined3d_device *device, UINT stream_idx, 1382 struct wined3d_buffer *buffer, UINT offset, UINT stride) 1383 { 1384 struct wined3d_stream_state *stream; 1385 struct wined3d_buffer *prev_buffer; 1386 1387 TRACE("device %p, stream_idx %u, buffer %p, offset %u, stride %u.\n", 1388 device, stream_idx, buffer, offset, stride); 1389 1390 if (stream_idx >= MAX_STREAMS) 1391 { 1392 WARN("Stream index %u out of range.\n", stream_idx); 1393 return WINED3DERR_INVALIDCALL; 1394 } 1395 else if (offset & 0x3) 1396 { 1397 WARN("Offset %u is not 4 byte aligned.\n", offset); 1398 return WINED3DERR_INVALIDCALL; 1399 } 1400 1401 stream = &device->update_state->streams[stream_idx]; 1402 prev_buffer = stream->buffer; 1403 1404 if (device->recording) 1405 device->recording->changed.streamSource |= 1u << stream_idx; 1406 1407 if (prev_buffer == buffer 1408 && stream->stride == stride 1409 && stream->offset == offset) 1410 { 1411 TRACE("Application is setting the old values over, nothing to do.\n"); 1412 return WINED3D_OK; 1413 } 1414 1415 stream->buffer = buffer; 1416 if (buffer) 1417 { 1418 stream->stride = stride; 1419 stream->offset = offset; 1420 wined3d_buffer_incref(buffer); 1421 } 1422 1423 if (!device->recording) 1424 wined3d_cs_emit_set_stream_source(device->cs, stream_idx, buffer, offset, stride); 1425 if (prev_buffer) 1426 wined3d_buffer_decref(prev_buffer); 1427 1428 return WINED3D_OK; 1429 } 1430 1431 HRESULT CDECL wined3d_device_get_stream_source(const struct wined3d_device *device, 1432 UINT stream_idx, struct wined3d_buffer **buffer, UINT *offset, UINT *stride) 1433 { 1434 const struct wined3d_stream_state *stream; 1435 1436 TRACE("device %p, stream_idx %u, buffer %p, offset %p, stride %p.\n", 1437 device, stream_idx, buffer, offset, stride); 1438 1439 if (stream_idx >= MAX_STREAMS) 1440 { 1441 WARN("Stream index %u out of range.\n", stream_idx); 1442 return WINED3DERR_INVALIDCALL; 1443 } 1444 1445 stream = &device->state.streams[stream_idx]; 1446 *buffer = stream->buffer; 1447 if (offset) 1448 *offset = stream->offset; 1449 *stride = stream->stride; 1450 1451 return WINED3D_OK; 1452 } 1453 1454 HRESULT CDECL wined3d_device_set_stream_source_freq(struct wined3d_device *device, UINT stream_idx, UINT divider) 1455 { 1456 struct wined3d_stream_state *stream; 1457 UINT old_flags, old_freq; 1458 1459 TRACE("device %p, stream_idx %u, divider %#x.\n", device, stream_idx, divider); 1460 1461 /* Verify input. At least in d3d9 this is invalid. */ 1462 if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && (divider & WINED3DSTREAMSOURCE_INDEXEDDATA)) 1463 { 1464 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL.\n"); 1465 return WINED3DERR_INVALIDCALL; 1466 } 1467 if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && !stream_idx) 1468 { 1469 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL.\n"); 1470 return WINED3DERR_INVALIDCALL; 1471 } 1472 if (!divider) 1473 { 1474 WARN("Divider is 0, returning D3DERR_INVALIDCALL.\n"); 1475 return WINED3DERR_INVALIDCALL; 1476 } 1477 1478 stream = &device->update_state->streams[stream_idx]; 1479 old_flags = stream->flags; 1480 old_freq = stream->frequency; 1481 1482 stream->flags = divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA); 1483 stream->frequency = divider & 0x7fffff; 1484 1485 if (device->recording) 1486 device->recording->changed.streamFreq |= 1u << stream_idx; 1487 else if (stream->frequency != old_freq || stream->flags != old_flags) 1488 wined3d_cs_emit_set_stream_source_freq(device->cs, stream_idx, stream->frequency, stream->flags); 1489 1490 return WINED3D_OK; 1491 } 1492 1493 HRESULT CDECL wined3d_device_get_stream_source_freq(const struct wined3d_device *device, 1494 UINT stream_idx, UINT *divider) 1495 { 1496 const struct wined3d_stream_state *stream; 1497 1498 TRACE("device %p, stream_idx %u, divider %p.\n", device, stream_idx, divider); 1499 1500 stream = &device->state.streams[stream_idx]; 1501 *divider = stream->flags | stream->frequency; 1502 1503 TRACE("Returning %#x.\n", *divider); 1504 1505 return WINED3D_OK; 1506 } 1507 1508 void CDECL wined3d_device_set_transform(struct wined3d_device *device, 1509 enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix) 1510 { 1511 TRACE("device %p, state %s, matrix %p.\n", 1512 device, debug_d3dtstype(d3dts), matrix); 1513 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14); 1514 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24); 1515 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34); 1516 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44); 1517 1518 /* Handle recording of state blocks. */ 1519 if (device->recording) 1520 { 1521 TRACE("Recording... not performing anything.\n"); 1522 device->recording->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f); 1523 device->update_state->transforms[d3dts] = *matrix; 1524 return; 1525 } 1526 1527 /* If the new matrix is the same as the current one, 1528 * we cut off any further processing. this seems to be a reasonable 1529 * optimization because as was noticed, some apps (warcraft3 for example) 1530 * tend towards setting the same matrix repeatedly for some reason. 1531 * 1532 * From here on we assume that the new matrix is different, wherever it matters. */ 1533 if (!memcmp(&device->state.transforms[d3dts], matrix, sizeof(*matrix))) 1534 { 1535 TRACE("The application is setting the same matrix over again.\n"); 1536 return; 1537 } 1538 1539 device->state.transforms[d3dts] = *matrix; 1540 wined3d_cs_emit_set_transform(device->cs, d3dts, matrix); 1541 } 1542 1543 void CDECL wined3d_device_get_transform(const struct wined3d_device *device, 1544 enum wined3d_transform_state state, struct wined3d_matrix *matrix) 1545 { 1546 TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix); 1547 1548 *matrix = device->state.transforms[state]; 1549 } 1550 1551 void CDECL wined3d_device_multiply_transform(struct wined3d_device *device, 1552 enum wined3d_transform_state state, const struct wined3d_matrix *matrix) 1553 { 1554 const struct wined3d_matrix *mat; 1555 struct wined3d_matrix temp; 1556 1557 TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix); 1558 1559 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code 1560 * below means it will be recorded in a state block change, but it 1561 * works regardless where it is recorded. 1562 * If this is found to be wrong, change to StateBlock. */ 1563 if (state > HIGHEST_TRANSFORMSTATE) 1564 { 1565 WARN("Unhandled transform state %#x.\n", state); 1566 return; 1567 } 1568 1569 mat = &device->update_state->transforms[state]; 1570 multiply_matrix(&temp, mat, matrix); 1571 1572 /* Apply change via set transform - will reapply to eg. lights this way. */ 1573 wined3d_device_set_transform(device, state, &temp); 1574 } 1575 1576 /* Note lights are real special cases. Although the device caps state only 1577 * e.g. 8 are supported, you can reference any indexes you want as long as 1578 * that number max are enabled at any one point in time. Therefore since the 1579 * indices can be anything, we need a hashmap of them. However, this causes 1580 * stateblock problems. When capturing the state block, I duplicate the 1581 * hashmap, but when recording, just build a chain pretty much of commands to 1582 * be replayed. */ 1583 HRESULT CDECL wined3d_device_set_light(struct wined3d_device *device, 1584 UINT light_idx, const struct wined3d_light *light) 1585 { 1586 UINT hash_idx = LIGHTMAP_HASHFUNC(light_idx); 1587 struct wined3d_light_info *object = NULL; 1588 float rho; 1589 1590 TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light); 1591 1592 /* Check the parameter range. Need for speed most wanted sets junk lights 1593 * which confuse the GL driver. */ 1594 if (!light) 1595 return WINED3DERR_INVALIDCALL; 1596 1597 switch (light->type) 1598 { 1599 case WINED3D_LIGHT_POINT: 1600 case WINED3D_LIGHT_SPOT: 1601 case WINED3D_LIGHT_GLSPOT: 1602 /* Incorrect attenuation values can cause the gl driver to crash. 1603 * Happens with Need for speed most wanted. */ 1604 if (light->attenuation0 < 0.0f || light->attenuation1 < 0.0f || light->attenuation2 < 0.0f) 1605 { 1606 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL.\n"); 1607 return WINED3DERR_INVALIDCALL; 1608 } 1609 break; 1610 1611 case WINED3D_LIGHT_DIRECTIONAL: 1612 case WINED3D_LIGHT_PARALLELPOINT: 1613 /* Ignores attenuation */ 1614 break; 1615 1616 default: 1617 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n"); 1618 return WINED3DERR_INVALIDCALL; 1619 } 1620 1621 if (!(object = wined3d_state_get_light(device->update_state, light_idx))) 1622 { 1623 TRACE("Adding new light\n"); 1624 if (!(object = heap_alloc_zero(sizeof(*object)))) 1625 return E_OUTOFMEMORY; 1626 1627 list_add_head(&device->update_state->light_map[hash_idx], &object->entry); 1628 object->glIndex = -1; 1629 object->OriginalIndex = light_idx; 1630 } 1631 1632 /* Initialize the object. */ 1633 TRACE("Light %u setting to type %#x, diffuse %s, specular %s, ambient %s, " 1634 "position {%.8e, %.8e, %.8e}, direction {%.8e, %.8e, %.8e}, " 1635 "range %.8e, falloff %.8e, theta %.8e, phi %.8e.\n", 1636 light_idx, light->type, debug_color(&light->diffuse), 1637 debug_color(&light->specular), debug_color(&light->ambient), 1638 light->position.x, light->position.y, light->position.z, 1639 light->direction.x, light->direction.y, light->direction.z, 1640 light->range, light->falloff, light->theta, light->phi); 1641 1642 /* Save away the information. */ 1643 object->OriginalParms = *light; 1644 1645 switch (light->type) 1646 { 1647 case WINED3D_LIGHT_POINT: 1648 /* Position */ 1649 object->position.x = light->position.x; 1650 object->position.y = light->position.y; 1651 object->position.z = light->position.z; 1652 object->position.w = 1.0f; 1653 object->cutoff = 180.0f; 1654 /* FIXME: Range */ 1655 break; 1656 1657 case WINED3D_LIGHT_DIRECTIONAL: 1658 /* Direction */ 1659 object->direction.x = -light->direction.x; 1660 object->direction.y = -light->direction.y; 1661 object->direction.z = -light->direction.z; 1662 object->direction.w = 0.0f; 1663 object->exponent = 0.0f; 1664 object->cutoff = 180.0f; 1665 break; 1666 1667 case WINED3D_LIGHT_SPOT: 1668 /* Position */ 1669 object->position.x = light->position.x; 1670 object->position.y = light->position.y; 1671 object->position.z = light->position.z; 1672 object->position.w = 1.0f; 1673 1674 /* Direction */ 1675 object->direction.x = light->direction.x; 1676 object->direction.y = light->direction.y; 1677 object->direction.z = light->direction.z; 1678 object->direction.w = 0.0f; 1679 1680 /* opengl-ish and d3d-ish spot lights use too different models 1681 * for the light "intensity" as a function of the angle towards 1682 * the main light direction, so we only can approximate very 1683 * roughly. However, spot lights are rather rarely used in games 1684 * (if ever used at all). Furthermore if still used, probably 1685 * nobody pays attention to such details. */ 1686 if (!light->falloff) 1687 { 1688 /* Falloff = 0 is easy, because d3d's and opengl's spot light 1689 * equations have the falloff resp. exponent parameter as an 1690 * exponent, so the spot light lighting will always be 1.0 for 1691 * both of them, and we don't have to care for the rest of the 1692 * rather complex calculation. */ 1693 object->exponent = 0.0f; 1694 } 1695 else 1696 { 1697 rho = light->theta + (light->phi - light->theta) / (2 * light->falloff); 1698 if (rho < 0.0001f) 1699 rho = 0.0001f; 1700 object->exponent = -0.3f / logf(cosf(rho / 2)); 1701 } 1702 1703 if (object->exponent > 128.0f) 1704 object->exponent = 128.0f; 1705 1706 object->cutoff = (float)(light->phi * 90 / M_PI); 1707 /* FIXME: Range */ 1708 break; 1709 1710 case WINED3D_LIGHT_PARALLELPOINT: 1711 object->position.x = light->position.x; 1712 object->position.y = light->position.y; 1713 object->position.z = light->position.z; 1714 object->position.w = 1.0f; 1715 break; 1716 1717 default: 1718 FIXME("Unrecognized light type %#x.\n", light->type); 1719 } 1720 1721 if (!device->recording) 1722 wined3d_cs_emit_set_light(device->cs, object); 1723 1724 return WINED3D_OK; 1725 } 1726 1727 HRESULT CDECL wined3d_device_get_light(const struct wined3d_device *device, 1728 UINT light_idx, struct wined3d_light *light) 1729 { 1730 struct wined3d_light_info *light_info; 1731 1732 TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light); 1733 1734 if (!(light_info = wined3d_state_get_light(&device->state, light_idx))) 1735 { 1736 TRACE("Light information requested but light not defined\n"); 1737 return WINED3DERR_INVALIDCALL; 1738 } 1739 1740 *light = light_info->OriginalParms; 1741 return WINED3D_OK; 1742 } 1743 1744 HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UINT light_idx, BOOL enable) 1745 { 1746 struct wined3d_light_info *light_info; 1747 1748 TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable); 1749 1750 /* Special case - enabling an undefined light creates one with a strict set of parameters. */ 1751 if (!(light_info = wined3d_state_get_light(device->update_state, light_idx))) 1752 { 1753 TRACE("Light enabled requested but light not defined, so defining one!\n"); 1754 wined3d_device_set_light(device, light_idx, &WINED3D_default_light); 1755 1756 if (!(light_info = wined3d_state_get_light(device->update_state, light_idx))) 1757 { 1758 FIXME("Adding default lights has failed dismally\n"); 1759 return WINED3DERR_INVALIDCALL; 1760 } 1761 } 1762 1763 wined3d_state_enable_light(device->update_state, &device->adapter->d3d_info, light_info, enable); 1764 if (!device->recording) 1765 wined3d_cs_emit_set_light_enable(device->cs, light_idx, enable); 1766 1767 return WINED3D_OK; 1768 } 1769 1770 HRESULT CDECL wined3d_device_get_light_enable(const struct wined3d_device *device, UINT light_idx, BOOL *enable) 1771 { 1772 struct wined3d_light_info *light_info; 1773 1774 TRACE("device %p, light_idx %u, enable %p.\n", device, light_idx, enable); 1775 1776 if (!(light_info = wined3d_state_get_light(&device->state, light_idx))) 1777 { 1778 TRACE("Light enabled state requested but light not defined.\n"); 1779 return WINED3DERR_INVALIDCALL; 1780 } 1781 /* true is 128 according to SetLightEnable */ 1782 *enable = light_info->enabled ? 128 : 0; 1783 return WINED3D_OK; 1784 } 1785 1786 HRESULT CDECL wined3d_device_set_clip_plane(struct wined3d_device *device, 1787 UINT plane_idx, const struct wined3d_vec4 *plane) 1788 { 1789 TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane); 1790 1791 if (plane_idx >= device->adapter->gl_info.limits.user_clip_distances) 1792 { 1793 TRACE("Application has requested clipplane this device doesn't support.\n"); 1794 return WINED3DERR_INVALIDCALL; 1795 } 1796 1797 if (device->recording) 1798 device->recording->changed.clipplane |= 1u << plane_idx; 1799 1800 if (!memcmp(&device->update_state->clip_planes[plane_idx], plane, sizeof(*plane))) 1801 { 1802 TRACE("Application is setting old values over, nothing to do.\n"); 1803 return WINED3D_OK; 1804 } 1805 1806 device->update_state->clip_planes[plane_idx] = *plane; 1807 1808 if (!device->recording) 1809 wined3d_cs_emit_set_clip_plane(device->cs, plane_idx, plane); 1810 1811 return WINED3D_OK; 1812 } 1813 1814 HRESULT CDECL wined3d_device_get_clip_plane(const struct wined3d_device *device, 1815 UINT plane_idx, struct wined3d_vec4 *plane) 1816 { 1817 TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane); 1818 1819 if (plane_idx >= device->adapter->gl_info.limits.user_clip_distances) 1820 { 1821 TRACE("Application has requested clipplane this device doesn't support.\n"); 1822 return WINED3DERR_INVALIDCALL; 1823 } 1824 1825 *plane = device->state.clip_planes[plane_idx]; 1826 1827 return WINED3D_OK; 1828 } 1829 1830 HRESULT CDECL wined3d_device_set_clip_status(struct wined3d_device *device, 1831 const struct wined3d_clip_status *clip_status) 1832 { 1833 FIXME("device %p, clip_status %p stub!\n", device, clip_status); 1834 1835 if (!clip_status) 1836 return WINED3DERR_INVALIDCALL; 1837 1838 return WINED3D_OK; 1839 } 1840 1841 HRESULT CDECL wined3d_device_get_clip_status(const struct wined3d_device *device, 1842 struct wined3d_clip_status *clip_status) 1843 { 1844 FIXME("device %p, clip_status %p stub!\n", device, clip_status); 1845 1846 if (!clip_status) 1847 return WINED3DERR_INVALIDCALL; 1848 1849 return WINED3D_OK; 1850 } 1851 1852 void CDECL wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material) 1853 { 1854 TRACE("device %p, material %p.\n", device, material); 1855 1856 device->update_state->material = *material; 1857 1858 if (device->recording) 1859 device->recording->changed.material = TRUE; 1860 else 1861 wined3d_cs_emit_set_material(device->cs, material); 1862 } 1863 1864 void CDECL wined3d_device_get_material(const struct wined3d_device *device, struct wined3d_material *material) 1865 { 1866 TRACE("device %p, material %p.\n", device, material); 1867 1868 *material = device->state.material; 1869 1870 TRACE("diffuse %s\n", debug_color(&material->diffuse)); 1871 TRACE("ambient %s\n", debug_color(&material->ambient)); 1872 TRACE("specular %s\n", debug_color(&material->specular)); 1873 TRACE("emissive %s\n", debug_color(&material->emissive)); 1874 TRACE("power %.8e.\n", material->power); 1875 } 1876 1877 void CDECL wined3d_device_set_index_buffer(struct wined3d_device *device, 1878 struct wined3d_buffer *buffer, enum wined3d_format_id format_id, unsigned int offset) 1879 { 1880 enum wined3d_format_id prev_format; 1881 struct wined3d_buffer *prev_buffer; 1882 unsigned int prev_offset; 1883 1884 TRACE("device %p, buffer %p, format %s, offset %u.\n", 1885 device, buffer, debug_d3dformat(format_id), offset); 1886 1887 prev_buffer = device->update_state->index_buffer; 1888 prev_format = device->update_state->index_format; 1889 prev_offset = device->update_state->index_offset; 1890 1891 device->update_state->index_buffer = buffer; 1892 device->update_state->index_format = format_id; 1893 device->update_state->index_offset = offset; 1894 1895 if (device->recording) 1896 device->recording->changed.indices = TRUE; 1897 1898 if (prev_buffer == buffer && prev_format == format_id && prev_offset == offset) 1899 return; 1900 1901 if (buffer) 1902 wined3d_buffer_incref(buffer); 1903 if (!device->recording) 1904 wined3d_cs_emit_set_index_buffer(device->cs, buffer, format_id, offset); 1905 if (prev_buffer) 1906 wined3d_buffer_decref(prev_buffer); 1907 } 1908 1909 struct wined3d_buffer * CDECL wined3d_device_get_index_buffer(const struct wined3d_device *device, 1910 enum wined3d_format_id *format, unsigned int *offset) 1911 { 1912 TRACE("device %p, format %p, offset %p.\n", device, format, offset); 1913 1914 *format = device->state.index_format; 1915 if (offset) 1916 *offset = device->state.index_offset; 1917 return device->state.index_buffer; 1918 } 1919 1920 void CDECL wined3d_device_set_base_vertex_index(struct wined3d_device *device, INT base_index) 1921 { 1922 TRACE("device %p, base_index %d.\n", device, base_index); 1923 1924 device->update_state->base_vertex_index = base_index; 1925 } 1926 1927 INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *device) 1928 { 1929 TRACE("device %p.\n", device); 1930 1931 return device->state.base_vertex_index; 1932 } 1933 1934 void CDECL wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count, 1935 const struct wined3d_viewport *viewports) 1936 { 1937 unsigned int i; 1938 1939 TRACE("device %p, viewport_count %u, viewports %p.\n", device, viewport_count, viewports); 1940 1941 for (i = 0; i < viewport_count; ++i) 1942 { 1943 TRACE("%u: x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n", i, viewports[i].x, viewports[i].y, 1944 viewports[i].width, viewports[i].height, viewports[i].min_z, viewports[i].max_z); 1945 } 1946 1947 if (viewport_count) 1948 memcpy(device->update_state->viewports, viewports, viewport_count * sizeof(*viewports)); 1949 else 1950 memset(device->update_state->viewports, 0, sizeof(device->update_state->viewports)); 1951 device->update_state->viewport_count = viewport_count; 1952 1953 /* Handle recording of state blocks */ 1954 if (device->recording) 1955 { 1956 TRACE("Recording... not performing anything\n"); 1957 device->recording->changed.viewport = TRUE; 1958 return; 1959 } 1960 1961 wined3d_cs_emit_set_viewports(device->cs, viewport_count, viewports); 1962 } 1963 1964 void CDECL wined3d_device_get_viewports(const struct wined3d_device *device, unsigned int *viewport_count, 1965 struct wined3d_viewport *viewports) 1966 { 1967 unsigned int count; 1968 1969 TRACE("device %p, viewport_count %p, viewports %p.\n", device, viewport_count, viewports); 1970 1971 count = viewport_count ? min(*viewport_count, device->state.viewport_count) : 1; 1972 if (count && viewports) 1973 memcpy(viewports, device->state.viewports, count * sizeof(*viewports)); 1974 if (viewport_count) 1975 *viewport_count = device->state.viewport_count; 1976 } 1977 1978 static void resolve_depth_buffer(struct wined3d_device *device) 1979 { 1980 const struct wined3d_state *state = &device->state; 1981 struct wined3d_rendertarget_view *src_view; 1982 struct wined3d_resource *dst_resource; 1983 struct wined3d_texture *dst_texture; 1984 1985 if (!(dst_texture = state->textures[0])) 1986 return; 1987 dst_resource = &dst_texture->resource; 1988 if (!(dst_resource->format_flags & WINED3DFMT_FLAG_DEPTH)) 1989 return; 1990 if (!(src_view = state->fb->depth_stencil)) 1991 return; 1992 1993 wined3d_device_resolve_sub_resource(device, dst_resource, 0, 1994 src_view->resource, src_view->sub_resource_idx, dst_resource->format->id); 1995 } 1996 1997 void CDECL wined3d_device_set_blend_state(struct wined3d_device *device, struct wined3d_blend_state *blend_state) 1998 { 1999 struct wined3d_blend_state *prev; 2000 2001 TRACE("device %p, blend_state %p.\n", device, blend_state); 2002 2003 prev = device->update_state->blend_state; 2004 if (prev == blend_state) 2005 return; 2006 2007 if (blend_state) 2008 wined3d_blend_state_incref(blend_state); 2009 device->update_state->blend_state = blend_state; 2010 wined3d_cs_emit_set_blend_state(device->cs, blend_state); 2011 if (prev) 2012 wined3d_blend_state_decref(prev); 2013 } 2014 2015 struct wined3d_blend_state * CDECL wined3d_device_get_blend_state(const struct wined3d_device *device) 2016 { 2017 TRACE("device %p.\n", device); 2018 2019 return device->state.blend_state; 2020 } 2021 2022 void CDECL wined3d_device_set_rasterizer_state(struct wined3d_device *device, 2023 struct wined3d_rasterizer_state *rasterizer_state) 2024 { 2025 struct wined3d_rasterizer_state *prev; 2026 2027 TRACE("device %p, rasterizer_state %p.\n", device, rasterizer_state); 2028 2029 prev = device->update_state->rasterizer_state; 2030 if (prev == rasterizer_state) 2031 return; 2032 2033 if (rasterizer_state) 2034 wined3d_rasterizer_state_incref(rasterizer_state); 2035 device->update_state->rasterizer_state = rasterizer_state; 2036 wined3d_cs_emit_set_rasterizer_state(device->cs, rasterizer_state); 2037 if (prev) 2038 wined3d_rasterizer_state_decref(prev); 2039 } 2040 2041 struct wined3d_rasterizer_state * CDECL wined3d_device_get_rasterizer_state(struct wined3d_device *device) 2042 { 2043 TRACE("device %p.\n", device); 2044 2045 return device->state.rasterizer_state; 2046 } 2047 2048 void CDECL wined3d_device_set_render_state(struct wined3d_device *device, 2049 enum wined3d_render_state state, DWORD value) 2050 { 2051 DWORD old_value; 2052 2053 TRACE("device %p, state %s (%#x), value %#x.\n", device, debug_d3drenderstate(state), state, value); 2054 2055 if (state > WINEHIGHEST_RENDER_STATE) 2056 { 2057 WARN("Unhandled render state %#x.\n", state); 2058 return; 2059 } 2060 2061 old_value = device->state.render_states[state]; 2062 device->update_state->render_states[state] = value; 2063 2064 /* Handle recording of state blocks. */ 2065 if (device->recording) 2066 { 2067 TRACE("Recording... not performing anything.\n"); 2068 device->recording->changed.renderState[state >> 5] |= 1u << (state & 0x1f); 2069 return; 2070 } 2071 2072 /* Compared here and not before the assignment to allow proper stateblock recording. */ 2073 if (value == old_value) 2074 TRACE("Application is setting the old value over, nothing to do.\n"); 2075 else 2076 wined3d_cs_emit_set_render_state(device->cs, state, value); 2077 2078 if (state == WINED3D_RS_POINTSIZE && value == WINED3D_RESZ_CODE) 2079 { 2080 TRACE("RESZ multisampled depth buffer resolve triggered.\n"); 2081 resolve_depth_buffer(device); 2082 } 2083 } 2084 2085 DWORD CDECL wined3d_device_get_render_state(const struct wined3d_device *device, enum wined3d_render_state state) 2086 { 2087 TRACE("device %p, state %s (%#x).\n", device, debug_d3drenderstate(state), state); 2088 2089 return device->state.render_states[state]; 2090 } 2091 2092 void CDECL wined3d_device_set_sampler_state(struct wined3d_device *device, 2093 UINT sampler_idx, enum wined3d_sampler_state state, DWORD value) 2094 { 2095 DWORD old_value; 2096 2097 TRACE("device %p, sampler_idx %u, state %s, value %#x.\n", 2098 device, sampler_idx, debug_d3dsamplerstate(state), value); 2099 2100 if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3) 2101 sampler_idx -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS); 2102 2103 if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states)) 2104 { 2105 WARN("Invalid sampler %u.\n", sampler_idx); 2106 return; /* Windows accepts overflowing this array ... we do not. */ 2107 } 2108 2109 old_value = device->state.sampler_states[sampler_idx][state]; 2110 device->update_state->sampler_states[sampler_idx][state] = value; 2111 2112 /* Handle recording of state blocks. */ 2113 if (device->recording) 2114 { 2115 TRACE("Recording... not performing anything.\n"); 2116 device->recording->changed.samplerState[sampler_idx] |= 1u << state; 2117 return; 2118 } 2119 2120 if (old_value == value) 2121 { 2122 TRACE("Application is setting the old value over, nothing to do.\n"); 2123 return; 2124 } 2125 2126 wined3d_cs_emit_set_sampler_state(device->cs, sampler_idx, state, value); 2127 } 2128 2129 DWORD CDECL wined3d_device_get_sampler_state(const struct wined3d_device *device, 2130 UINT sampler_idx, enum wined3d_sampler_state state) 2131 { 2132 TRACE("device %p, sampler_idx %u, state %s.\n", 2133 device, sampler_idx, debug_d3dsamplerstate(state)); 2134 2135 if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3) 2136 sampler_idx -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS); 2137 2138 if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states)) 2139 { 2140 WARN("Invalid sampler %u.\n", sampler_idx); 2141 return 0; /* Windows accepts overflowing this array ... we do not. */ 2142 } 2143 2144 return device->state.sampler_states[sampler_idx][state]; 2145 } 2146 2147 void CDECL wined3d_device_set_scissor_rects(struct wined3d_device *device, unsigned int rect_count, 2148 const RECT *rects) 2149 { 2150 unsigned int i; 2151 2152 TRACE("device %p, rect_count %u, rects %p.\n", device, rect_count, rects); 2153 2154 for (i = 0; i < rect_count; ++i) 2155 { 2156 TRACE("%u: %s\n", i, wine_dbgstr_rect(&rects[i])); 2157 } 2158 2159 if (device->recording) 2160 device->recording->changed.scissorRect = TRUE; 2161 2162 if (device->update_state->scissor_rect_count == rect_count 2163 && !memcmp(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects))) 2164 { 2165 TRACE("App is setting the old scissor rectangles over, nothing to do.\n"); 2166 return; 2167 } 2168 2169 if (rect_count) 2170 memcpy(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects)); 2171 else 2172 memset(device->update_state->scissor_rects, 0, sizeof(device->update_state->scissor_rects)); 2173 device->update_state->scissor_rect_count = rect_count; 2174 2175 if (device->recording) 2176 { 2177 TRACE("Recording... not performing anything.\n"); 2178 return; 2179 } 2180 2181 wined3d_cs_emit_set_scissor_rects(device->cs, rect_count, rects); 2182 } 2183 2184 void CDECL wined3d_device_get_scissor_rects(const struct wined3d_device *device, unsigned int *rect_count, RECT *rects) 2185 { 2186 unsigned int count; 2187 2188 TRACE("device %p, rect_count %p, rects %p.\n", device, rect_count, rects); 2189 2190 count = rect_count ? min(*rect_count, device->state.scissor_rect_count) : 1; 2191 if (count && rects) 2192 memcpy(rects, device->state.scissor_rects, count * sizeof(*rects)); 2193 if (rect_count) 2194 *rect_count = device->state.scissor_rect_count; 2195 } 2196 2197 void CDECL wined3d_device_set_vertex_declaration(struct wined3d_device *device, 2198 struct wined3d_vertex_declaration *declaration) 2199 { 2200 struct wined3d_vertex_declaration *prev = device->update_state->vertex_declaration; 2201 2202 TRACE("device %p, declaration %p.\n", device, declaration); 2203 2204 if (device->recording) 2205 device->recording->changed.vertexDecl = TRUE; 2206 2207 if (declaration == prev) 2208 return; 2209 2210 if (declaration) 2211 wined3d_vertex_declaration_incref(declaration); 2212 device->update_state->vertex_declaration = declaration; 2213 if (!device->recording) 2214 wined3d_cs_emit_set_vertex_declaration(device->cs, declaration); 2215 if (prev) 2216 wined3d_vertex_declaration_decref(prev); 2217 } 2218 2219 struct wined3d_vertex_declaration * CDECL wined3d_device_get_vertex_declaration(const struct wined3d_device *device) 2220 { 2221 TRACE("device %p.\n", device); 2222 2223 return device->state.vertex_declaration; 2224 } 2225 2226 void CDECL wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader) 2227 { 2228 struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX]; 2229 2230 TRACE("device %p, shader %p.\n", device, shader); 2231 2232 if (device->recording) 2233 device->recording->changed.vertexShader = TRUE; 2234 2235 if (shader == prev) 2236 return; 2237 2238 if (shader) 2239 wined3d_shader_incref(shader); 2240 device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX] = shader; 2241 if (!device->recording) 2242 wined3d_cs_emit_set_shader(device->cs, WINED3D_SHADER_TYPE_VERTEX, shader); 2243 if (prev) 2244 wined3d_shader_decref(prev); 2245 } 2246 2247 struct wined3d_shader * CDECL wined3d_device_get_vertex_shader(const struct wined3d_device *device) 2248 { 2249 TRACE("device %p.\n", device); 2250 2251 return device->state.shader[WINED3D_SHADER_TYPE_VERTEX]; 2252 } 2253 2254 static void wined3d_device_set_constant_buffer(struct wined3d_device *device, 2255 enum wined3d_shader_type type, UINT idx, struct wined3d_buffer *buffer) 2256 { 2257 struct wined3d_buffer *prev; 2258 2259 if (idx >= MAX_CONSTANT_BUFFERS) 2260 { 2261 WARN("Invalid constant buffer index %u.\n", idx); 2262 return; 2263 } 2264 2265 prev = device->update_state->cb[type][idx]; 2266 if (buffer == prev) 2267 return; 2268 2269 if (buffer) 2270 wined3d_buffer_incref(buffer); 2271 device->update_state->cb[type][idx] = buffer; 2272 if (!device->recording) 2273 wined3d_cs_emit_set_constant_buffer(device->cs, type, idx, buffer); 2274 if (prev) 2275 wined3d_buffer_decref(prev); 2276 } 2277 2278 void CDECL wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer) 2279 { 2280 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer); 2281 2282 wined3d_device_set_constant_buffer(device, WINED3D_SHADER_TYPE_VERTEX, idx, buffer); 2283 } 2284 2285 static struct wined3d_buffer *wined3d_device_get_constant_buffer(const struct wined3d_device *device, 2286 enum wined3d_shader_type shader_type, unsigned int idx) 2287 { 2288 if (idx >= MAX_CONSTANT_BUFFERS) 2289 { 2290 WARN("Invalid constant buffer index %u.\n", idx); 2291 return NULL; 2292 } 2293 2294 return device->state.cb[shader_type][idx]; 2295 } 2296 2297 struct wined3d_buffer * CDECL wined3d_device_get_vs_cb(const struct wined3d_device *device, UINT idx) 2298 { 2299 TRACE("device %p, idx %u.\n", device, idx); 2300 2301 return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_VERTEX, idx); 2302 } 2303 2304 static void wined3d_device_set_shader_resource_view(struct wined3d_device *device, 2305 enum wined3d_shader_type type, UINT idx, struct wined3d_shader_resource_view *view) 2306 { 2307 struct wined3d_shader_resource_view *prev; 2308 2309 if (idx >= MAX_SHADER_RESOURCE_VIEWS) 2310 { 2311 WARN("Invalid view index %u.\n", idx); 2312 return; 2313 } 2314 2315 prev = device->update_state->shader_resource_view[type][idx]; 2316 if (view == prev) 2317 return; 2318 2319 if (view) 2320 wined3d_shader_resource_view_incref(view); 2321 device->update_state->shader_resource_view[type][idx] = view; 2322 if (!device->recording) 2323 wined3d_cs_emit_set_shader_resource_view(device->cs, type, idx, view); 2324 if (prev) 2325 wined3d_shader_resource_view_decref(prev); 2326 } 2327 2328 void CDECL wined3d_device_set_vs_resource_view(struct wined3d_device *device, 2329 UINT idx, struct wined3d_shader_resource_view *view) 2330 { 2331 TRACE("device %p, idx %u, view %p.\n", device, idx, view); 2332 2333 wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_VERTEX, idx, view); 2334 } 2335 2336 static struct wined3d_shader_resource_view *wined3d_device_get_shader_resource_view( 2337 const struct wined3d_device *device, enum wined3d_shader_type shader_type, unsigned int idx) 2338 { 2339 if (idx >= MAX_SHADER_RESOURCE_VIEWS) 2340 { 2341 WARN("Invalid view index %u.\n", idx); 2342 return NULL; 2343 } 2344 2345 return device->state.shader_resource_view[shader_type][idx]; 2346 } 2347 2348 struct wined3d_shader_resource_view * CDECL wined3d_device_get_vs_resource_view(const struct wined3d_device *device, 2349 UINT idx) 2350 { 2351 TRACE("device %p, idx %u.\n", device, idx); 2352 2353 return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_VERTEX, idx); 2354 } 2355 2356 static void wined3d_device_set_sampler(struct wined3d_device *device, 2357 enum wined3d_shader_type type, UINT idx, struct wined3d_sampler *sampler) 2358 { 2359 struct wined3d_sampler *prev; 2360 2361 if (idx >= MAX_SAMPLER_OBJECTS) 2362 { 2363 WARN("Invalid sampler index %u.\n", idx); 2364 return; 2365 } 2366 2367 prev = device->update_state->sampler[type][idx]; 2368 if (sampler == prev) 2369 return; 2370 2371 if (sampler) 2372 wined3d_sampler_incref(sampler); 2373 device->update_state->sampler[type][idx] = sampler; 2374 if (!device->recording) 2375 wined3d_cs_emit_set_sampler(device->cs, type, idx, sampler); 2376 if (prev) 2377 wined3d_sampler_decref(prev); 2378 } 2379 2380 void CDECL wined3d_device_set_vs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler) 2381 { 2382 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler); 2383 2384 wined3d_device_set_sampler(device, WINED3D_SHADER_TYPE_VERTEX, idx, sampler); 2385 } 2386 2387 static struct wined3d_sampler *wined3d_device_get_sampler(const struct wined3d_device *device, 2388 enum wined3d_shader_type shader_type, unsigned int idx) 2389 { 2390 if (idx >= MAX_SAMPLER_OBJECTS) 2391 { 2392 WARN("Invalid sampler index %u.\n", idx); 2393 return NULL; 2394 } 2395 2396 return device->state.sampler[shader_type][idx]; 2397 } 2398 2399 struct wined3d_sampler * CDECL wined3d_device_get_vs_sampler(const struct wined3d_device *device, UINT idx) 2400 { 2401 TRACE("device %p, idx %u.\n", device, idx); 2402 2403 return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_VERTEX, idx); 2404 } 2405 2406 HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device, 2407 unsigned int start_idx, unsigned int count, const BOOL *constants) 2408 { 2409 unsigned int i; 2410 2411 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2412 device, start_idx, count, constants); 2413 2414 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B) 2415 return WINED3DERR_INVALIDCALL; 2416 2417 if (count > WINED3D_MAX_CONSTS_B - start_idx) 2418 count = WINED3D_MAX_CONSTS_B - start_idx; 2419 memcpy(&device->update_state->vs_consts_b[start_idx], constants, count * sizeof(*constants)); 2420 if (TRACE_ON(d3d)) 2421 { 2422 for (i = 0; i < count; ++i) 2423 TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]); 2424 } 2425 2426 if (device->recording) 2427 { 2428 for (i = start_idx; i < count + start_idx; ++i) 2429 device->recording->changed.vertexShaderConstantsB |= (1u << i); 2430 } 2431 else 2432 { 2433 wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_VS_B, start_idx, count, constants); 2434 } 2435 2436 return WINED3D_OK; 2437 } 2438 2439 HRESULT CDECL wined3d_device_get_vs_consts_b(const struct wined3d_device *device, 2440 unsigned int start_idx, unsigned int count, BOOL *constants) 2441 { 2442 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2443 device, start_idx, count, constants); 2444 2445 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B) 2446 return WINED3DERR_INVALIDCALL; 2447 2448 if (count > WINED3D_MAX_CONSTS_B - start_idx) 2449 count = WINED3D_MAX_CONSTS_B - start_idx; 2450 memcpy(constants, &device->state.vs_consts_b[start_idx], count * sizeof(*constants)); 2451 2452 return WINED3D_OK; 2453 } 2454 2455 HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device, 2456 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants) 2457 { 2458 unsigned int i; 2459 2460 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2461 device, start_idx, count, constants); 2462 2463 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) 2464 return WINED3DERR_INVALIDCALL; 2465 2466 if (count > WINED3D_MAX_CONSTS_I - start_idx) 2467 count = WINED3D_MAX_CONSTS_I - start_idx; 2468 memcpy(&device->update_state->vs_consts_i[start_idx], constants, count * sizeof(*constants)); 2469 if (TRACE_ON(d3d)) 2470 { 2471 for (i = 0; i < count; ++i) 2472 TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i])); 2473 } 2474 2475 if (device->recording) 2476 { 2477 for (i = start_idx; i < count + start_idx; ++i) 2478 device->recording->changed.vertexShaderConstantsI |= (1u << i); 2479 } 2480 else 2481 { 2482 wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_VS_I, start_idx, count, constants); 2483 } 2484 2485 return WINED3D_OK; 2486 } 2487 2488 HRESULT CDECL wined3d_device_get_vs_consts_i(const struct wined3d_device *device, 2489 unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants) 2490 { 2491 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2492 device, start_idx, count, constants); 2493 2494 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) 2495 return WINED3DERR_INVALIDCALL; 2496 2497 if (count > WINED3D_MAX_CONSTS_I - start_idx) 2498 count = WINED3D_MAX_CONSTS_I - start_idx; 2499 memcpy(constants, &device->state.vs_consts_i[start_idx], count * sizeof(*constants)); 2500 return WINED3D_OK; 2501 } 2502 2503 HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device, 2504 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants) 2505 { 2506 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; 2507 unsigned int i; 2508 2509 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2510 device, start_idx, count, constants); 2511 2512 if (!constants || start_idx >= d3d_info->limits.vs_uniform_count 2513 || count > d3d_info->limits.vs_uniform_count - start_idx) 2514 return WINED3DERR_INVALIDCALL; 2515 2516 memcpy(&device->update_state->vs_consts_f[start_idx], constants, count * sizeof(*constants)); 2517 if (TRACE_ON(d3d)) 2518 { 2519 for (i = 0; i < count; ++i) 2520 TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i])); 2521 } 2522 2523 if (device->recording) 2524 memset(&device->recording->changed.vs_consts_f[start_idx], 1, 2525 count * sizeof(*device->recording->changed.vs_consts_f)); 2526 else 2527 wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_VS_F, start_idx, count, constants); 2528 2529 return WINED3D_OK; 2530 } 2531 2532 HRESULT CDECL wined3d_device_get_vs_consts_f(const struct wined3d_device *device, 2533 unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants) 2534 { 2535 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; 2536 2537 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2538 device, start_idx, count, constants); 2539 2540 if (!constants || start_idx >= d3d_info->limits.vs_uniform_count 2541 || count > d3d_info->limits.vs_uniform_count - start_idx) 2542 return WINED3DERR_INVALIDCALL; 2543 2544 memcpy(constants, &device->state.vs_consts_f[start_idx], count * sizeof(*constants)); 2545 2546 return WINED3D_OK; 2547 } 2548 2549 void CDECL wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader) 2550 { 2551 struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_PIXEL]; 2552 2553 TRACE("device %p, shader %p.\n", device, shader); 2554 2555 if (device->recording) 2556 device->recording->changed.pixelShader = TRUE; 2557 2558 if (shader == prev) 2559 return; 2560 2561 if (shader) 2562 wined3d_shader_incref(shader); 2563 device->update_state->shader[WINED3D_SHADER_TYPE_PIXEL] = shader; 2564 if (!device->recording) 2565 wined3d_cs_emit_set_shader(device->cs, WINED3D_SHADER_TYPE_PIXEL, shader); 2566 if (prev) 2567 wined3d_shader_decref(prev); 2568 } 2569 2570 struct wined3d_shader * CDECL wined3d_device_get_pixel_shader(const struct wined3d_device *device) 2571 { 2572 TRACE("device %p.\n", device); 2573 2574 return device->state.shader[WINED3D_SHADER_TYPE_PIXEL]; 2575 } 2576 2577 void CDECL wined3d_device_set_ps_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer) 2578 { 2579 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer); 2580 2581 wined3d_device_set_constant_buffer(device, WINED3D_SHADER_TYPE_PIXEL, idx, buffer); 2582 } 2583 2584 struct wined3d_buffer * CDECL wined3d_device_get_ps_cb(const struct wined3d_device *device, UINT idx) 2585 { 2586 TRACE("device %p, idx %u.\n", device, idx); 2587 2588 return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_PIXEL, idx); 2589 } 2590 2591 void CDECL wined3d_device_set_ps_resource_view(struct wined3d_device *device, 2592 UINT idx, struct wined3d_shader_resource_view *view) 2593 { 2594 TRACE("device %p, idx %u, view %p.\n", device, idx, view); 2595 2596 wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_PIXEL, idx, view); 2597 } 2598 2599 struct wined3d_shader_resource_view * CDECL wined3d_device_get_ps_resource_view(const struct wined3d_device *device, 2600 UINT idx) 2601 { 2602 TRACE("device %p, idx %u.\n", device, idx); 2603 2604 return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_PIXEL, idx); 2605 } 2606 2607 void CDECL wined3d_device_set_ps_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler) 2608 { 2609 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler); 2610 2611 wined3d_device_set_sampler(device, WINED3D_SHADER_TYPE_PIXEL, idx, sampler); 2612 } 2613 2614 struct wined3d_sampler * CDECL wined3d_device_get_ps_sampler(const struct wined3d_device *device, UINT idx) 2615 { 2616 TRACE("device %p, idx %u.\n", device, idx); 2617 2618 return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_PIXEL, idx); 2619 } 2620 2621 HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device, 2622 unsigned int start_idx, unsigned int count, const BOOL *constants) 2623 { 2624 unsigned int i; 2625 2626 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2627 device, start_idx, count, constants); 2628 2629 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B) 2630 return WINED3DERR_INVALIDCALL; 2631 2632 if (count > WINED3D_MAX_CONSTS_B - start_idx) 2633 count = WINED3D_MAX_CONSTS_B - start_idx; 2634 memcpy(&device->update_state->ps_consts_b[start_idx], constants, count * sizeof(*constants)); 2635 if (TRACE_ON(d3d)) 2636 { 2637 for (i = 0; i < count; ++i) 2638 TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]); 2639 } 2640 2641 if (device->recording) 2642 { 2643 for (i = start_idx; i < count + start_idx; ++i) 2644 device->recording->changed.pixelShaderConstantsB |= (1u << i); 2645 } 2646 else 2647 { 2648 wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_PS_B, start_idx, count, constants); 2649 } 2650 2651 return WINED3D_OK; 2652 } 2653 2654 HRESULT CDECL wined3d_device_get_ps_consts_b(const struct wined3d_device *device, 2655 unsigned int start_idx, unsigned int count, BOOL *constants) 2656 { 2657 TRACE("device %p, start_idx %u, count %u,constants %p.\n", 2658 device, start_idx, count, constants); 2659 2660 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B) 2661 return WINED3DERR_INVALIDCALL; 2662 2663 if (count > WINED3D_MAX_CONSTS_B - start_idx) 2664 count = WINED3D_MAX_CONSTS_B - start_idx; 2665 memcpy(constants, &device->state.ps_consts_b[start_idx], count * sizeof(*constants)); 2666 2667 return WINED3D_OK; 2668 } 2669 2670 HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device, 2671 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants) 2672 { 2673 unsigned int i; 2674 2675 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2676 device, start_idx, count, constants); 2677 2678 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) 2679 return WINED3DERR_INVALIDCALL; 2680 2681 if (count > WINED3D_MAX_CONSTS_I - start_idx) 2682 count = WINED3D_MAX_CONSTS_I - start_idx; 2683 memcpy(&device->update_state->ps_consts_i[start_idx], constants, count * sizeof(*constants)); 2684 if (TRACE_ON(d3d)) 2685 { 2686 for (i = 0; i < count; ++i) 2687 TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i])); 2688 } 2689 2690 if (device->recording) 2691 { 2692 for (i = start_idx; i < count + start_idx; ++i) 2693 device->recording->changed.pixelShaderConstantsI |= (1u << i); 2694 } 2695 else 2696 { 2697 wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_PS_I, start_idx, count, constants); 2698 } 2699 2700 return WINED3D_OK; 2701 } 2702 2703 HRESULT CDECL wined3d_device_get_ps_consts_i(const struct wined3d_device *device, 2704 unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants) 2705 { 2706 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2707 device, start_idx, count, constants); 2708 2709 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) 2710 return WINED3DERR_INVALIDCALL; 2711 2712 if (count > WINED3D_MAX_CONSTS_I - start_idx) 2713 count = WINED3D_MAX_CONSTS_I - start_idx; 2714 memcpy(constants, &device->state.ps_consts_i[start_idx], count * sizeof(*constants)); 2715 2716 return WINED3D_OK; 2717 } 2718 2719 HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device, 2720 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants) 2721 { 2722 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; 2723 unsigned int i; 2724 2725 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2726 device, start_idx, count, constants); 2727 2728 if (!constants || start_idx >= d3d_info->limits.ps_uniform_count 2729 || count > d3d_info->limits.ps_uniform_count - start_idx) 2730 return WINED3DERR_INVALIDCALL; 2731 2732 memcpy(&device->update_state->ps_consts_f[start_idx], constants, count * sizeof(*constants)); 2733 if (TRACE_ON(d3d)) 2734 { 2735 for (i = 0; i < count; ++i) 2736 TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i])); 2737 } 2738 2739 if (device->recording) 2740 memset(&device->recording->changed.ps_consts_f[start_idx], 1, 2741 count * sizeof(*device->recording->changed.ps_consts_f)); 2742 else 2743 wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_PS_F, start_idx, count, constants); 2744 2745 return WINED3D_OK; 2746 } 2747 2748 HRESULT CDECL wined3d_device_get_ps_consts_f(const struct wined3d_device *device, 2749 unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants) 2750 { 2751 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; 2752 2753 TRACE("device %p, start_idx %u, count %u, constants %p.\n", 2754 device, start_idx, count, constants); 2755 2756 if (!constants || start_idx >= d3d_info->limits.ps_uniform_count 2757 || count > d3d_info->limits.ps_uniform_count - start_idx) 2758 return WINED3DERR_INVALIDCALL; 2759 2760 memcpy(constants, &device->state.ps_consts_f[start_idx], count * sizeof(*constants)); 2761 2762 return WINED3D_OK; 2763 } 2764 2765 void CDECL wined3d_device_set_hull_shader(struct wined3d_device *device, struct wined3d_shader *shader) 2766 { 2767 struct wined3d_shader *prev; 2768 2769 TRACE("device %p, shader %p.\n", device, shader); 2770 2771 prev = device->update_state->shader[WINED3D_SHADER_TYPE_HULL]; 2772 if (shader == prev) 2773 return; 2774 if (shader) 2775 wined3d_shader_incref(shader); 2776 device->update_state->shader[WINED3D_SHADER_TYPE_HULL] = shader; 2777 wined3d_cs_emit_set_shader(device->cs, WINED3D_SHADER_TYPE_HULL, shader); 2778 if (prev) 2779 wined3d_shader_decref(prev); 2780 } 2781 2782 struct wined3d_shader * CDECL wined3d_device_get_hull_shader(const struct wined3d_device *device) 2783 { 2784 TRACE("device %p.\n", device); 2785 2786 return device->state.shader[WINED3D_SHADER_TYPE_HULL]; 2787 } 2788 2789 void CDECL wined3d_device_set_hs_cb(struct wined3d_device *device, unsigned int idx, struct wined3d_buffer *buffer) 2790 { 2791 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer); 2792 2793 wined3d_device_set_constant_buffer(device, WINED3D_SHADER_TYPE_HULL, idx, buffer); 2794 } 2795 2796 struct wined3d_buffer * CDECL wined3d_device_get_hs_cb(const struct wined3d_device *device, unsigned int idx) 2797 { 2798 TRACE("device %p, idx %u.\n", device, idx); 2799 2800 return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_HULL, idx); 2801 } 2802 2803 void CDECL wined3d_device_set_hs_resource_view(struct wined3d_device *device, 2804 unsigned int idx, struct wined3d_shader_resource_view *view) 2805 { 2806 TRACE("device %p, idx %u, view %p.\n", device, idx, view); 2807 2808 wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_HULL, idx, view); 2809 } 2810 2811 struct wined3d_shader_resource_view * CDECL wined3d_device_get_hs_resource_view(const struct wined3d_device *device, 2812 unsigned int idx) 2813 { 2814 TRACE("device %p, idx %u.\n", device, idx); 2815 2816 return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_HULL, idx); 2817 } 2818 2819 void CDECL wined3d_device_set_hs_sampler(struct wined3d_device *device, 2820 unsigned int idx, struct wined3d_sampler *sampler) 2821 { 2822 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler); 2823 2824 wined3d_device_set_sampler(device, WINED3D_SHADER_TYPE_HULL, idx, sampler); 2825 } 2826 2827 struct wined3d_sampler * CDECL wined3d_device_get_hs_sampler(const struct wined3d_device *device, unsigned int idx) 2828 { 2829 TRACE("device %p, idx %u.\n", device, idx); 2830 2831 return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_HULL, idx); 2832 } 2833 2834 void CDECL wined3d_device_set_domain_shader(struct wined3d_device *device, struct wined3d_shader *shader) 2835 { 2836 struct wined3d_shader *prev; 2837 2838 TRACE("device %p, shader %p.\n", device, shader); 2839 2840 prev = device->update_state->shader[WINED3D_SHADER_TYPE_DOMAIN]; 2841 if (shader == prev) 2842 return; 2843 if (shader) 2844 wined3d_shader_incref(shader); 2845 device->update_state->shader[WINED3D_SHADER_TYPE_DOMAIN] = shader; 2846 wined3d_cs_emit_set_shader(device->cs, WINED3D_SHADER_TYPE_DOMAIN, shader); 2847 if (prev) 2848 wined3d_shader_decref(prev); 2849 } 2850 2851 struct wined3d_shader * CDECL wined3d_device_get_domain_shader(const struct wined3d_device *device) 2852 { 2853 TRACE("device %p.\n", device); 2854 2855 return device->state.shader[WINED3D_SHADER_TYPE_DOMAIN]; 2856 } 2857 2858 void CDECL wined3d_device_set_ds_cb(struct wined3d_device *device, unsigned int idx, struct wined3d_buffer *buffer) 2859 { 2860 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer); 2861 2862 wined3d_device_set_constant_buffer(device, WINED3D_SHADER_TYPE_DOMAIN, idx, buffer); 2863 } 2864 2865 struct wined3d_buffer * CDECL wined3d_device_get_ds_cb(const struct wined3d_device *device, unsigned int idx) 2866 { 2867 TRACE("device %p, idx %u.\n", device, idx); 2868 2869 return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_DOMAIN, idx); 2870 } 2871 2872 void CDECL wined3d_device_set_ds_resource_view(struct wined3d_device *device, 2873 unsigned int idx, struct wined3d_shader_resource_view *view) 2874 { 2875 TRACE("device %p, idx %u, view %p.\n", device, idx, view); 2876 2877 wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_DOMAIN, idx, view); 2878 } 2879 2880 struct wined3d_shader_resource_view * CDECL wined3d_device_get_ds_resource_view(const struct wined3d_device *device, 2881 unsigned int idx) 2882 { 2883 TRACE("device %p, idx %u.\n", device, idx); 2884 2885 return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_DOMAIN, idx); 2886 } 2887 2888 void CDECL wined3d_device_set_ds_sampler(struct wined3d_device *device, 2889 unsigned int idx, struct wined3d_sampler *sampler) 2890 { 2891 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler); 2892 2893 wined3d_device_set_sampler(device, WINED3D_SHADER_TYPE_DOMAIN, idx, sampler); 2894 } 2895 2896 struct wined3d_sampler * CDECL wined3d_device_get_ds_sampler(const struct wined3d_device *device, unsigned int idx) 2897 { 2898 TRACE("device %p, idx %u.\n", device, idx); 2899 2900 return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_DOMAIN, idx); 2901 } 2902 2903 void CDECL wined3d_device_set_geometry_shader(struct wined3d_device *device, struct wined3d_shader *shader) 2904 { 2905 struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_GEOMETRY]; 2906 2907 TRACE("device %p, shader %p.\n", device, shader); 2908 2909 if (device->recording || shader == prev) 2910 return; 2911 if (shader) 2912 wined3d_shader_incref(shader); 2913 device->update_state->shader[WINED3D_SHADER_TYPE_GEOMETRY] = shader; 2914 wined3d_cs_emit_set_shader(device->cs, WINED3D_SHADER_TYPE_GEOMETRY, shader); 2915 if (prev) 2916 wined3d_shader_decref(prev); 2917 } 2918 2919 struct wined3d_shader * CDECL wined3d_device_get_geometry_shader(const struct wined3d_device *device) 2920 { 2921 TRACE("device %p.\n", device); 2922 2923 return device->state.shader[WINED3D_SHADER_TYPE_GEOMETRY]; 2924 } 2925 2926 void CDECL wined3d_device_set_gs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer) 2927 { 2928 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer); 2929 2930 wined3d_device_set_constant_buffer(device, WINED3D_SHADER_TYPE_GEOMETRY, idx, buffer); 2931 } 2932 2933 struct wined3d_buffer * CDECL wined3d_device_get_gs_cb(const struct wined3d_device *device, UINT idx) 2934 { 2935 TRACE("device %p, idx %u.\n", device, idx); 2936 2937 return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_GEOMETRY, idx); 2938 } 2939 2940 void CDECL wined3d_device_set_gs_resource_view(struct wined3d_device *device, 2941 UINT idx, struct wined3d_shader_resource_view *view) 2942 { 2943 TRACE("device %p, idx %u, view %p.\n", device, idx, view); 2944 2945 wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_GEOMETRY, idx, view); 2946 } 2947 2948 struct wined3d_shader_resource_view * CDECL wined3d_device_get_gs_resource_view(const struct wined3d_device *device, 2949 UINT idx) 2950 { 2951 TRACE("device %p, idx %u.\n", device, idx); 2952 2953 return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_GEOMETRY, idx); 2954 } 2955 2956 void CDECL wined3d_device_set_gs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler) 2957 { 2958 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler); 2959 2960 wined3d_device_set_sampler(device, WINED3D_SHADER_TYPE_GEOMETRY, idx, sampler); 2961 } 2962 2963 struct wined3d_sampler * CDECL wined3d_device_get_gs_sampler(const struct wined3d_device *device, UINT idx) 2964 { 2965 TRACE("device %p, idx %u.\n", device, idx); 2966 2967 return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_GEOMETRY, idx); 2968 } 2969 2970 void CDECL wined3d_device_set_compute_shader(struct wined3d_device *device, struct wined3d_shader *shader) 2971 { 2972 struct wined3d_shader *prev; 2973 2974 TRACE("device %p, shader %p.\n", device, shader); 2975 2976 prev = device->update_state->shader[WINED3D_SHADER_TYPE_COMPUTE]; 2977 if (device->recording || shader == prev) 2978 return; 2979 if (shader) 2980 wined3d_shader_incref(shader); 2981 device->update_state->shader[WINED3D_SHADER_TYPE_COMPUTE] = shader; 2982 wined3d_cs_emit_set_shader(device->cs, WINED3D_SHADER_TYPE_COMPUTE, shader); 2983 if (prev) 2984 wined3d_shader_decref(prev); 2985 } 2986 2987 struct wined3d_shader * CDECL wined3d_device_get_compute_shader(const struct wined3d_device *device) 2988 { 2989 TRACE("device %p.\n", device); 2990 2991 return device->state.shader[WINED3D_SHADER_TYPE_COMPUTE]; 2992 } 2993 2994 void CDECL wined3d_device_set_cs_cb(struct wined3d_device *device, unsigned int idx, struct wined3d_buffer *buffer) 2995 { 2996 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer); 2997 2998 wined3d_device_set_constant_buffer(device, WINED3D_SHADER_TYPE_COMPUTE, idx, buffer); 2999 } 3000 3001 struct wined3d_buffer * CDECL wined3d_device_get_cs_cb(const struct wined3d_device *device, unsigned int idx) 3002 { 3003 TRACE("device %p, idx %u.\n", device, idx); 3004 3005 return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_COMPUTE, idx); 3006 } 3007 3008 void CDECL wined3d_device_set_cs_resource_view(struct wined3d_device *device, 3009 unsigned int idx, struct wined3d_shader_resource_view *view) 3010 { 3011 TRACE("device %p, idx %u, view %p.\n", device, idx, view); 3012 3013 wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_COMPUTE, idx, view); 3014 } 3015 3016 struct wined3d_shader_resource_view * CDECL wined3d_device_get_cs_resource_view(const struct wined3d_device *device, 3017 unsigned int idx) 3018 { 3019 TRACE("device %p, idx %u.\n", device, idx); 3020 3021 return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_COMPUTE, idx); 3022 } 3023 3024 void CDECL wined3d_device_set_cs_sampler(struct wined3d_device *device, 3025 unsigned int idx, struct wined3d_sampler *sampler) 3026 { 3027 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler); 3028 3029 wined3d_device_set_sampler(device, WINED3D_SHADER_TYPE_COMPUTE, idx, sampler); 3030 } 3031 3032 struct wined3d_sampler * CDECL wined3d_device_get_cs_sampler(const struct wined3d_device *device, unsigned int idx) 3033 { 3034 TRACE("device %p, idx %u.\n", device, idx); 3035 3036 return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_COMPUTE, idx); 3037 } 3038 3039 static void wined3d_device_set_pipeline_unordered_access_view(struct wined3d_device *device, 3040 enum wined3d_pipeline pipeline, unsigned int idx, struct wined3d_unordered_access_view *uav, 3041 unsigned int initial_count) 3042 { 3043 struct wined3d_unordered_access_view *prev; 3044 3045 if (idx >= MAX_UNORDERED_ACCESS_VIEWS) 3046 { 3047 WARN("Invalid UAV index %u.\n", idx); 3048 return; 3049 } 3050 3051 prev = device->update_state->unordered_access_view[pipeline][idx]; 3052 if (uav == prev && initial_count == ~0u) 3053 return; 3054 3055 if (uav) 3056 wined3d_unordered_access_view_incref(uav); 3057 device->update_state->unordered_access_view[pipeline][idx] = uav; 3058 if (!device->recording) 3059 wined3d_cs_emit_set_unordered_access_view(device->cs, pipeline, idx, uav, initial_count); 3060 if (prev) 3061 wined3d_unordered_access_view_decref(prev); 3062 } 3063 3064 static struct wined3d_unordered_access_view *wined3d_device_get_pipeline_unordered_access_view( 3065 const struct wined3d_device *device, enum wined3d_pipeline pipeline, unsigned int idx) 3066 { 3067 if (idx >= MAX_UNORDERED_ACCESS_VIEWS) 3068 { 3069 WARN("Invalid UAV index %u.\n", idx); 3070 return NULL; 3071 } 3072 3073 return device->state.unordered_access_view[pipeline][idx]; 3074 } 3075 3076 void CDECL wined3d_device_set_cs_uav(struct wined3d_device *device, unsigned int idx, 3077 struct wined3d_unordered_access_view *uav, unsigned int initial_count) 3078 { 3079 TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device, idx, uav, initial_count); 3080 3081 wined3d_device_set_pipeline_unordered_access_view(device, WINED3D_PIPELINE_COMPUTE, idx, uav, initial_count); 3082 } 3083 3084 struct wined3d_unordered_access_view * CDECL wined3d_device_get_cs_uav(const struct wined3d_device *device, 3085 unsigned int idx) 3086 { 3087 TRACE("device %p, idx %u.\n", device, idx); 3088 3089 return wined3d_device_get_pipeline_unordered_access_view(device, WINED3D_PIPELINE_COMPUTE, idx); 3090 } 3091 3092 void CDECL wined3d_device_set_unordered_access_view(struct wined3d_device *device, 3093 unsigned int idx, struct wined3d_unordered_access_view *uav, unsigned int initial_count) 3094 { 3095 TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device, idx, uav, initial_count); 3096 3097 wined3d_device_set_pipeline_unordered_access_view(device, WINED3D_PIPELINE_GRAPHICS, idx, uav, initial_count); 3098 } 3099 3100 struct wined3d_unordered_access_view * CDECL wined3d_device_get_unordered_access_view( 3101 const struct wined3d_device *device, unsigned int idx) 3102 { 3103 TRACE("device %p, idx %u.\n", device, idx); 3104 3105 return wined3d_device_get_pipeline_unordered_access_view(device, WINED3D_PIPELINE_GRAPHICS, idx); 3106 } 3107 3108 void CDECL wined3d_device_set_max_frame_latency(struct wined3d_device *device, unsigned int latency) 3109 { 3110 unsigned int i; 3111 3112 if (!latency) 3113 latency = 3; 3114 3115 device->max_frame_latency = latency; 3116 for (i = 0; i < device->swapchain_count; ++i) 3117 swapchain_set_max_frame_latency(device->swapchains[i], device); 3118 } 3119 3120 unsigned int CDECL wined3d_device_get_max_frame_latency(const struct wined3d_device *device) 3121 { 3122 return device->max_frame_latency; 3123 } 3124 3125 /* Context activation is done by the caller. */ 3126 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) 3127 static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount, 3128 const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD flags, 3129 DWORD DestFVF) 3130 { 3131 struct wined3d_matrix mat, proj_mat, view_mat, world_mat; 3132 struct wined3d_map_desc map_desc; 3133 struct wined3d_box box = {0}; 3134 struct wined3d_viewport vp; 3135 UINT vertex_size; 3136 unsigned int i; 3137 BYTE *dest_ptr; 3138 BOOL doClip; 3139 DWORD numTextures; 3140 HRESULT hr; 3141 3142 if (stream_info->use_map & (1u << WINED3D_FFP_NORMAL)) 3143 { 3144 WARN(" lighting state not saved yet... Some strange stuff may happen !\n"); 3145 } 3146 3147 if (!(stream_info->use_map & (1u << WINED3D_FFP_POSITION))) 3148 { 3149 ERR("Source has no position mask\n"); 3150 return WINED3DERR_INVALIDCALL; 3151 } 3152 3153 if (device->state.render_states[WINED3D_RS_CLIPPING]) 3154 { 3155 static BOOL warned = FALSE; 3156 /* 3157 * The clipping code is not quite correct. Some things need 3158 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9, 3159 * so disable clipping for now. 3160 * (The graphics in Half-Life are broken, and my processvertices 3161 * test crashes with IDirect3DDevice3) 3162 doClip = TRUE; 3163 */ 3164 doClip = FALSE; 3165 if(!warned) { 3166 warned = TRUE; 3167 FIXME("Clipping is broken and disabled for now\n"); 3168 } 3169 } 3170 else 3171 doClip = FALSE; 3172 3173 vertex_size = get_flexible_vertex_size(DestFVF); 3174 box.left = dwDestIndex * vertex_size; 3175 box.right = box.left + dwCount * vertex_size; 3176 if (FAILED(hr = wined3d_resource_map(&dest->resource, 0, &map_desc, &box, WINED3D_MAP_WRITE))) 3177 { 3178 WARN("Failed to map buffer, hr %#x.\n", hr); 3179 return hr; 3180 } 3181 dest_ptr = map_desc.data; 3182 3183 wined3d_device_get_transform(device, WINED3D_TS_VIEW, &view_mat); 3184 wined3d_device_get_transform(device, WINED3D_TS_PROJECTION, &proj_mat); 3185 wined3d_device_get_transform(device, WINED3D_TS_WORLD_MATRIX(0), &world_mat); 3186 3187 TRACE("View mat:\n"); 3188 TRACE("%.8e %.8e %.8e %.8e\n", view_mat._11, view_mat._12, view_mat._13, view_mat._14); 3189 TRACE("%.8e %.8e %.8e %.8e\n", view_mat._21, view_mat._22, view_mat._23, view_mat._24); 3190 TRACE("%.8e %.8e %.8e %.8e\n", view_mat._31, view_mat._32, view_mat._33, view_mat._34); 3191 TRACE("%.8e %.8e %.8e %.8e\n", view_mat._41, view_mat._42, view_mat._43, view_mat._44); 3192 3193 TRACE("Proj mat:\n"); 3194 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._11, proj_mat._12, proj_mat._13, proj_mat._14); 3195 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._21, proj_mat._22, proj_mat._23, proj_mat._24); 3196 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._31, proj_mat._32, proj_mat._33, proj_mat._34); 3197 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._41, proj_mat._42, proj_mat._43, proj_mat._44); 3198 3199 TRACE("World mat:\n"); 3200 TRACE("%.8e %.8e %.8e %.8e\n", world_mat._11, world_mat._12, world_mat._13, world_mat._14); 3201 TRACE("%.8e %.8e %.8e %.8e\n", world_mat._21, world_mat._22, world_mat._23, world_mat._24); 3202 TRACE("%.8e %.8e %.8e %.8e\n", world_mat._31, world_mat._32, world_mat._33, world_mat._34); 3203 TRACE("%.8e %.8e %.8e %.8e\n", world_mat._41, world_mat._42, world_mat._43, world_mat._44); 3204 3205 /* Get the viewport */ 3206 wined3d_device_get_viewports(device, NULL, &vp); 3207 TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n", 3208 vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z); 3209 3210 multiply_matrix(&mat,&view_mat,&world_mat); 3211 multiply_matrix(&mat,&proj_mat,&mat); 3212 3213 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT; 3214 3215 for (i = 0; i < dwCount; i+= 1) { 3216 unsigned int tex_index; 3217 3218 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) || 3219 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) { 3220 /* The position first */ 3221 const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_POSITION]; 3222 const float *p = (const float *)(element->data.addr + i * element->stride); 3223 float x, y, z, rhw; 3224 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]); 3225 3226 /* Multiplication with world, view and projection matrix. */ 3227 x = (p[0] * mat._11) + (p[1] * mat._21) + (p[2] * mat._31) + mat._41; 3228 y = (p[0] * mat._12) + (p[1] * mat._22) + (p[2] * mat._32) + mat._42; 3229 z = (p[0] * mat._13) + (p[1] * mat._23) + (p[2] * mat._33) + mat._43; 3230 rhw = (p[0] * mat._14) + (p[1] * mat._24) + (p[2] * mat._34) + mat._44; 3231 3232 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw); 3233 3234 /* WARNING: The following things are taken from d3d7 and were not yet checked 3235 * against d3d8 or d3d9! 3236 */ 3237 3238 /* Clipping conditions: From msdn 3239 * 3240 * A vertex is clipped if it does not match the following requirements 3241 * -rhw < x <= rhw 3242 * -rhw < y <= rhw 3243 * 0 < z <= rhw 3244 * 0 < rhw ( Not in d3d7, but tested in d3d7) 3245 * 3246 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and 3247 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked) 3248 * 3249 */ 3250 3251 if( !doClip || 3252 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) && 3253 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 3254 ( rhw > eps ) ) ) { 3255 3256 /* "Normal" viewport transformation (not clipped) 3257 * 1) The values are divided by rhw 3258 * 2) The y axis is negative, so multiply it with -1 3259 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and 3260 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ 3261 * 4) Multiply x with Width/2 and add Width/2 3262 * 5) The same for the height 3263 * 6) Add the viewpoint X and Y to the 2D coordinates and 3264 * The minimum Z value to z 3265 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W.... 3266 * 3267 * Well, basically it's simply a linear transformation into viewport 3268 * coordinates 3269 */ 3270 3271 x /= rhw; 3272 y /= rhw; 3273 z /= rhw; 3274 3275 y *= -1; 3276 3277 x *= vp.width / 2; 3278 y *= vp.height / 2; 3279 z *= vp.max_z - vp.min_z; 3280 3281 x += vp.width / 2 + vp.x; 3282 y += vp.height / 2 + vp.y; 3283 z += vp.min_z; 3284 3285 rhw = 1 / rhw; 3286 } else { 3287 /* That vertex got clipped 3288 * Contrary to OpenGL it is not dropped completely, it just 3289 * undergoes a different calculation. 3290 */ 3291 TRACE("Vertex got clipped\n"); 3292 x += rhw; 3293 y += rhw; 3294 3295 x /= 2; 3296 y /= 2; 3297 3298 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices 3299 * outside of the main vertex buffer memory. That needs some more 3300 * investigation... 3301 */ 3302 } 3303 3304 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw); 3305 3306 3307 ( (float *) dest_ptr)[0] = x; 3308 ( (float *) dest_ptr)[1] = y; 3309 ( (float *) dest_ptr)[2] = z; 3310 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */ 3311 3312 dest_ptr += 3 * sizeof(float); 3313 3314 if ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) 3315 dest_ptr += sizeof(float); 3316 } 3317 3318 if (DestFVF & WINED3DFVF_PSIZE) 3319 dest_ptr += sizeof(DWORD); 3320 3321 if (DestFVF & WINED3DFVF_NORMAL) 3322 { 3323 const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_NORMAL]; 3324 const float *normal = (const float *)(element->data.addr + i * element->stride); 3325 /* AFAIK this should go into the lighting information */ 3326 FIXME("Didn't expect the destination to have a normal\n"); 3327 copy_and_next(dest_ptr, normal, 3 * sizeof(float)); 3328 } 3329 3330 if (DestFVF & WINED3DFVF_DIFFUSE) 3331 { 3332 const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE]; 3333 const DWORD *color_d = (const DWORD *)(element->data.addr + i * element->stride); 3334 if (!(stream_info->use_map & (1u << WINED3D_FFP_DIFFUSE))) 3335 { 3336 static BOOL warned = FALSE; 3337 3338 if(!warned) { 3339 ERR("No diffuse color in source, but destination has one\n"); 3340 warned = TRUE; 3341 } 3342 3343 *( (DWORD *) dest_ptr) = 0xffffffff; 3344 dest_ptr += sizeof(DWORD); 3345 } 3346 else 3347 { 3348 copy_and_next(dest_ptr, color_d, sizeof(DWORD)); 3349 } 3350 } 3351 3352 if (DestFVF & WINED3DFVF_SPECULAR) 3353 { 3354 /* What's the color value in the feedback buffer? */ 3355 const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR]; 3356 const DWORD *color_s = (const DWORD *)(element->data.addr + i * element->stride); 3357 if (!(stream_info->use_map & (1u << WINED3D_FFP_SPECULAR))) 3358 { 3359 static BOOL warned = FALSE; 3360 3361 if(!warned) { 3362 ERR("No specular color in source, but destination has one\n"); 3363 warned = TRUE; 3364 } 3365 3366 *(DWORD *)dest_ptr = 0xff000000; 3367 dest_ptr += sizeof(DWORD); 3368 } 3369 else 3370 { 3371 copy_and_next(dest_ptr, color_s, sizeof(DWORD)); 3372 } 3373 } 3374 3375 for (tex_index = 0; tex_index < numTextures; ++tex_index) 3376 { 3377 const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index]; 3378 const float *tex_coord = (const float *)(element->data.addr + i * element->stride); 3379 if (!(stream_info->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + tex_index)))) 3380 { 3381 ERR("No source texture, but destination requests one\n"); 3382 dest_ptr += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float); 3383 } 3384 else 3385 { 3386 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float)); 3387 } 3388 } 3389 } 3390 3391 wined3d_resource_unmap(&dest->resource, 0); 3392 3393 return WINED3D_OK; 3394 } 3395 #undef copy_and_next 3396 3397 HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device, 3398 UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer, 3399 const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf) 3400 { 3401 struct wined3d_state *state = &device->state; 3402 struct wined3d_stream_info stream_info; 3403 struct wined3d_resource *resource; 3404 struct wined3d_box box = {0}; 3405 struct wined3d_shader *vs; 3406 unsigned int i; 3407 HRESULT hr; 3408 WORD map; 3409 3410 TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, " 3411 "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n", 3412 device, src_start_idx, dst_idx, vertex_count, 3413 dst_buffer, declaration, flags, dst_fvf); 3414 3415 if (declaration) 3416 FIXME("Output vertex declaration not implemented yet.\n"); 3417 3418 vs = state->shader[WINED3D_SHADER_TYPE_VERTEX]; 3419 state->shader[WINED3D_SHADER_TYPE_VERTEX] = NULL; 3420 wined3d_stream_info_from_declaration(&stream_info, state, &device->adapter->gl_info, &device->adapter->d3d_info); 3421 state->shader[WINED3D_SHADER_TYPE_VERTEX] = vs; 3422 3423 /* We can't convert FROM a VBO, and vertex buffers used to source into 3424 * process_vertices() are unlikely to ever be used for drawing. Release 3425 * VBOs in those buffers and fix up the stream_info structure. 3426 * 3427 * Also apply the start index. */ 3428 for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i) 3429 { 3430 struct wined3d_stream_info_element *e; 3431 struct wined3d_map_desc map_desc; 3432 3433 if (!(map & 1)) 3434 continue; 3435 3436 e = &stream_info.elements[i]; 3437 resource = &state->streams[e->stream_idx].buffer->resource; 3438 box.left = src_start_idx * e->stride; 3439 box.right = box.left + vertex_count * e->stride; 3440 if (FAILED(wined3d_resource_map(resource, 0, &map_desc, &box, WINED3D_MAP_READ))) 3441 ERR("Failed to map resource.\n"); 3442 e->data.buffer_object = 0; 3443 e->data.addr += (ULONG_PTR)map_desc.data; 3444 } 3445 3446 hr = process_vertices_strided(device, dst_idx, vertex_count, 3447 &stream_info, dst_buffer, flags, dst_fvf); 3448 3449 for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i) 3450 { 3451 if (!(map & 1)) 3452 continue; 3453 3454 resource = &state->streams[stream_info.elements[i].stream_idx].buffer->resource; 3455 if (FAILED(wined3d_resource_unmap(resource, 0))) 3456 ERR("Failed to unmap resource.\n"); 3457 } 3458 3459 return hr; 3460 } 3461 3462 void CDECL wined3d_device_set_texture_stage_state(struct wined3d_device *device, 3463 UINT stage, enum wined3d_texture_stage_state state, DWORD value) 3464 { 3465 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; 3466 DWORD old_value; 3467 3468 TRACE("device %p, stage %u, state %s, value %#x.\n", 3469 device, stage, debug_d3dtexturestate(state), value); 3470 3471 if (state > WINED3D_HIGHEST_TEXTURE_STATE) 3472 { 3473 WARN("Invalid state %#x passed.\n", state); 3474 return; 3475 } 3476 3477 if (stage >= d3d_info->limits.ffp_blend_stages) 3478 { 3479 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n", 3480 stage, d3d_info->limits.ffp_blend_stages - 1); 3481 return; 3482 } 3483 3484 old_value = device->update_state->texture_states[stage][state]; 3485 device->update_state->texture_states[stage][state] = value; 3486 3487 if (device->recording) 3488 { 3489 TRACE("Recording... not performing anything.\n"); 3490 device->recording->changed.textureState[stage] |= 1u << state; 3491 return; 3492 } 3493 3494 /* Checked after the assignments to allow proper stateblock recording. */ 3495 if (old_value == value) 3496 { 3497 TRACE("Application is setting the old value over, nothing to do.\n"); 3498 return; 3499 } 3500 3501 wined3d_cs_emit_set_texture_state(device->cs, stage, state, value); 3502 } 3503 3504 DWORD CDECL wined3d_device_get_texture_stage_state(const struct wined3d_device *device, 3505 UINT stage, enum wined3d_texture_stage_state state) 3506 { 3507 TRACE("device %p, stage %u, state %s.\n", 3508 device, stage, debug_d3dtexturestate(state)); 3509 3510 if (state > WINED3D_HIGHEST_TEXTURE_STATE) 3511 { 3512 WARN("Invalid state %#x passed.\n", state); 3513 return 0; 3514 } 3515 3516 return device->state.texture_states[stage][state]; 3517 } 3518 3519 HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device, 3520 UINT stage, struct wined3d_texture *texture) 3521 { 3522 struct wined3d_texture *prev; 3523 3524 TRACE("device %p, stage %u, texture %p.\n", device, stage, texture); 3525 3526 if (stage >= WINED3DVERTEXTEXTURESAMPLER0 && stage <= WINED3DVERTEXTEXTURESAMPLER3) 3527 stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS); 3528 3529 /* Windows accepts overflowing this array... we do not. */ 3530 if (stage >= ARRAY_SIZE(device->state.textures)) 3531 { 3532 WARN("Ignoring invalid stage %u.\n", stage); 3533 return WINED3D_OK; 3534 } 3535 3536 if (texture && texture->resource.usage & WINED3DUSAGE_SCRATCH) 3537 { 3538 WARN("Rejecting attempt to set scratch texture.\n"); 3539 return WINED3DERR_INVALIDCALL; 3540 } 3541 3542 if (device->recording) 3543 device->recording->changed.textures |= 1u << stage; 3544 3545 prev = device->update_state->textures[stage]; 3546 TRACE("Previous texture %p.\n", prev); 3547 3548 if (texture == prev) 3549 { 3550 TRACE("App is setting the same texture again, nothing to do.\n"); 3551 return WINED3D_OK; 3552 } 3553 3554 TRACE("Setting new texture to %p.\n", texture); 3555 device->update_state->textures[stage] = texture; 3556 3557 if (texture) 3558 wined3d_texture_incref(texture); 3559 if (!device->recording) 3560 wined3d_cs_emit_set_texture(device->cs, stage, texture); 3561 if (prev) 3562 wined3d_texture_decref(prev); 3563 3564 return WINED3D_OK; 3565 } 3566 3567 struct wined3d_texture * CDECL wined3d_device_get_texture(const struct wined3d_device *device, UINT stage) 3568 { 3569 TRACE("device %p, stage %u.\n", device, stage); 3570 3571 if (stage >= WINED3DVERTEXTEXTURESAMPLER0 && stage <= WINED3DVERTEXTEXTURESAMPLER3) 3572 stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS); 3573 3574 if (stage >= ARRAY_SIZE(device->state.textures)) 3575 { 3576 WARN("Ignoring invalid stage %u.\n", stage); 3577 return NULL; /* Windows accepts overflowing this array ... we do not. */ 3578 } 3579 3580 return device->state.textures[stage]; 3581 } 3582 3583 HRESULT CDECL wined3d_device_get_device_caps(const struct wined3d_device *device, WINED3DCAPS *caps) 3584 { 3585 HRESULT hr; 3586 3587 TRACE("device %p, caps %p.\n", device, caps); 3588 3589 hr = wined3d_get_device_caps(device->wined3d, device->adapter->ordinal, 3590 device->create_parms.device_type, caps); 3591 3592 if (SUCCEEDED(hr) && use_software_vertex_processing(device)) 3593 caps->MaxVertexBlendMatrixIndex = 255; 3594 3595 return hr; 3596 } 3597 3598 HRESULT CDECL wined3d_device_get_display_mode(const struct wined3d_device *device, UINT swapchain_idx, 3599 struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation) 3600 { 3601 struct wined3d_swapchain *swapchain; 3602 3603 TRACE("device %p, swapchain_idx %u, mode %p, rotation %p.\n", 3604 device, swapchain_idx, mode, rotation); 3605 3606 if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx))) 3607 return WINED3DERR_INVALIDCALL; 3608 3609 return wined3d_swapchain_get_display_mode(swapchain, mode, rotation); 3610 } 3611 3612 HRESULT CDECL wined3d_device_begin_stateblock(struct wined3d_device *device) 3613 { 3614 struct wined3d_stateblock *stateblock; 3615 HRESULT hr; 3616 3617 TRACE("device %p.\n", device); 3618 3619 if (device->recording) 3620 return WINED3DERR_INVALIDCALL; 3621 3622 hr = wined3d_stateblock_create(device, WINED3D_SBT_RECORDED, &stateblock); 3623 if (FAILED(hr)) 3624 return hr; 3625 3626 device->recording = stateblock; 3627 device->update_state = &stateblock->state; 3628 3629 TRACE("Recording stateblock %p.\n", stateblock); 3630 3631 return WINED3D_OK; 3632 } 3633 3634 HRESULT CDECL wined3d_device_end_stateblock(struct wined3d_device *device, 3635 struct wined3d_stateblock **stateblock) 3636 { 3637 struct wined3d_stateblock *object = device->recording; 3638 3639 TRACE("device %p, stateblock %p.\n", device, stateblock); 3640 3641 if (!device->recording) 3642 { 3643 WARN("Not recording.\n"); 3644 *stateblock = NULL; 3645 return WINED3DERR_INVALIDCALL; 3646 } 3647 3648 stateblock_init_contained_states(object); 3649 3650 *stateblock = object; 3651 device->recording = NULL; 3652 device->update_state = &device->state; 3653 3654 TRACE("Returning stateblock %p.\n", *stateblock); 3655 3656 return WINED3D_OK; 3657 } 3658 3659 HRESULT CDECL wined3d_device_begin_scene(struct wined3d_device *device) 3660 { 3661 /* At the moment we have no need for any functionality at the beginning 3662 * of a scene. */ 3663 TRACE("device %p.\n", device); 3664 3665 if (device->inScene) 3666 { 3667 WARN("Already in scene, returning WINED3DERR_INVALIDCALL.\n"); 3668 return WINED3DERR_INVALIDCALL; 3669 } 3670 device->inScene = TRUE; 3671 return WINED3D_OK; 3672 } 3673 3674 HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) 3675 { 3676 TRACE("device %p.\n", device); 3677 3678 if (!device->inScene) 3679 { 3680 WARN("Not in scene, returning WINED3DERR_INVALIDCALL.\n"); 3681 return WINED3DERR_INVALIDCALL; 3682 } 3683 3684 wined3d_cs_emit_flush(device->cs); 3685 3686 device->inScene = FALSE; 3687 return WINED3D_OK; 3688 } 3689 3690 HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_count, 3691 const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) 3692 { 3693 TRACE("device %p, rect_count %u, rects %p, flags %#x, color %s, depth %.8e, stencil %u.\n", 3694 device, rect_count, rects, flags, debug_color(color), depth, stencil); 3695 3696 if (!rect_count && rects) 3697 { 3698 WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects); 3699 return WINED3D_OK; 3700 } 3701 3702 if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) 3703 { 3704 struct wined3d_rendertarget_view *ds = device->fb.depth_stencil; 3705 if (!ds) 3706 { 3707 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n"); 3708 /* TODO: What about depth stencil buffers without stencil bits? */ 3709 return WINED3DERR_INVALIDCALL; 3710 } 3711 else if (flags & WINED3DCLEAR_TARGET) 3712 { 3713 if (ds->width < device->fb.render_targets[0]->width 3714 || ds->height < device->fb.render_targets[0]->height) 3715 { 3716 WARN("Silently ignoring depth and target clear with mismatching sizes\n"); 3717 return WINED3D_OK; 3718 } 3719 } 3720 } 3721 3722 wined3d_cs_emit_clear(device->cs, rect_count, rects, flags, color, depth, stencil); 3723 3724 return WINED3D_OK; 3725 } 3726 3727 void CDECL wined3d_device_set_predication(struct wined3d_device *device, 3728 struct wined3d_query *predicate, BOOL value) 3729 { 3730 struct wined3d_query *prev; 3731 3732 TRACE("device %p, predicate %p, value %#x.\n", device, predicate, value); 3733 3734 prev = device->update_state->predicate; 3735 if (predicate) 3736 { 3737 FIXME("Predicated rendering not implemented.\n"); 3738 wined3d_query_incref(predicate); 3739 } 3740 device->update_state->predicate = predicate; 3741 device->update_state->predicate_value = value; 3742 if (!device->recording) 3743 wined3d_cs_emit_set_predication(device->cs, predicate, value); 3744 if (prev) 3745 wined3d_query_decref(prev); 3746 } 3747 3748 struct wined3d_query * CDECL wined3d_device_get_predication(struct wined3d_device *device, BOOL *value) 3749 { 3750 TRACE("device %p, value %p.\n", device, value); 3751 3752 if (value) 3753 *value = device->state.predicate_value; 3754 return device->state.predicate; 3755 } 3756 3757 void CDECL wined3d_device_dispatch_compute(struct wined3d_device *device, 3758 unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) 3759 { 3760 TRACE("device %p, group_count_x %u, group_count_y %u, group_count_z %u.\n", 3761 device, group_count_x, group_count_y, group_count_z); 3762 3763 wined3d_cs_emit_dispatch(device->cs, group_count_x, group_count_y, group_count_z); 3764 } 3765 3766 void CDECL wined3d_device_dispatch_compute_indirect(struct wined3d_device *device, 3767 struct wined3d_buffer *buffer, unsigned int offset) 3768 { 3769 TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset); 3770 3771 wined3d_cs_emit_dispatch_indirect(device->cs, buffer, offset); 3772 } 3773 3774 void CDECL wined3d_device_set_primitive_type(struct wined3d_device *device, 3775 enum wined3d_primitive_type primitive_type, unsigned int patch_vertex_count) 3776 { 3777 TRACE("device %p, primitive_type %s, patch_vertex_count %u.\n", 3778 device, debug_d3dprimitivetype(primitive_type), patch_vertex_count); 3779 3780 device->state.gl_primitive_type = gl_primitive_type_from_d3d(primitive_type); 3781 device->state.gl_patch_vertices = patch_vertex_count; 3782 } 3783 3784 void CDECL wined3d_device_get_primitive_type(const struct wined3d_device *device, 3785 enum wined3d_primitive_type *primitive_type, unsigned int *patch_vertex_count) 3786 { 3787 TRACE("device %p, primitive_type %p, patch_vertex_count %p.\n", 3788 device, primitive_type, patch_vertex_count); 3789 3790 *primitive_type = d3d_primitive_type_from_gl(device->state.gl_primitive_type); 3791 if (patch_vertex_count) 3792 *patch_vertex_count = device->state.gl_patch_vertices; 3793 3794 TRACE("Returning %s.\n", debug_d3dprimitivetype(*primitive_type)); 3795 } 3796 3797 HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT start_vertex, UINT vertex_count) 3798 { 3799 TRACE("device %p, start_vertex %u, vertex_count %u.\n", device, start_vertex, vertex_count); 3800 3801 wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, 3802 0, start_vertex, vertex_count, 0, 0, FALSE); 3803 3804 return WINED3D_OK; 3805 } 3806 3807 void CDECL wined3d_device_draw_primitive_instanced(struct wined3d_device *device, 3808 UINT start_vertex, UINT vertex_count, UINT start_instance, UINT instance_count) 3809 { 3810 TRACE("device %p, start_vertex %u, vertex_count %u, start_instance %u, instance_count %u.\n", 3811 device, start_vertex, vertex_count, start_instance, instance_count); 3812 3813 wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, 3814 0, start_vertex, vertex_count, start_instance, instance_count, FALSE); 3815 } 3816 3817 void CDECL wined3d_device_draw_primitive_instanced_indirect(struct wined3d_device *device, 3818 struct wined3d_buffer *buffer, unsigned int offset) 3819 { 3820 TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset); 3821 3822 wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, 3823 buffer, offset, FALSE); 3824 } 3825 3826 HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count) 3827 { 3828 TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count); 3829 3830 if (!device->state.index_buffer) 3831 { 3832 /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called 3833 * without an index buffer set. (The first time at least...) 3834 * D3D8 simply dies, but I doubt it can do much harm to return 3835 * D3DERR_INVALIDCALL there as well. */ 3836 WARN("Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL.\n"); 3837 return WINED3DERR_INVALIDCALL; 3838 } 3839 3840 wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, 3841 device->state.base_vertex_index, start_idx, index_count, 0, 0, TRUE); 3842 3843 return WINED3D_OK; 3844 } 3845 3846 void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device *device, 3847 UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count) 3848 { 3849 TRACE("device %p, start_idx %u, index_count %u, start_instance %u, instance_count %u.\n", 3850 device, start_idx, index_count, start_instance, instance_count); 3851 3852 wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, 3853 device->state.base_vertex_index, start_idx, index_count, start_instance, instance_count, TRUE); 3854 } 3855 3856 void CDECL wined3d_device_draw_indexed_primitive_instanced_indirect(struct wined3d_device *device, 3857 struct wined3d_buffer *buffer, unsigned int offset) 3858 { 3859 TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset); 3860 3861 wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, 3862 buffer, offset, TRUE); 3863 } 3864 3865 HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, 3866 struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture) 3867 { 3868 unsigned int src_size, dst_size, src_skip_levels = 0; 3869 unsigned int src_level_count, dst_level_count; 3870 unsigned int layer_count, level_count, i, j; 3871 unsigned int width, height, depth; 3872 enum wined3d_resource_type type; 3873 struct wined3d_box box; 3874 3875 TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture); 3876 3877 /* Verify that the source and destination textures are non-NULL. */ 3878 if (!src_texture || !dst_texture) 3879 { 3880 WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n"); 3881 return WINED3DERR_INVALIDCALL; 3882 } 3883 3884 if (src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU 3885 || src_texture->resource.usage & WINED3DUSAGE_SCRATCH) 3886 { 3887 WARN("Source resource is GPU accessible or a scratch resource.\n"); 3888 return WINED3DERR_INVALIDCALL; 3889 } 3890 if (dst_texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) 3891 { 3892 WARN("Destination resource is CPU accessible.\n"); 3893 return WINED3DERR_INVALIDCALL; 3894 } 3895 3896 /* Verify that the source and destination textures are the same type. */ 3897 type = src_texture->resource.type; 3898 if (dst_texture->resource.type != type) 3899 { 3900 WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n"); 3901 return WINED3DERR_INVALIDCALL; 3902 } 3903 3904 layer_count = src_texture->layer_count; 3905 if (layer_count != dst_texture->layer_count) 3906 { 3907 WARN("Source and destination have different layer counts.\n"); 3908 return WINED3DERR_INVALIDCALL; 3909 } 3910 3911 if (src_texture->resource.format != dst_texture->resource.format) 3912 { 3913 WARN("Source and destination formats do not match.\n"); 3914 return WINED3DERR_INVALIDCALL; 3915 } 3916 3917 src_level_count = src_texture->level_count; 3918 dst_level_count = dst_texture->level_count; 3919 level_count = min(src_level_count, dst_level_count); 3920 3921 src_size = max(src_texture->resource.width, src_texture->resource.height); 3922 src_size = max(src_size, src_texture->resource.depth); 3923 dst_size = max(dst_texture->resource.width, dst_texture->resource.height); 3924 dst_size = max(dst_size, dst_texture->resource.depth); 3925 while (src_size > dst_size) 3926 { 3927 src_size >>= 1; 3928 ++src_skip_levels; 3929 } 3930 3931 if (wined3d_texture_get_level_width(src_texture, src_skip_levels) != dst_texture->resource.width 3932 || wined3d_texture_get_level_height(src_texture, src_skip_levels) != dst_texture->resource.height 3933 || wined3d_texture_get_level_depth(src_texture, src_skip_levels) != dst_texture->resource.depth) 3934 { 3935 WARN("Source and destination dimensions do not match.\n"); 3936 return WINED3DERR_INVALIDCALL; 3937 } 3938 3939 /* Update every surface level of the texture. */ 3940 for (i = 0; i < level_count; ++i) 3941 { 3942 width = wined3d_texture_get_level_width(dst_texture, i); 3943 height = wined3d_texture_get_level_height(dst_texture, i); 3944 depth = wined3d_texture_get_level_depth(dst_texture, i); 3945 wined3d_box_set(&box, 0, 0, width, height, 0, depth); 3946 3947 for (j = 0; j < layer_count; ++j) 3948 { 3949 wined3d_cs_emit_blt_sub_resource(device->cs, 3950 &dst_texture->resource, j * dst_level_count + i, &box, 3951 &src_texture->resource, j * src_level_count + i + src_skip_levels, &box, 3952 0, NULL, WINED3D_TEXF_POINT); 3953 } 3954 } 3955 3956 return WINED3D_OK; 3957 } 3958 3959 HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes) 3960 { 3961 const struct wined3d_state *state = &device->state; 3962 struct wined3d_texture *texture; 3963 DWORD i; 3964 3965 TRACE("device %p, num_passes %p.\n", device, num_passes); 3966 3967 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) 3968 { 3969 if (state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] == WINED3D_TEXF_NONE) 3970 { 3971 WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i); 3972 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER; 3973 } 3974 if (state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] == WINED3D_TEXF_NONE) 3975 { 3976 WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i); 3977 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER; 3978 } 3979 3980 texture = state->textures[i]; 3981 if (!texture || texture->resource.format_flags & WINED3DFMT_FLAG_FILTERING) continue; 3982 3983 if (state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] != WINED3D_TEXF_POINT) 3984 { 3985 WARN("Non-filterable texture and mag filter enabled on sampler %u, returning E_FAIL\n", i); 3986 return E_FAIL; 3987 } 3988 if (state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] != WINED3D_TEXF_POINT) 3989 { 3990 WARN("Non-filterable texture and min filter enabled on sampler %u, returning E_FAIL\n", i); 3991 return E_FAIL; 3992 } 3993 if (state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_NONE 3994 && state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_POINT) 3995 { 3996 WARN("Non-filterable texture and mip filter enabled on sampler %u, returning E_FAIL\n", i); 3997 return E_FAIL; 3998 } 3999 } 4000 4001 if (state->render_states[WINED3D_RS_ZENABLE] || state->render_states[WINED3D_RS_ZWRITEENABLE] 4002 || state->render_states[WINED3D_RS_STENCILENABLE]) 4003 { 4004 struct wined3d_rendertarget_view *rt = device->fb.render_targets[0]; 4005 struct wined3d_rendertarget_view *ds = device->fb.depth_stencil; 4006 4007 if (ds && rt && (ds->width < rt->width || ds->height < rt->height)) 4008 { 4009 WARN("Depth stencil is smaller than the color buffer, returning D3DERR_CONFLICTINGRENDERSTATE\n"); 4010 return WINED3DERR_CONFLICTINGRENDERSTATE; 4011 } 4012 } 4013 4014 /* return a sensible default */ 4015 *num_passes = 1; 4016 4017 TRACE("returning D3D_OK\n"); 4018 return WINED3D_OK; 4019 } 4020 4021 void CDECL wined3d_device_set_software_vertex_processing(struct wined3d_device *device, BOOL software) 4022 { 4023 TRACE("device %p, software %#x.\n", device, software); 4024 4025 device->softwareVertexProcessing = software; 4026 } 4027 4028 BOOL CDECL wined3d_device_get_software_vertex_processing(const struct wined3d_device *device) 4029 { 4030 TRACE("device %p.\n", device); 4031 4032 return device->softwareVertexProcessing; 4033 } 4034 4035 HRESULT CDECL wined3d_device_get_raster_status(const struct wined3d_device *device, 4036 UINT swapchain_idx, struct wined3d_raster_status *raster_status) 4037 { 4038 struct wined3d_swapchain *swapchain; 4039 4040 TRACE("device %p, swapchain_idx %u, raster_status %p.\n", 4041 device, swapchain_idx, raster_status); 4042 4043 if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx))) 4044 return WINED3DERR_INVALIDCALL; 4045 4046 return wined3d_swapchain_get_raster_status(swapchain, raster_status); 4047 } 4048 4049 HRESULT CDECL wined3d_device_set_npatch_mode(struct wined3d_device *device, float segments) 4050 { 4051 static BOOL warned; 4052 4053 TRACE("device %p, segments %.8e.\n", device, segments); 4054 4055 if (segments != 0.0f) 4056 { 4057 if (!warned) 4058 { 4059 FIXME("device %p, segments %.8e stub!\n", device, segments); 4060 warned = TRUE; 4061 } 4062 } 4063 4064 return WINED3D_OK; 4065 } 4066 4067 float CDECL wined3d_device_get_npatch_mode(const struct wined3d_device *device) 4068 { 4069 static BOOL warned; 4070 4071 TRACE("device %p.\n", device); 4072 4073 if (!warned) 4074 { 4075 FIXME("device %p stub!\n", device); 4076 warned = TRUE; 4077 } 4078 4079 return 0.0f; 4080 } 4081 4082 void CDECL wined3d_device_copy_uav_counter(struct wined3d_device *device, 4083 struct wined3d_buffer *dst_buffer, unsigned int offset, struct wined3d_unordered_access_view *uav) 4084 { 4085 TRACE("device %p, dst_buffer %p, offset %u, uav %p.\n", 4086 device, dst_buffer, offset, uav); 4087 4088 if (offset + sizeof(GLuint) > dst_buffer->resource.size) 4089 { 4090 WARN("Offset %u too large.\n", offset); 4091 return; 4092 } 4093 4094 wined3d_cs_emit_copy_uav_counter(device->cs, dst_buffer, offset, uav); 4095 } 4096 4097 void CDECL wined3d_device_copy_resource(struct wined3d_device *device, 4098 struct wined3d_resource *dst_resource, struct wined3d_resource *src_resource) 4099 { 4100 struct wined3d_texture *dst_texture, *src_texture; 4101 struct wined3d_box box; 4102 unsigned int i, j; 4103 4104 TRACE("device %p, dst_resource %p, src_resource %p.\n", device, dst_resource, src_resource); 4105 4106 if (src_resource == dst_resource) 4107 { 4108 WARN("Source and destination are the same resource.\n"); 4109 return; 4110 } 4111 4112 if (src_resource->type != dst_resource->type) 4113 { 4114 WARN("Resource types (%s / %s) don't match.\n", 4115 debug_d3dresourcetype(dst_resource->type), 4116 debug_d3dresourcetype(src_resource->type)); 4117 return; 4118 } 4119 4120 if (src_resource->width != dst_resource->width 4121 || src_resource->height != dst_resource->height 4122 || src_resource->depth != dst_resource->depth) 4123 { 4124 WARN("Resource dimensions (%ux%ux%u / %ux%ux%u) don't match.\n", 4125 dst_resource->width, dst_resource->height, dst_resource->depth, 4126 src_resource->width, src_resource->height, src_resource->depth); 4127 return; 4128 } 4129 4130 if (src_resource->format->typeless_id != dst_resource->format->typeless_id 4131 || (!src_resource->format->typeless_id && src_resource->format->id != dst_resource->format->id)) 4132 { 4133 WARN("Resource formats %s and %s are incompatible.\n", 4134 debug_d3dformat(dst_resource->format->id), 4135 debug_d3dformat(src_resource->format->id)); 4136 return; 4137 } 4138 4139 if (dst_resource->type == WINED3D_RTYPE_BUFFER) 4140 { 4141 wined3d_box_set(&box, 0, 0, src_resource->size, 1, 0, 1); 4142 wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, 0, &box, 4143 src_resource, 0, &box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT); 4144 return; 4145 } 4146 4147 dst_texture = texture_from_resource(dst_resource); 4148 src_texture = texture_from_resource(src_resource); 4149 4150 if (src_texture->layer_count != dst_texture->layer_count 4151 || src_texture->level_count != dst_texture->level_count) 4152 { 4153 WARN("Subresource layouts (%ux%u / %ux%u) don't match.\n", 4154 dst_texture->layer_count, dst_texture->level_count, 4155 src_texture->layer_count, src_texture->level_count); 4156 return; 4157 } 4158 4159 for (i = 0; i < dst_texture->level_count; ++i) 4160 { 4161 wined3d_box_set(&box, 0, 0, 4162 wined3d_texture_get_level_width(dst_texture, i), 4163 wined3d_texture_get_level_height(dst_texture, i), 4164 0, wined3d_texture_get_level_depth(dst_texture, i)); 4165 for (j = 0; j < dst_texture->layer_count; ++j) 4166 { 4167 unsigned int idx = j * dst_texture->level_count + i; 4168 4169 wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, idx, &box, 4170 src_resource, idx, &box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT); 4171 } 4172 } 4173 } 4174 4175 HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *device, 4176 struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x, 4177 unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource, 4178 unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, unsigned int flags) 4179 { 4180 struct wined3d_box dst_box, b; 4181 4182 TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, " 4183 "src_resource %p, src_sub_resource_idx %u, src_box %s, flags %#x.\n", 4184 device, dst_resource, dst_sub_resource_idx, dst_x, dst_y, dst_z, 4185 src_resource, src_sub_resource_idx, debug_box(src_box), flags); 4186 4187 if (flags) 4188 FIXME("Ignoring flags %#x.\n", flags); 4189 4190 if (src_resource == dst_resource && src_sub_resource_idx == dst_sub_resource_idx) 4191 { 4192 WARN("Source and destination are the same sub-resource.\n"); 4193 return WINED3DERR_INVALIDCALL; 4194 } 4195 4196 if (src_resource->type != dst_resource->type) 4197 { 4198 WARN("Resource types (%s / %s) don't match.\n", 4199 debug_d3dresourcetype(dst_resource->type), 4200 debug_d3dresourcetype(src_resource->type)); 4201 return WINED3DERR_INVALIDCALL; 4202 } 4203 4204 if (src_resource->format->typeless_id != dst_resource->format->typeless_id 4205 || (!src_resource->format->typeless_id && src_resource->format->id != dst_resource->format->id)) 4206 { 4207 WARN("Resource formats %s and %s are incompatible.\n", 4208 debug_d3dformat(dst_resource->format->id), 4209 debug_d3dformat(src_resource->format->id)); 4210 return WINED3DERR_INVALIDCALL; 4211 } 4212 4213 if (dst_resource->type == WINED3D_RTYPE_BUFFER) 4214 { 4215 if (dst_sub_resource_idx) 4216 { 4217 WARN("Invalid dst_sub_resource_idx %u.\n", dst_sub_resource_idx); 4218 return WINED3DERR_INVALIDCALL; 4219 } 4220 4221 if (src_sub_resource_idx) 4222 { 4223 WARN("Invalid src_sub_resource_idx %u.\n", src_sub_resource_idx); 4224 return WINED3DERR_INVALIDCALL; 4225 } 4226 4227 if (!src_box) 4228 { 4229 unsigned int dst_w; 4230 4231 dst_w = dst_resource->size - dst_x; 4232 wined3d_box_set(&b, 0, 0, min(src_resource->size, dst_w), 1, 0, 1); 4233 src_box = &b; 4234 } 4235 else if ((src_box->left >= src_box->right 4236 || src_box->top >= src_box->bottom 4237 || src_box->front >= src_box->back)) 4238 { 4239 WARN("Invalid box %s specified.\n", debug_box(src_box)); 4240 return WINED3DERR_INVALIDCALL; 4241 } 4242 4243 if (src_box->right > src_resource->size || dst_x >= dst_resource->size 4244 || src_box->right - src_box->left > dst_resource->size - dst_x) 4245 { 4246 WARN("Invalid range specified, dst_offset %u, src_offset %u, size %u.\n", 4247 dst_x, src_box->left, src_box->right - src_box->left); 4248 return WINED3DERR_INVALIDCALL; 4249 } 4250 4251 wined3d_box_set(&dst_box, dst_x, 0, dst_x + (src_box->right - src_box->left), 1, 0, 1); 4252 } 4253 else 4254 { 4255 struct wined3d_texture *dst_texture = texture_from_resource(dst_resource); 4256 struct wined3d_texture *src_texture = texture_from_resource(src_resource); 4257 unsigned int src_level = src_sub_resource_idx % src_texture->level_count; 4258 4259 if (dst_sub_resource_idx >= dst_texture->level_count * dst_texture->layer_count) 4260 { 4261 WARN("Invalid destination sub-resource %u.\n", dst_sub_resource_idx); 4262 return WINED3DERR_INVALIDCALL; 4263 } 4264 4265 if (src_sub_resource_idx >= src_texture->level_count * src_texture->layer_count) 4266 { 4267 WARN("Invalid source sub-resource %u.\n", src_sub_resource_idx); 4268 return WINED3DERR_INVALIDCALL; 4269 } 4270 4271 if (dst_texture->sub_resources[dst_sub_resource_idx].map_count) 4272 { 4273 WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx); 4274 return WINED3DERR_INVALIDCALL; 4275 } 4276 4277 if (src_texture->sub_resources[src_sub_resource_idx].map_count) 4278 { 4279 WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx); 4280 return WINED3DERR_INVALIDCALL; 4281 } 4282 4283 if (!src_box) 4284 { 4285 unsigned int src_w, src_h, src_d, dst_w, dst_h, dst_d, dst_level; 4286 4287 src_w = wined3d_texture_get_level_width(src_texture, src_level); 4288 src_h = wined3d_texture_get_level_height(src_texture, src_level); 4289 src_d = wined3d_texture_get_level_depth(src_texture, src_level); 4290 4291 dst_level = dst_sub_resource_idx % dst_texture->level_count; 4292 dst_w = wined3d_texture_get_level_width(dst_texture, dst_level) - dst_x; 4293 dst_h = wined3d_texture_get_level_height(dst_texture, dst_level) - dst_y; 4294 dst_d = wined3d_texture_get_level_depth(dst_texture, dst_level) - dst_z; 4295 4296 wined3d_box_set(&b, 0, 0, min(src_w, dst_w), min(src_h, dst_h), 0, min(src_d, dst_d)); 4297 src_box = &b; 4298 } 4299 else if (FAILED(wined3d_texture_check_box_dimensions(src_texture, src_level, src_box))) 4300 { 4301 WARN("Invalid source box %s.\n", debug_box(src_box)); 4302 return WINED3DERR_INVALIDCALL; 4303 } 4304 4305 wined3d_box_set(&dst_box, dst_x, dst_y, dst_x + (src_box->right - src_box->left), 4306 dst_y + (src_box->bottom - src_box->top), dst_z, dst_z + (src_box->back - src_box->front)); 4307 if (FAILED(wined3d_texture_check_box_dimensions(dst_texture, 4308 dst_sub_resource_idx % dst_texture->level_count, &dst_box))) 4309 { 4310 WARN("Invalid destination box %s.\n", debug_box(&dst_box)); 4311 return WINED3DERR_INVALIDCALL; 4312 } 4313 } 4314 4315 wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box, 4316 src_resource, src_sub_resource_idx, src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT); 4317 4318 return WINED3D_OK; 4319 } 4320 4321 void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource, 4322 unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, 4323 unsigned int depth_pitch, unsigned int flags) 4324 { 4325 unsigned int width, height, depth; 4326 struct wined3d_box b; 4327 4328 TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u, " 4329 "flags %#x.\n", 4330 device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch, flags); 4331 4332 if (flags) 4333 FIXME("Ignoring flags %#x.\n", flags); 4334 4335 if (resource->type == WINED3D_RTYPE_BUFFER) 4336 { 4337 if (sub_resource_idx > 0) 4338 { 4339 WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); 4340 return; 4341 } 4342 4343 width = resource->size; 4344 height = 1; 4345 depth = 1; 4346 } 4347 else 4348 { 4349 struct wined3d_texture *texture = texture_from_resource(resource); 4350 unsigned int level; 4351 4352 if (sub_resource_idx >= texture->level_count * texture->layer_count) 4353 { 4354 WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); 4355 return; 4356 } 4357 4358 level = sub_resource_idx % texture->level_count; 4359 width = wined3d_texture_get_level_width(texture, level); 4360 height = wined3d_texture_get_level_height(texture, level); 4361 depth = wined3d_texture_get_level_depth(texture, level); 4362 } 4363 4364 if (!box) 4365 { 4366 wined3d_box_set(&b, 0, 0, width, height, 0, depth); 4367 box = &b; 4368 } 4369 else if (box->left >= box->right || box->right > width 4370 || box->top >= box->bottom || box->bottom > height 4371 || box->front >= box->back || box->back > depth) 4372 { 4373 WARN("Invalid box %s specified.\n", debug_box(box)); 4374 return; 4375 } 4376 4377 wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch); 4378 } 4379 4380 void CDECL wined3d_device_resolve_sub_resource(struct wined3d_device *device, 4381 struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, 4382 struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx, 4383 enum wined3d_format_id format_id) 4384 { 4385 struct wined3d_texture *dst_texture, *src_texture; 4386 unsigned int dst_level, src_level; 4387 RECT dst_rect, src_rect; 4388 4389 TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, " 4390 "src_resource %p, src_sub_resource_idx %u, format %s.\n", 4391 device, dst_resource, dst_sub_resource_idx, 4392 src_resource, src_sub_resource_idx, debug_d3dformat(format_id)); 4393 4394 if (wined3d_format_is_typeless(dst_resource->format) 4395 || wined3d_format_is_typeless(src_resource->format)) 4396 { 4397 FIXME("Unhandled multisample resolve, dst_format %s, src_format %s, format %s.\n", 4398 debug_d3dformat(dst_resource->format->id), debug_d3dformat(src_resource->format->id), 4399 debug_d3dformat(format_id)); 4400 return; 4401 } 4402 if (dst_resource->type != WINED3D_RTYPE_TEXTURE_2D) 4403 { 4404 WARN("Invalid destination resource type %s.\n", debug_d3dresourcetype(dst_resource->type)); 4405 return; 4406 } 4407 if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D) 4408 { 4409 WARN("Invalid source resource type %s.\n", debug_d3dresourcetype(src_resource->type)); 4410 return; 4411 } 4412 4413 dst_texture = texture_from_resource(dst_resource); 4414 src_texture = texture_from_resource(src_resource); 4415 4416 dst_level = dst_sub_resource_idx % dst_texture->level_count; 4417 SetRect(&dst_rect, 0, 0, wined3d_texture_get_level_width(dst_texture, dst_level), 4418 wined3d_texture_get_level_height(dst_texture, dst_level)); 4419 src_level = src_sub_resource_idx % src_texture->level_count; 4420 SetRect(&src_rect, 0, 0, wined3d_texture_get_level_width(src_texture, src_level), 4421 wined3d_texture_get_level_height(src_texture, src_level)); 4422 wined3d_texture_blt(dst_texture, dst_sub_resource_idx, &dst_rect, 4423 src_texture, src_sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT); 4424 } 4425 4426 HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device, 4427 struct wined3d_rendertarget_view *view, const RECT *rect, DWORD flags, 4428 const struct wined3d_color *color, float depth, DWORD stencil) 4429 { 4430 struct wined3d_resource *resource; 4431 RECT r; 4432 4433 TRACE("device %p, view %p, rect %s, flags %#x, color %s, depth %.8e, stencil %u.\n", 4434 device, view, wine_dbgstr_rect(rect), flags, debug_color(color), depth, stencil); 4435 4436 if (!flags) 4437 return WINED3D_OK; 4438 4439 resource = view->resource; 4440 if (resource->type != WINED3D_RTYPE_TEXTURE_1D && resource->type != WINED3D_RTYPE_TEXTURE_2D) 4441 { 4442 FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); 4443 return WINED3DERR_INVALIDCALL; 4444 } 4445 4446 if (view->layer_count > 1) 4447 { 4448 FIXME("Layered clears not implemented.\n"); 4449 return WINED3DERR_INVALIDCALL; 4450 } 4451 4452 if (!rect) 4453 { 4454 SetRect(&r, 0, 0, view->width, view->height); 4455 rect = &r; 4456 } 4457 else 4458 { 4459 struct wined3d_box b = {rect->left, rect->top, rect->right, rect->bottom, 0, 1}; 4460 struct wined3d_texture *texture = texture_from_resource(view->resource); 4461 HRESULT hr; 4462 4463 if (FAILED(hr = wined3d_texture_check_box_dimensions(texture, 4464 view->sub_resource_idx % texture->level_count, &b))) 4465 return hr; 4466 } 4467 4468 wined3d_cs_emit_clear_rendertarget_view(device->cs, view, rect, flags, color, depth, stencil); 4469 4470 return WINED3D_OK; 4471 } 4472 4473 void CDECL wined3d_device_clear_unordered_access_view_uint(struct wined3d_device *device, 4474 struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value) 4475 { 4476 TRACE("device %p, view %p, clear_value %s.\n", device, view, debug_uvec4(clear_value)); 4477 4478 wined3d_cs_emit_clear_unordered_access_view_uint(device->cs, view, clear_value); 4479 } 4480 4481 struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(const struct wined3d_device *device, 4482 unsigned int view_idx) 4483 { 4484 TRACE("device %p, view_idx %u.\n", device, view_idx); 4485 4486 if (view_idx >= device->adapter->gl_info.limits.buffers) 4487 { 4488 WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers); 4489 return NULL; 4490 } 4491 4492 return device->fb.render_targets[view_idx]; 4493 } 4494 4495 struct wined3d_rendertarget_view * CDECL wined3d_device_get_depth_stencil_view(const struct wined3d_device *device) 4496 { 4497 TRACE("device %p.\n", device); 4498 4499 return device->fb.depth_stencil; 4500 } 4501 4502 HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device, 4503 unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport) 4504 { 4505 struct wined3d_rendertarget_view *prev; 4506 4507 TRACE("device %p, view_idx %u, view %p, set_viewport %#x.\n", 4508 device, view_idx, view, set_viewport); 4509 4510 if (view_idx >= device->adapter->gl_info.limits.buffers) 4511 { 4512 WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers); 4513 return WINED3DERR_INVALIDCALL; 4514 } 4515 4516 if (view && !(view->resource->usage & WINED3DUSAGE_RENDERTARGET)) 4517 { 4518 WARN("View resource %p doesn't have render target usage.\n", view->resource); 4519 return WINED3DERR_INVALIDCALL; 4520 } 4521 4522 /* Set the viewport and scissor rectangles, if requested. Tests show that 4523 * stateblock recording is ignored, the change goes directly into the 4524 * primary stateblock. */ 4525 if (!view_idx && set_viewport) 4526 { 4527 struct wined3d_state *state = &device->state; 4528 4529 state->viewports[0].x = 0; 4530 state->viewports[0].y = 0; 4531 state->viewports[0].width = view->width; 4532 state->viewports[0].height = view->height; 4533 state->viewports[0].min_z = 0.0f; 4534 state->viewports[0].max_z = 1.0f; 4535 state->viewport_count = 1; 4536 wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports); 4537 4538 SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height); 4539 state->scissor_rect_count = 1; 4540 wined3d_cs_emit_set_scissor_rects(device->cs, 1, state->scissor_rects); 4541 } 4542 4543 prev = device->fb.render_targets[view_idx]; 4544 if (view == prev) 4545 return WINED3D_OK; 4546 4547 if (view) 4548 wined3d_rendertarget_view_incref(view); 4549 device->fb.render_targets[view_idx] = view; 4550 wined3d_cs_emit_set_rendertarget_view(device->cs, view_idx, view); 4551 /* Release after the assignment, to prevent device_resource_released() 4552 * from seeing the surface as still in use. */ 4553 if (prev) 4554 wined3d_rendertarget_view_decref(prev); 4555 4556 return WINED3D_OK; 4557 } 4558 4559 void CDECL wined3d_device_set_depth_stencil_view(struct wined3d_device *device, struct wined3d_rendertarget_view *view) 4560 { 4561 struct wined3d_rendertarget_view *prev; 4562 4563 TRACE("device %p, view %p.\n", device, view); 4564 4565 prev = device->fb.depth_stencil; 4566 if (prev == view) 4567 { 4568 TRACE("Trying to do a NOP SetRenderTarget operation.\n"); 4569 return; 4570 } 4571 4572 if ((device->fb.depth_stencil = view)) 4573 wined3d_rendertarget_view_incref(view); 4574 wined3d_cs_emit_set_depth_stencil_view(device->cs, view); 4575 if (prev) 4576 wined3d_rendertarget_view_decref(prev); 4577 } 4578 4579 static struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined3d_device *device, 4580 struct wined3d_texture *cursor_image, unsigned int sub_resource_idx) 4581 { 4582 unsigned int texture_level = sub_resource_idx % cursor_image->level_count; 4583 struct wined3d_sub_resource_data data; 4584 struct wined3d_resource_desc desc; 4585 struct wined3d_map_desc map_desc; 4586 struct wined3d_texture *texture; 4587 HRESULT hr; 4588 4589 if (FAILED(wined3d_resource_map(&cursor_image->resource, sub_resource_idx, &map_desc, NULL, WINED3D_MAP_READ))) 4590 { 4591 ERR("Failed to map source texture.\n"); 4592 return NULL; 4593 } 4594 4595 data.data = map_desc.data; 4596 data.row_pitch = map_desc.row_pitch; 4597 data.slice_pitch = map_desc.slice_pitch; 4598 4599 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 4600 desc.format = WINED3DFMT_B8G8R8A8_UNORM; 4601 desc.multisample_type = WINED3D_MULTISAMPLE_NONE; 4602 desc.multisample_quality = 0; 4603 desc.usage = WINED3DUSAGE_DYNAMIC; 4604 desc.access = WINED3D_RESOURCE_ACCESS_GPU; 4605 desc.width = wined3d_texture_get_level_width(cursor_image, texture_level); 4606 desc.height = wined3d_texture_get_level_height(cursor_image, texture_level); 4607 desc.depth = 1; 4608 desc.size = 0; 4609 4610 hr = wined3d_texture_create(device, &desc, 1, 1, WINED3D_TEXTURE_CREATE_MAPPABLE, 4611 &data, NULL, &wined3d_null_parent_ops, &texture); 4612 wined3d_resource_unmap(&cursor_image->resource, sub_resource_idx); 4613 if (FAILED(hr)) 4614 { 4615 ERR("Failed to create cursor texture.\n"); 4616 return NULL; 4617 } 4618 4619 return texture; 4620 } 4621 4622 HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device, 4623 UINT x_hotspot, UINT y_hotspot, struct wined3d_texture *texture, unsigned int sub_resource_idx) 4624 { 4625 unsigned int texture_level = sub_resource_idx % texture->level_count; 4626 unsigned int cursor_width, cursor_height; 4627 struct wined3d_display_mode mode; 4628 struct wined3d_map_desc map_desc; 4629 HRESULT hr; 4630 4631 TRACE("device %p, x_hotspot %u, y_hotspot %u, texture %p, sub_resource_idx %u.\n", 4632 device, x_hotspot, y_hotspot, texture, sub_resource_idx); 4633 4634 if (sub_resource_idx >= texture->level_count * texture->layer_count 4635 || texture->resource.type != WINED3D_RTYPE_TEXTURE_2D) 4636 return WINED3DERR_INVALIDCALL; 4637 4638 if (device->cursor_texture) 4639 { 4640 wined3d_texture_decref(device->cursor_texture); 4641 device->cursor_texture = NULL; 4642 } 4643 4644 if (texture->resource.format->id != WINED3DFMT_B8G8R8A8_UNORM) 4645 { 4646 WARN("Texture %p has invalid format %s.\n", 4647 texture, debug_d3dformat(texture->resource.format->id)); 4648 return WINED3DERR_INVALIDCALL; 4649 } 4650 4651 if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, device->adapter->ordinal, &mode, NULL))) 4652 { 4653 ERR("Failed to get display mode, hr %#x.\n", hr); 4654 return WINED3DERR_INVALIDCALL; 4655 } 4656 4657 cursor_width = wined3d_texture_get_level_width(texture, texture_level); 4658 cursor_height = wined3d_texture_get_level_height(texture, texture_level); 4659 if (cursor_width > mode.width || cursor_height > mode.height) 4660 { 4661 WARN("Texture %p, sub-resource %u dimensions are %ux%u, but screen dimensions are %ux%u.\n", 4662 texture, sub_resource_idx, cursor_width, cursor_height, mode.width, mode.height); 4663 return WINED3DERR_INVALIDCALL; 4664 } 4665 4666 /* TODO: MSDN: Cursor sizes must be a power of 2 */ 4667 4668 /* Do not store the surface's pointer because the application may 4669 * release it after setting the cursor image. Windows doesn't 4670 * addref the set surface, so we can't do this either without 4671 * creating circular refcount dependencies. */ 4672 if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, texture, sub_resource_idx))) 4673 { 4674 ERR("Failed to create cursor texture.\n"); 4675 return WINED3DERR_INVALIDCALL; 4676 } 4677 4678 if (cursor_width == 32 && cursor_height == 32) 4679 { 4680 UINT mask_size = cursor_width * cursor_height / 8; 4681 ICONINFO cursor_info; 4682 DWORD *mask_bits; 4683 HCURSOR cursor; 4684 4685 /* 32-bit user32 cursors ignore the alpha channel if it's all 4686 * zeroes, and use the mask instead. Fill the mask with all ones 4687 * to ensure we still get a fully transparent cursor. */ 4688 if (!(mask_bits = heap_alloc(mask_size))) 4689 return E_OUTOFMEMORY; 4690 memset(mask_bits, 0xff, mask_size); 4691 4692 wined3d_resource_map(&texture->resource, sub_resource_idx, &map_desc, NULL, 4693 WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READ); 4694 cursor_info.fIcon = FALSE; 4695 cursor_info.xHotspot = x_hotspot; 4696 cursor_info.yHotspot = y_hotspot; 4697 cursor_info.hbmMask = CreateBitmap(cursor_width, cursor_height, 1, 1, mask_bits); 4698 cursor_info.hbmColor = CreateBitmap(cursor_width, cursor_height, 1, 32, map_desc.data); 4699 wined3d_resource_unmap(&texture->resource, sub_resource_idx); 4700 4701 /* Create our cursor and clean up. */ 4702 cursor = CreateIconIndirect(&cursor_info); 4703 if (cursor_info.hbmMask) 4704 DeleteObject(cursor_info.hbmMask); 4705 if (cursor_info.hbmColor) 4706 DeleteObject(cursor_info.hbmColor); 4707 if (device->hardwareCursor) 4708 DestroyCursor(device->hardwareCursor); 4709 device->hardwareCursor = cursor; 4710 if (device->bCursorVisible) 4711 SetCursor(cursor); 4712 4713 heap_free(mask_bits); 4714 } 4715 4716 TRACE("New cursor dimensions are %ux%u.\n", cursor_width, cursor_height); 4717 device->cursorWidth = cursor_width; 4718 device->cursorHeight = cursor_height; 4719 device->xHotSpot = x_hotspot; 4720 device->yHotSpot = y_hotspot; 4721 4722 return WINED3D_OK; 4723 } 4724 4725 void CDECL wined3d_device_set_cursor_position(struct wined3d_device *device, 4726 int x_screen_space, int y_screen_space, DWORD flags) 4727 { 4728 TRACE("device %p, x %d, y %d, flags %#x.\n", 4729 device, x_screen_space, y_screen_space, flags); 4730 4731 device->xScreenSpace = x_screen_space; 4732 device->yScreenSpace = y_screen_space; 4733 4734 if (device->hardwareCursor) 4735 { 4736 POINT pt; 4737 4738 GetCursorPos( &pt ); 4739 if (x_screen_space == pt.x && y_screen_space == pt.y) 4740 return; 4741 SetCursorPos( x_screen_space, y_screen_space ); 4742 4743 /* Switch to the software cursor if position diverges from the hardware one. */ 4744 GetCursorPos( &pt ); 4745 if (x_screen_space != pt.x || y_screen_space != pt.y) 4746 { 4747 if (device->bCursorVisible) SetCursor( NULL ); 4748 DestroyCursor( device->hardwareCursor ); 4749 device->hardwareCursor = 0; 4750 } 4751 } 4752 } 4753 4754 BOOL CDECL wined3d_device_show_cursor(struct wined3d_device *device, BOOL show) 4755 { 4756 BOOL oldVisible = device->bCursorVisible; 4757 4758 TRACE("device %p, show %#x.\n", device, show); 4759 4760 /* 4761 * When ShowCursor is first called it should make the cursor appear at the OS's last 4762 * known cursor position. 4763 */ 4764 if (show && !oldVisible) 4765 { 4766 POINT pt; 4767 GetCursorPos(&pt); 4768 device->xScreenSpace = pt.x; 4769 device->yScreenSpace = pt.y; 4770 } 4771 4772 if (device->hardwareCursor) 4773 { 4774 device->bCursorVisible = show; 4775 if (show) 4776 SetCursor(device->hardwareCursor); 4777 else 4778 SetCursor(NULL); 4779 } 4780 else if (device->cursor_texture) 4781 { 4782 device->bCursorVisible = show; 4783 } 4784 4785 return oldVisible; 4786 } 4787 4788 void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device) 4789 { 4790 struct wined3d_resource *resource, *cursor; 4791 4792 TRACE("device %p.\n", device); 4793 4794 LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) 4795 { 4796 TRACE("Checking resource %p for eviction.\n", resource); 4797 4798 if (wined3d_resource_access_is_managed(resource->access) && !resource->map_count) 4799 { 4800 TRACE("Evicting %p.\n", resource); 4801 wined3d_cs_emit_unload_resource(device->cs, resource); 4802 } 4803 } 4804 } 4805 4806 HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, 4807 const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode, 4808 wined3d_device_reset_cb callback, BOOL reset_state) 4809 { 4810 struct wined3d_resource *resource, *cursor; 4811 struct wined3d_swapchain *swapchain; 4812 struct wined3d_view_desc view_desc; 4813 BOOL backbuffer_resized; 4814 HRESULT hr = WINED3D_OK; 4815 unsigned int i; 4816 4817 TRACE("device %p, swapchain_desc %p, mode %p, callback %p, reset_state %#x.\n", 4818 device, swapchain_desc, mode, callback, reset_state); 4819 4820 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); 4821 4822 if (!(swapchain = wined3d_device_get_swapchain(device, 0))) 4823 { 4824 ERR("Failed to get the first implicit swapchain.\n"); 4825 return WINED3DERR_INVALIDCALL; 4826 } 4827 4828 if (reset_state) 4829 { 4830 if (device->logo_texture) 4831 { 4832 wined3d_texture_decref(device->logo_texture); 4833 device->logo_texture = NULL; 4834 } 4835 if (device->cursor_texture) 4836 { 4837 wined3d_texture_decref(device->cursor_texture); 4838 device->cursor_texture = NULL; 4839 } 4840 state_unbind_resources(&device->state); 4841 } 4842 4843 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) 4844 { 4845 wined3d_device_set_rendertarget_view(device, i, NULL, FALSE); 4846 } 4847 wined3d_device_set_depth_stencil_view(device, NULL); 4848 4849 if (reset_state) 4850 { 4851 LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) 4852 { 4853 TRACE("Enumerating resource %p.\n", resource); 4854 if (FAILED(hr = callback(resource))) 4855 return hr; 4856 } 4857 } 4858 4859 TRACE("New params:\n"); 4860 TRACE("backbuffer_width %u\n", swapchain_desc->backbuffer_width); 4861 TRACE("backbuffer_height %u\n", swapchain_desc->backbuffer_height); 4862 TRACE("backbuffer_format %s\n", debug_d3dformat(swapchain_desc->backbuffer_format)); 4863 TRACE("backbuffer_count %u\n", swapchain_desc->backbuffer_count); 4864 TRACE("multisample_type %#x\n", swapchain_desc->multisample_type); 4865 TRACE("multisample_quality %u\n", swapchain_desc->multisample_quality); 4866 TRACE("swap_effect %#x\n", swapchain_desc->swap_effect); 4867 TRACE("device_window %p\n", swapchain_desc->device_window); 4868 TRACE("windowed %#x\n", swapchain_desc->windowed); 4869 TRACE("enable_auto_depth_stencil %#x\n", swapchain_desc->enable_auto_depth_stencil); 4870 if (swapchain_desc->enable_auto_depth_stencil) 4871 TRACE("auto_depth_stencil_format %s\n", debug_d3dformat(swapchain_desc->auto_depth_stencil_format)); 4872 TRACE("flags %#x\n", swapchain_desc->flags); 4873 TRACE("refresh_rate %u\n", swapchain_desc->refresh_rate); 4874 TRACE("auto_restore_display_mode %#x\n", swapchain_desc->auto_restore_display_mode); 4875 4876 if (swapchain_desc->backbuffer_usage && swapchain_desc->backbuffer_usage != WINED3DUSAGE_RENDERTARGET) 4877 FIXME("Got unexpected backbuffer usage %#x.\n", swapchain_desc->backbuffer_usage); 4878 4879 if (swapchain_desc->swap_effect != WINED3D_SWAP_EFFECT_DISCARD 4880 && swapchain_desc->swap_effect != WINED3D_SWAP_EFFECT_SEQUENTIAL 4881 && swapchain_desc->swap_effect != WINED3D_SWAP_EFFECT_COPY) 4882 FIXME("Unimplemented swap effect %#x.\n", swapchain_desc->swap_effect); 4883 4884 /* No special treatment of these parameters. Just store them */ 4885 swapchain->desc.swap_effect = swapchain_desc->swap_effect; 4886 swapchain->desc.enable_auto_depth_stencil = swapchain_desc->enable_auto_depth_stencil; 4887 swapchain->desc.auto_depth_stencil_format = swapchain_desc->auto_depth_stencil_format; 4888 swapchain->desc.flags = swapchain_desc->flags; 4889 swapchain->desc.refresh_rate = swapchain_desc->refresh_rate; 4890 swapchain->desc.auto_restore_display_mode = swapchain_desc->auto_restore_display_mode; 4891 4892 if (swapchain_desc->device_window 4893 && swapchain_desc->device_window != swapchain->desc.device_window) 4894 { 4895 TRACE("Changing the device window from %p to %p.\n", 4896 swapchain->desc.device_window, swapchain_desc->device_window); 4897 swapchain->desc.device_window = swapchain_desc->device_window; 4898 swapchain->device_window = swapchain_desc->device_window; 4899 wined3d_swapchain_set_window(swapchain, NULL); 4900 } 4901 4902 backbuffer_resized = swapchain_desc->backbuffer_width != swapchain->desc.backbuffer_width 4903 || swapchain_desc->backbuffer_height != swapchain->desc.backbuffer_height; 4904 4905 if (!swapchain_desc->windowed != !swapchain->desc.windowed 4906 || swapchain->reapply_mode || mode 4907 || (!swapchain_desc->windowed && backbuffer_resized)) 4908 { 4909 if (FAILED(hr = wined3d_swapchain_set_fullscreen(swapchain, swapchain_desc, mode))) 4910 return hr; 4911 } 4912 else if (!swapchain_desc->windowed) 4913 { 4914 DWORD style = device->style; 4915 DWORD exStyle = device->exStyle; 4916 /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into 4917 * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call 4918 * Reset to clear up their mess. Guild Wars also loses the device during that. 4919 */ 4920 device->style = 0; 4921 device->exStyle = 0; 4922 wined3d_device_setup_fullscreen_window(device, swapchain->device_window, 4923 swapchain_desc->backbuffer_width, 4924 swapchain_desc->backbuffer_height); 4925 device->style = style; 4926 device->exStyle = exStyle; 4927 } 4928 4929 if (FAILED(hr = wined3d_swapchain_resize_buffers(swapchain, swapchain_desc->backbuffer_count, 4930 swapchain_desc->backbuffer_width, swapchain_desc->backbuffer_height, swapchain_desc->backbuffer_format, 4931 swapchain_desc->multisample_type, swapchain_desc->multisample_quality))) 4932 return hr; 4933 4934 if (device->auto_depth_stencil_view) 4935 { 4936 wined3d_rendertarget_view_decref(device->auto_depth_stencil_view); 4937 device->auto_depth_stencil_view = NULL; 4938 } 4939 if (swapchain->desc.enable_auto_depth_stencil) 4940 { 4941 struct wined3d_resource_desc texture_desc; 4942 struct wined3d_texture *texture; 4943 DWORD flags = 0; 4944 4945 TRACE("Creating the depth stencil buffer.\n"); 4946 4947 texture_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 4948 texture_desc.format = swapchain->desc.auto_depth_stencil_format; 4949 texture_desc.multisample_type = swapchain->desc.multisample_type; 4950 texture_desc.multisample_quality = swapchain->desc.multisample_quality; 4951 texture_desc.usage = WINED3DUSAGE_DEPTHSTENCIL; 4952 texture_desc.access = WINED3D_RESOURCE_ACCESS_GPU; 4953 texture_desc.width = swapchain->desc.backbuffer_width; 4954 texture_desc.height = swapchain->desc.backbuffer_height; 4955 texture_desc.depth = 1; 4956 texture_desc.size = 0; 4957 4958 if (swapchain_desc->flags & WINED3D_SWAPCHAIN_GDI_COMPATIBLE) 4959 flags |= WINED3D_TEXTURE_CREATE_GET_DC; 4960 4961 if (FAILED(hr = device->device_parent->ops->create_swapchain_texture(device->device_parent, 4962 device->device_parent, &texture_desc, flags, &texture))) 4963 { 4964 ERR("Failed to create the auto depth/stencil surface, hr %#x.\n", hr); 4965 return WINED3DERR_INVALIDCALL; 4966 } 4967 4968 view_desc.format_id = texture->resource.format->id; 4969 view_desc.flags = 0; 4970 view_desc.u.texture.level_idx = 0; 4971 view_desc.u.texture.level_count = 1; 4972 view_desc.u.texture.layer_idx = 0; 4973 view_desc.u.texture.layer_count = 1; 4974 hr = wined3d_rendertarget_view_create(&view_desc, &texture->resource, 4975 NULL, &wined3d_null_parent_ops, &device->auto_depth_stencil_view); 4976 wined3d_texture_decref(texture); 4977 if (FAILED(hr)) 4978 { 4979 ERR("Failed to create rendertarget view, hr %#x.\n", hr); 4980 return hr; 4981 } 4982 4983 wined3d_device_set_depth_stencil_view(device, device->auto_depth_stencil_view); 4984 } 4985 4986 if (device->back_buffer_view) 4987 { 4988 wined3d_rendertarget_view_decref(device->back_buffer_view); 4989 device->back_buffer_view = NULL; 4990 } 4991 if (swapchain->desc.backbuffer_count && swapchain->desc.backbuffer_usage & WINED3DUSAGE_RENDERTARGET) 4992 { 4993 struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource; 4994 4995 view_desc.format_id = back_buffer->format->id; 4996 view_desc.flags = 0; 4997 view_desc.u.texture.level_idx = 0; 4998 view_desc.u.texture.level_count = 1; 4999 view_desc.u.texture.layer_idx = 0; 5000 view_desc.u.texture.layer_count = 1; 5001 if (FAILED(hr = wined3d_rendertarget_view_create(&view_desc, back_buffer, 5002 NULL, &wined3d_null_parent_ops, &device->back_buffer_view))) 5003 { 5004 ERR("Failed to create rendertarget view, hr %#x.\n", hr); 5005 return hr; 5006 } 5007 } 5008 5009 wine_rb_clear(&device->samplers, device_free_sampler, NULL); 5010 5011 if (reset_state) 5012 { 5013 TRACE("Resetting stateblock.\n"); 5014 if (device->recording) 5015 { 5016 wined3d_stateblock_decref(device->recording); 5017 device->recording = NULL; 5018 } 5019 wined3d_cs_emit_reset_state(device->cs); 5020 state_cleanup(&device->state); 5021 5022 if (device->d3d_initialized) 5023 wined3d_device_delete_opengl_contexts(device); 5024 5025 memset(&device->state, 0, sizeof(device->state)); 5026 state_init(&device->state, &device->fb, &device->adapter->gl_info, 5027 &device->adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT); 5028 device->update_state = &device->state; 5029 5030 device_init_swapchain_state(device, swapchain); 5031 if (wined3d_settings.logo) 5032 device_load_logo(device, wined3d_settings.logo); 5033 } 5034 else if (device->back_buffer_view) 5035 { 5036 struct wined3d_rendertarget_view *view = device->back_buffer_view; 5037 struct wined3d_state *state = &device->state; 5038 5039 wined3d_device_set_rendertarget_view(device, 0, view, FALSE); 5040 5041 /* Note the min_z / max_z is not reset. */ 5042 state->viewports[0].x = 0; 5043 state->viewports[0].y = 0; 5044 state->viewports[0].width = view->width; 5045 state->viewports[0].height = view->height; 5046 state->viewport_count = 1; 5047 wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports); 5048 5049 SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height); 5050 state->scissor_rect_count = 1; 5051 wined3d_cs_emit_set_scissor_rects(device->cs, 1, state->scissor_rects); 5052 } 5053 5054 if (device->d3d_initialized) 5055 { 5056 if (reset_state) 5057 hr = wined3d_device_create_primary_opengl_context(device); 5058 } 5059 5060 /* All done. There is no need to reload resources or shaders, this will happen automatically on the 5061 * first use 5062 */ 5063 return hr; 5064 } 5065 5066 HRESULT CDECL wined3d_device_set_dialog_box_mode(struct wined3d_device *device, BOOL enable_dialogs) 5067 { 5068 TRACE("device %p, enable_dialogs %#x.\n", device, enable_dialogs); 5069 5070 if (!enable_dialogs) FIXME("Dialogs cannot be disabled yet.\n"); 5071 5072 return WINED3D_OK; 5073 } 5074 5075 5076 void CDECL wined3d_device_get_creation_parameters(const struct wined3d_device *device, 5077 struct wined3d_device_creation_parameters *parameters) 5078 { 5079 TRACE("device %p, parameters %p.\n", device, parameters); 5080 5081 *parameters = device->create_parms; 5082 } 5083 5084 struct wined3d * CDECL wined3d_device_get_wined3d(const struct wined3d_device *device) 5085 { 5086 TRACE("device %p.\n", device); 5087 5088 return device->wined3d; 5089 } 5090 5091 void CDECL wined3d_device_set_gamma_ramp(const struct wined3d_device *device, 5092 UINT swapchain_idx, DWORD flags, const struct wined3d_gamma_ramp *ramp) 5093 { 5094 struct wined3d_swapchain *swapchain; 5095 5096 TRACE("device %p, swapchain_idx %u, flags %#x, ramp %p.\n", 5097 device, swapchain_idx, flags, ramp); 5098 5099 if ((swapchain = wined3d_device_get_swapchain(device, swapchain_idx))) 5100 wined3d_swapchain_set_gamma_ramp(swapchain, flags, ramp); 5101 } 5102 5103 void CDECL wined3d_device_get_gamma_ramp(const struct wined3d_device *device, 5104 UINT swapchain_idx, struct wined3d_gamma_ramp *ramp) 5105 { 5106 struct wined3d_swapchain *swapchain; 5107 5108 TRACE("device %p, swapchain_idx %u, ramp %p.\n", 5109 device, swapchain_idx, ramp); 5110 5111 if ((swapchain = wined3d_device_get_swapchain(device, swapchain_idx))) 5112 wined3d_swapchain_get_gamma_ramp(swapchain, ramp); 5113 } 5114 5115 void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) 5116 { 5117 TRACE("device %p, resource %p.\n", device, resource); 5118 5119 wined3d_not_from_cs(device->cs); 5120 5121 list_add_head(&device->resources, &resource->resource_list_entry); 5122 } 5123 5124 static void device_resource_remove(struct wined3d_device *device, struct wined3d_resource *resource) 5125 { 5126 TRACE("device %p, resource %p.\n", device, resource); 5127 5128 wined3d_not_from_cs(device->cs); 5129 5130 list_remove(&resource->resource_list_entry); 5131 } 5132 5133 void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) 5134 { 5135 enum wined3d_resource_type type = resource->type; 5136 struct wined3d_rendertarget_view *rtv; 5137 unsigned int i; 5138 5139 TRACE("device %p, resource %p, type %s.\n", device, resource, debug_d3dresourcetype(type)); 5140 5141 if (device->d3d_initialized) 5142 { 5143 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) 5144 { 5145 if ((rtv = device->fb.render_targets[i]) && rtv->resource == resource) 5146 ERR("Resource %p is still in use as render target %u.\n", resource, i); 5147 } 5148 5149 if ((rtv = device->fb.depth_stencil) && rtv->resource == resource) 5150 ERR("Resource %p is still in use as depth/stencil buffer.\n", resource); 5151 } 5152 5153 switch (type) 5154 { 5155 case WINED3D_RTYPE_TEXTURE_1D: 5156 case WINED3D_RTYPE_TEXTURE_2D: 5157 case WINED3D_RTYPE_TEXTURE_3D: 5158 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) 5159 { 5160 if (&device->state.textures[i]->resource == resource) 5161 { 5162 ERR("Texture resource %p is still in use, stage %u.\n", resource, i); 5163 device->state.textures[i] = NULL; 5164 } 5165 5166 if (device->recording && &device->update_state->textures[i]->resource == resource) 5167 { 5168 ERR("Texture resource %p is still in use by recording stateblock %p, stage %u.\n", 5169 resource, device->recording, i); 5170 device->update_state->textures[i] = NULL; 5171 } 5172 } 5173 break; 5174 5175 case WINED3D_RTYPE_BUFFER: 5176 for (i = 0; i < MAX_STREAMS; ++i) 5177 { 5178 if (&device->state.streams[i].buffer->resource == resource) 5179 { 5180 ERR("Buffer resource %p is still in use, stream %u.\n", resource, i); 5181 device->state.streams[i].buffer = NULL; 5182 } 5183 5184 if (device->recording && &device->update_state->streams[i].buffer->resource == resource) 5185 { 5186 ERR("Buffer resource %p is still in use by stateblock %p, stream %u.\n", 5187 resource, device->recording, i); 5188 device->update_state->streams[i].buffer = NULL; 5189 } 5190 } 5191 5192 if (&device->state.index_buffer->resource == resource) 5193 { 5194 ERR("Buffer resource %p is still in use as index buffer.\n", resource); 5195 device->state.index_buffer = NULL; 5196 } 5197 5198 if (device->recording && &device->update_state->index_buffer->resource == resource) 5199 { 5200 ERR("Buffer resource %p is still in use by stateblock %p as index buffer.\n", 5201 resource, device->recording); 5202 device->update_state->index_buffer = NULL; 5203 } 5204 break; 5205 5206 default: 5207 break; 5208 } 5209 5210 /* Remove the resource from the resourceStore */ 5211 device_resource_remove(device, resource); 5212 5213 TRACE("Resource released.\n"); 5214 } 5215 5216 static int wined3d_sampler_compare(const void *key, const struct wine_rb_entry *entry) 5217 { 5218 const struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry); 5219 5220 return memcmp(&sampler->desc, key, sizeof(sampler->desc)); 5221 } 5222 5223 HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d, 5224 UINT adapter_idx, enum wined3d_device_type device_type, HWND focus_window, DWORD flags, 5225 BYTE surface_alignment, struct wined3d_device_parent *device_parent) 5226 { 5227 struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx]; 5228 const struct fragment_pipeline *fragment_pipeline; 5229 const struct wined3d_vertex_pipe_ops *vertex_pipeline; 5230 unsigned int i; 5231 HRESULT hr; 5232 5233 device->ref = 1; 5234 device->wined3d = wined3d; 5235 wined3d_incref(device->wined3d); 5236 device->adapter = wined3d->adapter_count ? adapter : NULL; 5237 device->device_parent = device_parent; 5238 list_init(&device->resources); 5239 list_init(&device->shaders); 5240 device->surface_alignment = surface_alignment; 5241 5242 /* Save the creation parameters. */ 5243 device->create_parms.adapter_idx = adapter_idx; 5244 device->create_parms.device_type = device_type; 5245 device->create_parms.focus_window = focus_window; 5246 device->create_parms.flags = flags; 5247 5248 device->shader_backend = adapter->shader_backend; 5249 5250 vertex_pipeline = adapter->vertex_pipe; 5251 5252 fragment_pipeline = adapter->fragment_pipe; 5253 5254 wine_rb_init(&device->samplers, wined3d_sampler_compare); 5255 5256 if (vertex_pipeline->vp_states && fragment_pipeline->states 5257 && FAILED(hr = compile_state_table(device->StateTable, device->multistate_funcs, 5258 &adapter->gl_info, &adapter->d3d_info, vertex_pipeline, 5259 fragment_pipeline, misc_state_template))) 5260 { 5261 ERR("Failed to compile state table, hr %#x.\n", hr); 5262 wine_rb_destroy(&device->samplers, NULL, NULL); 5263 wined3d_decref(device->wined3d); 5264 return hr; 5265 } 5266 5267 state_init(&device->state, &device->fb, &adapter->gl_info, 5268 &adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT); 5269 device->update_state = &device->state; 5270 5271 device->max_frame_latency = 3; 5272 5273 if (!(device->cs = wined3d_cs_create(device))) 5274 { 5275 WARN("Failed to create command stream.\n"); 5276 state_cleanup(&device->state); 5277 hr = E_FAIL; 5278 goto err; 5279 } 5280 5281 return WINED3D_OK; 5282 5283 err: 5284 for (i = 0; i < ARRAY_SIZE(device->multistate_funcs); ++i) 5285 { 5286 heap_free(device->multistate_funcs[i]); 5287 } 5288 wine_rb_destroy(&device->samplers, NULL, NULL); 5289 wined3d_decref(device->wined3d); 5290 return hr; 5291 } 5292 5293 void device_invalidate_state(const struct wined3d_device *device, DWORD state) 5294 { 5295 DWORD rep = device->StateTable[state].representative; 5296 struct wined3d_context *context; 5297 DWORD idx; 5298 BYTE shift; 5299 UINT i; 5300 5301 wined3d_from_cs(device->cs); 5302 5303 if (STATE_IS_COMPUTE(state)) 5304 { 5305 for (i = 0; i < device->context_count; ++i) 5306 context_invalidate_compute_state(device->contexts[i], state); 5307 return; 5308 } 5309 5310 for (i = 0; i < device->context_count; ++i) 5311 { 5312 context = device->contexts[i]; 5313 if(isStateDirty(context, rep)) continue; 5314 5315 context->dirtyArray[context->numDirtyEntries++] = rep; 5316 idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT); 5317 shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1); 5318 context->isStateDirty[idx] |= (1u << shift); 5319 } 5320 } 5321 5322 LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode, 5323 UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) 5324 { 5325 if (device->filter_messages && message != WM_DISPLAYCHANGE) 5326 { 5327 TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n", 5328 window, message, wparam, lparam); 5329 if (unicode) 5330 return DefWindowProcW(window, message, wparam, lparam); 5331 else 5332 return DefWindowProcA(window, message, wparam, lparam); 5333 } 5334 5335 if (message == WM_DESTROY) 5336 { 5337 TRACE("unregister window %p.\n", window); 5338 wined3d_unregister_window(window); 5339 5340 if (InterlockedCompareExchangePointer((void **)&device->focus_window, NULL, window) != window) 5341 ERR("Window %p is not the focus window for device %p.\n", window, device); 5342 } 5343 else if (message == WM_DISPLAYCHANGE) 5344 { 5345 device->device_parent->ops->mode_changed(device->device_parent); 5346 } 5347 else if (message == WM_ACTIVATEAPP) 5348 { 5349 UINT i; 5350 5351 for (i = 0; i < device->swapchain_count; i++) 5352 wined3d_swapchain_activate(device->swapchains[i], wparam); 5353 5354 device->device_parent->ops->activate(device->device_parent, wparam); 5355 } 5356 else if (message == WM_SYSCOMMAND) 5357 { 5358 if (wparam == SC_RESTORE && device->wined3d->flags & WINED3D_HANDLE_RESTORE) 5359 { 5360 if (unicode) 5361 DefWindowProcW(window, message, wparam, lparam); 5362 else 5363 DefWindowProcA(window, message, wparam, lparam); 5364 } 5365 } 5366 5367 if (unicode) 5368 return CallWindowProcW(proc, window, message, wparam, lparam); 5369 else 5370 return CallWindowProcA(proc, window, message, wparam, lparam); 5371 } 5372