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
21 #include "wine/port.h"
23 #include "wined3d_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
27 ULONG CDECL
wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view
*view
)
29 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
31 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
36 static void wined3d_rendertarget_view_destroy_object(void *object
)
38 HeapFree(GetProcessHeap(), 0, object
);
41 ULONG CDECL
wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view
*view
)
43 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
45 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
49 struct wined3d_device
*device
= view
->resource
->device
;
51 /* Call wined3d_object_destroyed() before releasing the resource,
52 * since releasing the resource may end up destroying the parent. */
53 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
54 wined3d_resource_decref(view
->resource
);
55 wined3d_cs_emit_destroy_object(device
->cs
, wined3d_rendertarget_view_destroy_object
, view
);
61 void * CDECL
wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view
*view
)
63 TRACE("view %p.\n", view
);
68 void * CDECL
wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view
*view
)
70 struct wined3d_texture
*texture
;
72 TRACE("view %p.\n", view
);
74 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
75 return wined3d_buffer_get_parent(buffer_from_resource(view
->resource
));
77 texture
= texture_from_resource(view
->resource
);
79 return texture
->sub_resources
[view
->sub_resource_idx
].parent
;
82 void CDECL
wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view
*view
, void *parent
)
84 TRACE("view %p, parent %p.\n", view
, parent
);
86 view
->parent
= parent
;
89 struct wined3d_resource
* CDECL
wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view
*view
)
91 TRACE("view %p.\n", view
);
93 return view
->resource
;
96 static HRESULT
wined3d_rendertarget_view_init(struct wined3d_rendertarget_view
*view
,
97 const struct wined3d_rendertarget_view_desc
*desc
, struct wined3d_resource
*resource
,
98 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
100 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
103 view
->parent
= parent
;
104 view
->parent_ops
= parent_ops
;
106 view
->format
= wined3d_get_format(gl_info
, desc
->format_id
);
107 view
->format_flags
= view
->format
->flags
[resource
->gl_type
];
109 if (wined3d_format_is_typeless(view
->format
))
111 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view
->format
->id
));
115 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
117 view
->sub_resource_idx
= 0;
118 view
->buffer_offset
= desc
->u
.buffer
.start_idx
;
119 view
->width
= desc
->u
.buffer
.count
;
125 struct wined3d_texture
*texture
= texture_from_resource(resource
);
126 unsigned int depth_or_layer_count
;
128 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
129 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
131 depth_or_layer_count
= texture
->layer_count
;
133 if (desc
->u
.texture
.level_idx
>= texture
->level_count
134 || desc
->u
.texture
.layer_idx
>= depth_or_layer_count
135 || !desc
->u
.texture
.layer_count
136 || desc
->u
.texture
.layer_count
> depth_or_layer_count
- desc
->u
.texture
.layer_idx
)
139 view
->sub_resource_idx
= desc
->u
.texture
.level_idx
;
140 if (resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
)
141 view
->sub_resource_idx
+= desc
->u
.texture
.layer_idx
* texture
->level_count
;
142 view
->buffer_offset
= 0;
143 view
->width
= wined3d_texture_get_level_width(texture
, desc
->u
.texture
.level_idx
);
144 view
->height
= wined3d_texture_get_level_height(texture
, desc
->u
.texture
.level_idx
);
145 view
->depth
= desc
->u
.texture
.layer_count
;
147 wined3d_resource_incref(view
->resource
= resource
);
152 HRESULT CDECL
wined3d_rendertarget_view_create(const struct wined3d_rendertarget_view_desc
*desc
,
153 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
154 struct wined3d_rendertarget_view
**view
)
156 struct wined3d_rendertarget_view
*object
;
159 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
160 desc
, resource
, parent
, parent_ops
, view
);
162 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
163 return E_OUTOFMEMORY
;
165 if (FAILED(hr
= wined3d_rendertarget_view_init(object
, desc
, resource
, parent
, parent_ops
)))
167 HeapFree(GetProcessHeap(), 0, object
);
168 WARN("Failed to initialise view, hr %#x.\n", hr
);
172 TRACE("Created render target view %p.\n", object
);
178 HRESULT CDECL
wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture
*texture
,
179 unsigned int sub_resource_idx
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
180 struct wined3d_rendertarget_view
**view
)
182 struct wined3d_rendertarget_view_desc desc
;
184 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
185 texture
, sub_resource_idx
, parent
, parent_ops
, view
);
187 desc
.format_id
= texture
->resource
.format
->id
;
188 desc
.u
.texture
.level_idx
= sub_resource_idx
% texture
->level_count
;
189 desc
.u
.texture
.layer_idx
= sub_resource_idx
/ texture
->level_count
;
190 desc
.u
.texture
.layer_count
= 1;
192 return wined3d_rendertarget_view_create(&desc
, &texture
->resource
, parent
, parent_ops
, view
);
195 ULONG CDECL
wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view
*view
)
197 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
199 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
204 static void wined3d_shader_resource_view_destroy_object(void *object
)
206 struct wined3d_shader_resource_view
*view
= object
;
210 const struct wined3d_gl_info
*gl_info
;
211 struct wined3d_context
*context
;
213 context
= context_acquire(view
->resource
->device
, NULL
);
214 gl_info
= context
->gl_info
;
215 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &view
->object
);
216 checkGLcall("glDeleteTextures");
217 context_release(context
);
220 HeapFree(GetProcessHeap(), 0, view
);
223 ULONG CDECL
wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view
*view
)
225 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
227 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
231 struct wined3d_resource
*resource
= view
->resource
;
232 struct wined3d_device
*device
= resource
->device
;
234 /* Call wined3d_object_destroyed() before releasing the resource,
235 * since releasing the resource may end up destroying the parent. */
236 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
237 wined3d_cs_emit_destroy_object(device
->cs
, wined3d_shader_resource_view_destroy_object
, view
);
238 wined3d_resource_decref(resource
);
244 void * CDECL
wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view
*view
)
246 TRACE("view %p.\n", view
);
251 static void wined3d_shader_resource_view_create_texture_view(struct wined3d_shader_resource_view
*view
,
252 const struct wined3d_shader_resource_view_desc
*desc
, struct wined3d_texture
*texture
,
253 const struct wined3d_format
*view_format
)
255 const struct wined3d_gl_info
*gl_info
;
256 struct wined3d_context
*context
;
257 struct gl_texture
*gl_texture
;
259 context
= context_acquire(texture
->resource
.device
, NULL
);
260 gl_info
= context
->gl_info
;
262 if (!gl_info
->supported
[ARB_TEXTURE_VIEW
])
264 context_release(context
);
265 FIXME("OpenGL implementation does not support texture views.\n");
269 wined3d_texture_prepare_texture(texture
, context
, FALSE
);
270 gl_texture
= wined3d_texture_get_gl_texture(texture
, FALSE
);
272 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &view
->object
);
273 GL_EXTCALL(glTextureView(view
->object
, view
->target
, gl_texture
->name
, view_format
->glInternal
,
274 desc
->u
.texture
.level_idx
, desc
->u
.texture
.level_count
,
275 desc
->u
.texture
.layer_idx
, desc
->u
.texture
.layer_count
));
276 checkGLcall("Create texture view");
278 context_release(context
);
281 static HRESULT
wined3d_shader_resource_view_init(struct wined3d_shader_resource_view
*view
,
282 const struct wined3d_shader_resource_view_desc
*desc
, struct wined3d_resource
*resource
,
283 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
287 GLenum texture_target
;
288 unsigned int view_flags
;
293 {GL_TEXTURE_2D
, 0, GL_TEXTURE_2D
},
294 {GL_TEXTURE_2D
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_ARRAY
},
295 {GL_TEXTURE_2D_ARRAY
, 0, GL_TEXTURE_2D
},
296 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_ARRAY
},
297 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_TEXTURE_CUBE
, GL_TEXTURE_CUBE_MAP
},
298 {GL_TEXTURE_3D
, 0, GL_TEXTURE_3D
},
301 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
302 const struct wined3d_format
*view_format
;
304 view_format
= wined3d_get_format(gl_info
, desc
->format_id
);
305 if (wined3d_format_is_typeless(view_format
))
307 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view_format
->id
));
312 view
->parent
= parent
;
313 view
->parent_ops
= parent_ops
;
315 view
->target
= GL_NONE
;
318 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
320 FIXME("Buffer shader resource views not supported.\n");
324 struct wined3d_texture
*texture
= texture_from_resource(resource
);
327 if (!desc
->u
.texture
.level_count
328 || desc
->u
.texture
.level_idx
>= texture
->level_count
329 || desc
->u
.texture
.level_count
> texture
->level_count
- desc
->u
.texture
.level_idx
330 || !desc
->u
.texture
.layer_count
331 || desc
->u
.texture
.layer_idx
>= texture
->layer_count
332 || desc
->u
.texture
.layer_count
> texture
->layer_count
- desc
->u
.texture
.layer_idx
)
335 view
->target
= texture
->target
;
336 for (i
= 0; i
< ARRAY_SIZE(view_types
); ++i
)
338 if (view_types
[i
].texture_target
== texture
->target
&& view_types
[i
].view_flags
== desc
->flags
)
340 view
->target
= view_types
[i
].view_target
;
344 if (i
== ARRAY_SIZE(view_types
))
345 FIXME("Unhandled view flags %#x for texture target %#x.\n", desc
->flags
, texture
->target
);
347 if (resource
->format
->id
== view_format
->id
&& texture
->target
== view
->target
348 && !desc
->u
.texture
.level_idx
&& desc
->u
.texture
.level_count
== texture
->level_count
349 && !desc
->u
.texture
.layer_idx
&& desc
->u
.texture
.layer_count
== texture
->layer_count
)
351 TRACE("Creating identity shader resource view.\n");
353 else if (texture
->swapchain
&& texture
->swapchain
->desc
.backbuffer_count
> 1)
355 FIXME("Swapchain shader resource views not supported.\n");
357 else if (resource
->format
->typeless_id
== view_format
->typeless_id
358 && resource
->format
->gl_view_class
== view_format
->gl_view_class
)
360 wined3d_shader_resource_view_create_texture_view(view
, desc
, texture
, view_format
);
364 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
365 debug_d3dformat(resource
->format
->id
), debug_d3dformat(view_format
->id
));
368 wined3d_resource_incref(view
->resource
= resource
);
373 HRESULT CDECL
wined3d_shader_resource_view_create(const struct wined3d_shader_resource_view_desc
*desc
,
374 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
375 struct wined3d_shader_resource_view
**view
)
377 struct wined3d_shader_resource_view
*object
;
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_shader_resource_view_init(object
, desc
, resource
, parent
, parent_ops
)))
388 HeapFree(GetProcessHeap(), 0, object
);
389 WARN("Failed to initialise view, hr %#x.\n", hr
);
393 TRACE("Created shader resource view %p.\n", object
);
399 void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view
*view
,
400 struct wined3d_context
*context
)
402 struct wined3d_texture
*texture
;
406 context_bind_texture(context
, view
->target
, view
->object
);
410 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
412 FIXME("Buffer shader resources not supported.\n");
416 texture
= wined3d_texture_from_resource(view
->resource
);
417 wined3d_texture_bind(texture
, context
, FALSE
);
420 ULONG CDECL
wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view
*view
)
422 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
424 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
429 static void wined3d_unordered_access_view_destroy_object(void *object
)
431 HeapFree(GetProcessHeap(), 0, object
);
434 ULONG CDECL
wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view
*view
)
436 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
438 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
442 struct wined3d_device
*device
= view
->resource
->device
;
444 /* Call wined3d_object_destroyed() before releasing the resource,
445 * since releasing the resource may end up destroying the parent. */
446 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
447 wined3d_resource_decref(view
->resource
);
448 wined3d_cs_emit_destroy_object(device
->cs
, wined3d_unordered_access_view_destroy_object
, view
);
454 void * CDECL
wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view
*view
)
456 TRACE("view %p.\n", view
);
461 static HRESULT
wined3d_unordered_access_view_init(struct wined3d_unordered_access_view
*view
,
462 const struct wined3d_unordered_access_view_desc
*desc
, struct wined3d_resource
*resource
,
463 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
465 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
468 view
->parent
= parent
;
469 view
->parent_ops
= parent_ops
;
471 view
->format
= wined3d_get_format(gl_info
, desc
->format_id
);
473 if (wined3d_format_is_typeless(view
->format
))
475 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view
->format
->id
));
479 if (resource
->type
!= WINED3D_RTYPE_BUFFER
)
481 struct wined3d_texture
*texture
= texture_from_resource(resource
);
482 unsigned int depth_or_layer_count
;
484 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
485 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
487 depth_or_layer_count
= texture
->layer_count
;
489 if (desc
->u
.texture
.level_idx
>= texture
->level_count
490 || desc
->u
.texture
.layer_idx
>= depth_or_layer_count
491 || !desc
->u
.texture
.layer_count
492 || desc
->u
.texture
.layer_count
> depth_or_layer_count
- desc
->u
.texture
.layer_idx
)
495 wined3d_resource_incref(view
->resource
= resource
);
500 HRESULT CDECL
wined3d_unordered_access_view_create(const struct wined3d_unordered_access_view_desc
*desc
,
501 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
502 struct wined3d_unordered_access_view
**view
)
504 struct wined3d_unordered_access_view
*object
;
507 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
508 desc
, resource
, parent
, parent_ops
, view
);
510 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
511 return E_OUTOFMEMORY
;
513 if (FAILED(hr
= wined3d_unordered_access_view_init(object
, desc
, resource
, parent
, parent_ops
)))
515 HeapFree(GetProcessHeap(), 0, object
);
516 WARN("Failed to initialise view, hr %#x.\n", hr
);
520 TRACE("Created unordered access view %p.\n", object
);