reg/tests: Test import with non-standard registry file headers.
[wine.git] / dlls / wined3d / view.c
blobb64b5e777d1be68154bf530df0d127e6c0f9d923
1 /*
2 * Copyright 2009, 2011 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include "wined3d_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 #define WINED3D_VIEW_CUBE_ARRAY (WINED3D_VIEW_TEXTURE_CUBE | WINED3D_VIEW_TEXTURE_ARRAY)
29 static BOOL is_stencil_view_format(const struct wined3d_format *format)
31 return format->id == WINED3DFMT_X24_TYPELESS_G8_UINT
32 || format->id == WINED3DFMT_X32_TYPELESS_G8X24_UINT;
35 static GLenum get_texture_view_target(const struct wined3d_gl_info *gl_info,
36 const struct wined3d_view_desc *desc, const struct wined3d_texture *texture)
38 static const struct
40 GLenum texture_target;
41 unsigned int view_flags;
42 GLenum view_target;
43 enum wined3d_gl_extension extension;
45 view_types[] =
47 {GL_TEXTURE_2D, 0, GL_TEXTURE_2D},
48 {GL_TEXTURE_2D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
49 {GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_2D},
50 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
51 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_CUBE, GL_TEXTURE_CUBE_MAP},
52 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_CUBE_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY, ARB_TEXTURE_CUBE_MAP_ARRAY},
53 {GL_TEXTURE_3D, 0, GL_TEXTURE_3D},
55 unsigned int i;
57 for (i = 0; i < ARRAY_SIZE(view_types); ++i)
59 if (view_types[i].texture_target != texture->target || view_types[i].view_flags != desc->flags)
60 continue;
61 if (gl_info->supported[view_types[i].extension])
62 return view_types[i].view_target;
64 FIXME("Extension %#x not supported.\n", view_types[i].extension);
67 FIXME("Unhandled view flags %#x for texture target %#x.\n", desc->flags, texture->target);
68 return texture->target;
71 static void create_texture_view(struct wined3d_gl_view *view, GLenum view_target,
72 const struct wined3d_view_desc *desc, struct wined3d_texture *texture,
73 const struct wined3d_format *view_format)
75 const struct wined3d_gl_info *gl_info;
76 unsigned int layer_idx, layer_count;
77 struct wined3d_context *context;
78 struct gl_texture *gl_texture;
80 view->target = view_target;
82 context = context_acquire(texture->resource.device, NULL, 0);
83 gl_info = context->gl_info;
85 if (!gl_info->supported[ARB_TEXTURE_VIEW])
87 context_release(context);
88 FIXME("OpenGL implementation does not support texture views.\n");
89 return;
92 wined3d_texture_prepare_texture(texture, context, FALSE);
93 gl_texture = wined3d_texture_get_gl_texture(texture, FALSE);
95 layer_idx = desc->u.texture.layer_idx;
96 layer_count = desc->u.texture.layer_count;
97 if (view_target == GL_TEXTURE_3D && (layer_idx || layer_count != 1))
99 FIXME("Depth slice (%u-%u) not supported.\n", layer_idx, layer_count);
100 layer_idx = 0;
101 layer_count = 1;
104 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
105 GL_EXTCALL(glTextureView(view->name, view->target, gl_texture->name, view_format->glInternal,
106 desc->u.texture.level_idx, desc->u.texture.level_count,
107 layer_idx, layer_count));
108 checkGLcall("Create texture view");
110 if (is_stencil_view_format(view_format))
112 static const GLint swizzle[] = {GL_ZERO, GL_RED, GL_ZERO, GL_ZERO};
114 if (!gl_info->supported[ARB_STENCIL_TEXTURING])
116 context_release(context);
117 FIXME("OpenGL implementation does not support stencil texturing.\n");
118 return;
121 context_bind_texture(context, view->target, view->name);
122 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
123 gl_info->gl_ops.gl.p_glTexParameteri(view->target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
124 checkGLcall("Initialize stencil view");
126 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
127 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
130 context_release(context);
133 static void create_buffer_texture(struct wined3d_gl_view *view,
134 struct wined3d_buffer *buffer, const struct wined3d_format *view_format,
135 unsigned int offset, unsigned int size)
137 const struct wined3d_gl_info *gl_info;
138 struct wined3d_context *context;
140 context = context_acquire(buffer->resource.device, NULL, 0);
141 gl_info = context->gl_info;
142 if (!gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
144 FIXME("OpenGL implementation does not support buffer textures.\n");
145 context_release(context);
146 return;
149 if ((offset & (gl_info->limits.texture_buffer_offset_alignment - 1)))
151 FIXME("Buffer offset %u is not %u byte aligned.\n",
152 offset, gl_info->limits.texture_buffer_offset_alignment);
153 context_release(context);
154 return;
157 wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER);
159 view->target = GL_TEXTURE_BUFFER;
160 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
162 context_bind_texture(context, GL_TEXTURE_BUFFER, view->name);
163 if (gl_info->supported[ARB_TEXTURE_BUFFER_RANGE])
165 GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER, view_format->glInternal,
166 buffer->buffer_object, offset, size));
168 else
170 if (offset || size != buffer->resource.size)
171 FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n");
172 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, view_format->glInternal, buffer->buffer_object));
174 checkGLcall("Create buffer texture");
176 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
177 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
179 context_release(context);
182 static void create_buffer_view(struct wined3d_gl_view *view,
183 const struct wined3d_view_desc *desc, struct wined3d_buffer *buffer,
184 const struct wined3d_format *view_format)
186 unsigned int offset, size;
188 if (desc->format_id == WINED3DFMT_UNKNOWN)
190 offset = desc->u.buffer.start_idx * buffer->desc.structure_byte_stride;
191 size = desc->u.buffer.count * buffer->desc.structure_byte_stride;
193 else
195 offset = desc->u.buffer.start_idx * view_format->byte_count;
196 size = desc->u.buffer.count * view_format->byte_count;
199 create_buffer_texture(view, buffer, view_format, offset, size);
202 ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view)
204 ULONG refcount = InterlockedIncrement(&view->refcount);
206 TRACE("%p increasing refcount to %u.\n", view, refcount);
208 return refcount;
211 static void wined3d_rendertarget_view_destroy_object(void *object)
213 HeapFree(GetProcessHeap(), 0, object);
216 ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view)
218 ULONG refcount = InterlockedDecrement(&view->refcount);
220 TRACE("%p decreasing refcount to %u.\n", view, refcount);
222 if (!refcount)
224 struct wined3d_resource *resource = view->resource;
225 struct wined3d_device *device = resource->device;
227 /* Call wined3d_object_destroyed() before releasing the resource,
228 * since releasing the resource may end up destroying the parent. */
229 view->parent_ops->wined3d_object_destroyed(view->parent);
230 wined3d_cs_destroy_object(device->cs, wined3d_rendertarget_view_destroy_object, view);
231 wined3d_resource_decref(resource);
234 return refcount;
237 void * CDECL wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view)
239 TRACE("view %p.\n", view);
241 return view->parent;
244 void * CDECL wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view *view)
246 struct wined3d_texture *texture;
248 TRACE("view %p.\n", view);
250 if (view->resource->type == WINED3D_RTYPE_BUFFER)
251 return wined3d_buffer_get_parent(buffer_from_resource(view->resource));
253 texture = texture_from_resource(view->resource);
255 return texture->sub_resources[view->sub_resource_idx].parent;
258 void CDECL wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view *view, void *parent)
260 TRACE("view %p, parent %p.\n", view, parent);
262 view->parent = parent;
265 struct wined3d_resource * CDECL wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view)
267 TRACE("view %p.\n", view);
269 return view->resource;
272 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view,
273 const struct wined3d_context *context, unsigned int *width, unsigned int *height)
275 const struct wined3d_texture *texture;
277 if (view->resource->type != WINED3D_RTYPE_TEXTURE_2D)
279 FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(view->resource->type));
280 *width = 0;
281 *height = 0;
282 return;
285 texture = texture_from_resource(view->resource);
286 if (texture->swapchain)
288 /* The drawable size of an onscreen drawable is the surface size.
289 * (Actually: The window size, but the surface is created in window
290 * size.) */
291 *width = context->current_rt.texture->resource.width;
292 *height = context->current_rt.texture->resource.height;
294 else if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
296 const struct wined3d_swapchain *swapchain = context->swapchain;
298 /* The drawable size of a backbuffer / aux buffer offscreen target is
299 * the size of the current context's drawable, which is the size of
300 * the back buffer of the swapchain the active context belongs to. */
301 *width = swapchain->desc.backbuffer_width;
302 *height = swapchain->desc.backbuffer_height;
304 else
306 struct wined3d_surface *rt;
308 /* The drawable size of an FBO target is the OpenGL texture size,
309 * which is the power of two size. */
310 rt = context->current_rt.texture->sub_resources[context->current_rt.sub_resource_idx].u.surface;
311 *width = wined3d_texture_get_level_pow2_width(rt->container, rt->texture_level);
312 *height = wined3d_texture_get_level_pow2_height(rt->container, rt->texture_level);
316 static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
317 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
318 void *parent, const struct wined3d_parent_ops *parent_ops)
320 const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
322 view->refcount = 1;
323 view->parent = parent;
324 view->parent_ops = parent_ops;
326 view->format = wined3d_get_format(gl_info, desc->format_id, resource->usage);
327 view->format_flags = view->format->flags[resource->gl_type];
329 if (wined3d_format_is_typeless(view->format))
331 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view->format->id));
332 return E_INVALIDARG;
335 if (resource->type == WINED3D_RTYPE_BUFFER)
337 view->sub_resource_idx = 0;
338 view->buffer_offset = desc->u.buffer.start_idx;
339 view->width = desc->u.buffer.count;
340 view->height = 1;
341 view->depth = 1;
343 else
345 struct wined3d_texture *texture = texture_from_resource(resource);
346 unsigned int depth_or_layer_count;
348 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
349 depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
350 else
351 depth_or_layer_count = texture->layer_count;
353 if (desc->u.texture.level_idx >= texture->level_count
354 || desc->u.texture.level_count != 1
355 || desc->u.texture.layer_idx >= depth_or_layer_count
356 || !desc->u.texture.layer_count
357 || desc->u.texture.layer_count > depth_or_layer_count - desc->u.texture.layer_idx)
358 return E_INVALIDARG;
360 view->sub_resource_idx = desc->u.texture.level_idx;
361 if (resource->type != WINED3D_RTYPE_TEXTURE_3D)
362 view->sub_resource_idx += desc->u.texture.layer_idx * texture->level_count;
363 view->buffer_offset = 0;
364 view->width = wined3d_texture_get_level_width(texture, desc->u.texture.level_idx);
365 view->height = wined3d_texture_get_level_height(texture, desc->u.texture.level_idx);
366 view->depth = desc->u.texture.layer_count;
368 wined3d_resource_incref(view->resource = resource);
370 return WINED3D_OK;
373 HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_view_desc *desc,
374 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
375 struct wined3d_rendertarget_view **view)
377 struct wined3d_rendertarget_view *object;
378 HRESULT hr;
380 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
381 desc, resource, parent, parent_ops, view);
383 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
384 return E_OUTOFMEMORY;
386 if (FAILED(hr = wined3d_rendertarget_view_init(object, desc, resource, parent, parent_ops)))
388 HeapFree(GetProcessHeap(), 0, object);
389 WARN("Failed to initialise view, hr %#x.\n", hr);
390 return hr;
393 TRACE("Created render target view %p.\n", object);
394 *view = object;
396 return hr;
399 HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture,
400 unsigned int sub_resource_idx, void *parent, const struct wined3d_parent_ops *parent_ops,
401 struct wined3d_rendertarget_view **view)
403 struct wined3d_view_desc desc;
405 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
406 texture, sub_resource_idx, parent, parent_ops, view);
408 desc.format_id = texture->resource.format->id;
409 desc.flags = 0;
410 desc.u.texture.level_idx = sub_resource_idx % texture->level_count;
411 desc.u.texture.level_count = 1;
412 desc.u.texture.layer_idx = sub_resource_idx / texture->level_count;
413 desc.u.texture.layer_count = 1;
415 return wined3d_rendertarget_view_create(&desc, &texture->resource, parent, parent_ops, view);
418 ULONG CDECL wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view *view)
420 ULONG refcount = InterlockedIncrement(&view->refcount);
422 TRACE("%p increasing refcount to %u.\n", view, refcount);
424 return refcount;
427 static void wined3d_shader_resource_view_destroy_object(void *object)
429 struct wined3d_shader_resource_view *view = object;
431 if (view->gl_view.name)
433 const struct wined3d_gl_info *gl_info;
434 struct wined3d_context *context;
436 context = context_acquire(view->resource->device, NULL, 0);
437 gl_info = context->gl_info;
438 gl_info->gl_ops.gl.p_glDeleteTextures(1, &view->gl_view.name);
439 checkGLcall("glDeleteTextures");
440 context_release(context);
443 HeapFree(GetProcessHeap(), 0, view);
446 ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view *view)
448 ULONG refcount = InterlockedDecrement(&view->refcount);
450 TRACE("%p decreasing refcount to %u.\n", view, refcount);
452 if (!refcount)
454 struct wined3d_resource *resource = view->resource;
455 struct wined3d_device *device = resource->device;
457 /* Call wined3d_object_destroyed() before releasing the resource,
458 * since releasing the resource may end up destroying the parent. */
459 view->parent_ops->wined3d_object_destroyed(view->parent);
460 wined3d_cs_destroy_object(device->cs, wined3d_shader_resource_view_destroy_object, view);
461 wined3d_resource_decref(resource);
464 return refcount;
467 void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view *view)
469 TRACE("view %p.\n", view);
471 return view->parent;
474 static void wined3d_shader_resource_view_cs_init(void *object)
476 struct wined3d_shader_resource_view *view = object;
477 struct wined3d_resource *resource = view->resource;
478 const struct wined3d_format *view_format;
479 const struct wined3d_gl_info *gl_info;
480 const struct wined3d_view_desc *desc;
481 GLenum view_target;
483 view_format = view->format;
484 gl_info = &resource->device->adapter->gl_info;
485 desc = &view->desc;
487 if (resource->type == WINED3D_RTYPE_BUFFER)
489 struct wined3d_buffer *buffer = buffer_from_resource(resource);
491 create_buffer_view(&view->gl_view, desc, buffer, view_format);
493 else
495 struct wined3d_texture *texture = texture_from_resource(resource);
497 view_target = get_texture_view_target(gl_info, desc, texture);
499 if (resource->format->id == view_format->id && texture->target == view_target
500 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture->level_count
501 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture->layer_count
502 && !is_stencil_view_format(view_format))
504 TRACE("Creating identity shader resource view.\n");
506 else if (texture->swapchain && texture->swapchain->desc.backbuffer_count > 1)
508 FIXME("Swapchain shader resource views not supported.\n");
510 else if (resource->format->typeless_id == view_format->typeless_id
511 && resource->format->gl_view_class == view_format->gl_view_class)
513 create_texture_view(&view->gl_view, view_target, desc, texture, view_format);
515 else
517 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
518 debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
523 static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
524 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
525 void *parent, const struct wined3d_parent_ops *parent_ops)
527 const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
528 const struct wined3d_format *view_format;
530 view_format = wined3d_get_format(gl_info, desc->format_id, resource->usage);
531 if (resource->type == WINED3D_RTYPE_BUFFER && desc->flags & WINED3D_VIEW_BUFFER_RAW)
533 if (view_format->id != WINED3DFMT_R32_TYPELESS)
535 WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(view_format->id));
536 return E_INVALIDARG;
539 view_format = wined3d_get_format(gl_info, WINED3DFMT_R32_UINT, resource->usage);
542 if (wined3d_format_is_typeless(view_format))
544 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view_format->id));
545 return E_INVALIDARG;
548 if (resource->type == WINED3D_RTYPE_BUFFER)
550 struct wined3d_buffer *buffer = buffer_from_resource(resource);
551 unsigned int buffer_size, element_size;
553 if (buffer->desc.structure_byte_stride)
555 if (desc->format_id != WINED3DFMT_UNKNOWN)
557 WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc->format_id));
558 return E_INVALIDARG;
561 view_format = wined3d_get_format(gl_info, WINED3DFMT_R32_UINT, resource->usage);
562 element_size = buffer->desc.structure_byte_stride;
564 else
566 element_size = view_format->byte_count;
569 if (!element_size)
570 return E_INVALIDARG;
572 buffer_size = buffer->resource.size / element_size;
573 if (desc->u.buffer.start_idx >= buffer_size
574 || desc->u.buffer.count > buffer_size - desc->u.buffer.start_idx)
575 return E_INVALIDARG;
577 else
579 struct wined3d_texture *texture = texture_from_resource(resource);
581 if (!desc->u.texture.level_count
582 || desc->u.texture.level_idx >= texture->level_count
583 || desc->u.texture.level_count > texture->level_count - desc->u.texture.level_idx
584 || !desc->u.texture.layer_count
585 || desc->u.texture.layer_idx >= texture->layer_count
586 || desc->u.texture.layer_count > texture->layer_count - desc->u.texture.layer_idx)
587 return E_INVALIDARG;
590 view->refcount = 1;
591 wined3d_resource_incref(view->resource = resource);
592 view->parent = parent;
593 view->parent_ops = parent_ops;
594 view->format = view_format;
595 view->desc = *desc;
597 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_cs_init, view);
599 return WINED3D_OK;
602 HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_view_desc *desc,
603 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
604 struct wined3d_shader_resource_view **view)
606 struct wined3d_shader_resource_view *object;
607 HRESULT hr;
609 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
610 desc, resource, parent, parent_ops, view);
612 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
613 return E_OUTOFMEMORY;
615 if (FAILED(hr = wined3d_shader_resource_view_init(object, desc, resource, parent, parent_ops)))
617 HeapFree(GetProcessHeap(), 0, object);
618 WARN("Failed to initialise view, hr %#x.\n", hr);
619 return hr;
622 TRACE("Created shader resource view %p.\n", object);
623 *view = object;
625 return WINED3D_OK;
628 void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view,
629 struct wined3d_context *context)
631 struct wined3d_texture *texture;
633 if (view->gl_view.name)
635 context_bind_texture(context, view->gl_view.target, view->gl_view.name);
636 return;
639 if (view->resource->type == WINED3D_RTYPE_BUFFER)
641 FIXME("Buffer shader resources not supported.\n");
642 return;
645 texture = wined3d_texture_from_resource(view->resource);
646 wined3d_texture_bind(texture, context, FALSE);
649 ULONG CDECL wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view *view)
651 ULONG refcount = InterlockedIncrement(&view->refcount);
653 TRACE("%p increasing refcount to %u.\n", view, refcount);
655 return refcount;
658 static void wined3d_unordered_access_view_destroy_object(void *object)
660 HeapFree(GetProcessHeap(), 0, object);
663 ULONG CDECL wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view *view)
665 ULONG refcount = InterlockedDecrement(&view->refcount);
667 TRACE("%p decreasing refcount to %u.\n", view, refcount);
669 if (!refcount)
671 struct wined3d_resource *resource = view->resource;
672 struct wined3d_device *device = resource->device;
674 /* Call wined3d_object_destroyed() before releasing the resource,
675 * since releasing the resource may end up destroying the parent. */
676 view->parent_ops->wined3d_object_destroyed(view->parent);
677 wined3d_cs_destroy_object(device->cs, wined3d_unordered_access_view_destroy_object, view);
678 wined3d_resource_decref(resource);
681 return refcount;
684 void * CDECL wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view *view)
686 TRACE("view %p.\n", view);
688 return view->parent;
691 void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_access_view *view,
692 DWORD location)
694 struct wined3d_resource *resource = view->resource;
695 unsigned int i, sub_resource_idx, layer_count;
696 struct wined3d_texture *texture;
698 if (resource->type == WINED3D_RTYPE_BUFFER)
700 wined3d_buffer_invalidate_location(buffer_from_resource(resource), location);
701 return;
704 texture = texture_from_resource(resource);
706 sub_resource_idx = view->desc.u.texture.layer_idx * texture->level_count + view->desc.u.texture.level_idx;
707 layer_count = (resource->type != WINED3D_RTYPE_TEXTURE_3D) ? view->desc.u.texture.layer_count : 1;
708 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
709 wined3d_texture_invalidate_location(texture, sub_resource_idx, location);
712 static void wined3d_unordered_access_view_cs_init(void *object)
714 struct wined3d_unordered_access_view *view = object;
715 struct wined3d_resource *resource = view->resource;
716 struct wined3d_view_desc *desc = &view->desc;
717 const struct wined3d_gl_info *gl_info;
719 gl_info = &resource->device->adapter->gl_info;
721 if (resource->type == WINED3D_RTYPE_BUFFER)
723 struct wined3d_buffer *buffer = buffer_from_resource(resource);
725 create_buffer_view(&view->gl_view, desc, buffer, view->format);
727 else
729 struct wined3d_texture *texture = texture_from_resource(resource);
730 unsigned int depth_or_layer_count;
732 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
733 depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
734 else
735 depth_or_layer_count = texture->layer_count;
737 if (desc->u.texture.layer_idx || desc->u.texture.layer_count != depth_or_layer_count)
739 create_texture_view(&view->gl_view, get_texture_view_target(gl_info, desc, texture),
740 desc, texture, view->format);
745 static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view,
746 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
747 void *parent, const struct wined3d_parent_ops *parent_ops)
749 const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
751 view->refcount = 1;
752 view->parent = parent;
753 view->parent_ops = parent_ops;
755 view->format = wined3d_get_format(gl_info, desc->format_id, resource->usage);
756 view->desc = *desc;
758 if (resource->type == WINED3D_RTYPE_BUFFER && desc->flags & WINED3D_VIEW_BUFFER_RAW)
760 if (view->format->id != WINED3DFMT_R32_TYPELESS)
762 WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(view->format->id));
763 return E_INVALIDARG;
766 view->format = wined3d_get_format(gl_info, WINED3DFMT_R32_UINT, resource->usage);
769 if (wined3d_format_is_typeless(view->format))
771 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view->format->id));
772 return E_INVALIDARG;
775 if (resource->type == WINED3D_RTYPE_BUFFER)
777 struct wined3d_buffer *buffer = buffer_from_resource(resource);
778 unsigned int buffer_size, element_size;
780 if (buffer->desc.structure_byte_stride)
782 if (desc->format_id != WINED3DFMT_UNKNOWN)
784 WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc->format_id));
785 return E_INVALIDARG;
788 view->format = wined3d_get_format(gl_info, WINED3DFMT_R32_UINT, resource->usage);
789 element_size = buffer->desc.structure_byte_stride;
791 else
793 element_size = view->format->byte_count;
796 if (!element_size)
797 return E_INVALIDARG;
799 buffer_size = buffer->resource.size / element_size;
800 if (desc->u.buffer.start_idx >= buffer_size
801 || desc->u.buffer.count > buffer_size - desc->u.buffer.start_idx)
802 return E_INVALIDARG;
804 else
806 struct wined3d_texture *texture = texture_from_resource(resource);
807 unsigned int depth_or_layer_count;
809 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
810 depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
811 else
812 depth_or_layer_count = texture->layer_count;
814 if (desc->u.texture.level_idx >= texture->level_count
815 || desc->u.texture.level_count != 1
816 || desc->u.texture.layer_idx >= depth_or_layer_count
817 || !desc->u.texture.layer_count
818 || desc->u.texture.layer_count > depth_or_layer_count - desc->u.texture.layer_idx)
819 return E_INVALIDARG;
821 wined3d_resource_incref(view->resource = resource);
823 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_cs_init, view);
825 return WINED3D_OK;
828 HRESULT CDECL wined3d_unordered_access_view_create(const struct wined3d_view_desc *desc,
829 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
830 struct wined3d_unordered_access_view **view)
832 struct wined3d_unordered_access_view *object;
833 HRESULT hr;
835 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
836 desc, resource, parent, parent_ops, view);
838 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
839 return E_OUTOFMEMORY;
841 if (FAILED(hr = wined3d_unordered_access_view_init(object, desc, resource, parent, parent_ops)))
843 HeapFree(GetProcessHeap(), 0, object);
844 WARN("Failed to initialise view, hr %#x.\n", hr);
845 return hr;
848 TRACE("Created unordered access view %p.\n", object);
849 *view = object;
851 return WINED3D_OK;