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_resource
*resource
= view
->resource
;
50 struct wined3d_device
*device
= resource
->device
;
52 /* Call wined3d_object_destroyed() before releasing the resource,
53 * since releasing the resource may end up destroying the parent. */
54 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
55 wined3d_cs_emit_destroy_object(device
->cs
, wined3d_rendertarget_view_destroy_object
, view
);
56 wined3d_resource_decref(resource
);
62 void * CDECL
wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view
*view
)
64 TRACE("view %p.\n", view
);
69 void * CDECL
wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view
*view
)
71 struct wined3d_texture
*texture
;
73 TRACE("view %p.\n", view
);
75 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
76 return wined3d_buffer_get_parent(buffer_from_resource(view
->resource
));
78 texture
= texture_from_resource(view
->resource
);
80 return texture
->sub_resources
[view
->sub_resource_idx
].parent
;
83 void CDECL
wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view
*view
, void *parent
)
85 TRACE("view %p, parent %p.\n", view
, parent
);
87 view
->parent
= parent
;
90 struct wined3d_resource
* CDECL
wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view
*view
)
92 TRACE("view %p.\n", view
);
94 return view
->resource
;
97 static HRESULT
wined3d_rendertarget_view_init(struct wined3d_rendertarget_view
*view
,
98 const struct wined3d_rendertarget_view_desc
*desc
, struct wined3d_resource
*resource
,
99 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
101 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
104 view
->parent
= parent
;
105 view
->parent_ops
= parent_ops
;
107 view
->format
= wined3d_get_format(gl_info
, desc
->format_id
);
108 view
->format_flags
= view
->format
->flags
[resource
->gl_type
];
110 if (wined3d_format_is_typeless(view
->format
))
112 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view
->format
->id
));
116 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
118 view
->sub_resource_idx
= 0;
119 view
->buffer_offset
= desc
->u
.buffer
.start_idx
;
120 view
->width
= desc
->u
.buffer
.count
;
126 struct wined3d_texture
*texture
= texture_from_resource(resource
);
127 unsigned int depth_or_layer_count
;
129 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
130 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
132 depth_or_layer_count
= texture
->layer_count
;
134 if (desc
->u
.texture
.level_idx
>= texture
->level_count
135 || desc
->u
.texture
.layer_idx
>= depth_or_layer_count
136 || !desc
->u
.texture
.layer_count
137 || desc
->u
.texture
.layer_count
> depth_or_layer_count
- desc
->u
.texture
.layer_idx
)
140 view
->sub_resource_idx
= desc
->u
.texture
.level_idx
;
141 if (resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
)
142 view
->sub_resource_idx
+= desc
->u
.texture
.layer_idx
* texture
->level_count
;
143 view
->buffer_offset
= 0;
144 view
->width
= wined3d_texture_get_level_width(texture
, desc
->u
.texture
.level_idx
);
145 view
->height
= wined3d_texture_get_level_height(texture
, desc
->u
.texture
.level_idx
);
146 view
->depth
= desc
->u
.texture
.layer_count
;
148 wined3d_resource_incref(view
->resource
= resource
);
153 HRESULT CDECL
wined3d_rendertarget_view_create(const struct wined3d_rendertarget_view_desc
*desc
,
154 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
155 struct wined3d_rendertarget_view
**view
)
157 struct wined3d_rendertarget_view
*object
;
160 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
161 desc
, resource
, parent
, parent_ops
, view
);
163 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
164 return E_OUTOFMEMORY
;
166 if (FAILED(hr
= wined3d_rendertarget_view_init(object
, desc
, resource
, parent
, parent_ops
)))
168 HeapFree(GetProcessHeap(), 0, object
);
169 WARN("Failed to initialise view, hr %#x.\n", hr
);
173 TRACE("Created render target view %p.\n", object
);
179 HRESULT CDECL
wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture
*texture
,
180 unsigned int sub_resource_idx
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
181 struct wined3d_rendertarget_view
**view
)
183 struct wined3d_rendertarget_view_desc desc
;
185 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
186 texture
, sub_resource_idx
, parent
, parent_ops
, view
);
188 desc
.format_id
= texture
->resource
.format
->id
;
189 desc
.u
.texture
.level_idx
= sub_resource_idx
% texture
->level_count
;
190 desc
.u
.texture
.layer_idx
= sub_resource_idx
/ texture
->level_count
;
191 desc
.u
.texture
.layer_count
= 1;
193 return wined3d_rendertarget_view_create(&desc
, &texture
->resource
, parent
, parent_ops
, view
);
196 ULONG CDECL
wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view
*view
)
198 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
200 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
205 static void wined3d_shader_resource_view_destroy_object(void *object
)
207 struct wined3d_shader_resource_view
*view
= object
;
211 const struct wined3d_gl_info
*gl_info
;
212 struct wined3d_context
*context
;
214 context
= context_acquire(view
->resource
->device
, NULL
);
215 gl_info
= context
->gl_info
;
216 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &view
->object
);
217 checkGLcall("glDeleteTextures");
218 context_release(context
);
221 HeapFree(GetProcessHeap(), 0, view
);
224 ULONG CDECL
wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view
*view
)
226 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
228 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
232 struct wined3d_resource
*resource
= view
->resource
;
233 struct wined3d_device
*device
= resource
->device
;
235 /* Call wined3d_object_destroyed() before releasing the resource,
236 * since releasing the resource may end up destroying the parent. */
237 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
238 wined3d_cs_emit_destroy_object(device
->cs
, wined3d_shader_resource_view_destroy_object
, view
);
239 wined3d_resource_decref(resource
);
245 void * CDECL
wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view
*view
)
247 TRACE("view %p.\n", view
);
252 static void wined3d_shader_resource_view_create_texture_view(struct wined3d_shader_resource_view
*view
,
253 const struct wined3d_shader_resource_view_desc
*desc
, struct wined3d_texture
*texture
,
254 const struct wined3d_format
*view_format
)
256 const struct wined3d_gl_info
*gl_info
;
257 struct wined3d_context
*context
;
258 struct gl_texture
*gl_texture
;
260 context
= context_acquire(texture
->resource
.device
, NULL
);
261 gl_info
= context
->gl_info
;
263 if (!gl_info
->supported
[ARB_TEXTURE_VIEW
])
265 context_release(context
);
266 FIXME("OpenGL implementation does not support texture views.\n");
270 wined3d_texture_prepare_texture(texture
, context
, FALSE
);
271 gl_texture
= wined3d_texture_get_gl_texture(texture
, FALSE
);
273 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &view
->object
);
274 GL_EXTCALL(glTextureView(view
->object
, view
->target
, gl_texture
->name
, view_format
->glInternal
,
275 desc
->u
.texture
.level_idx
, desc
->u
.texture
.level_count
,
276 desc
->u
.texture
.layer_idx
, desc
->u
.texture
.layer_count
));
277 checkGLcall("Create texture view");
279 context_release(context
);
282 static HRESULT
wined3d_shader_resource_view_init(struct wined3d_shader_resource_view
*view
,
283 const struct wined3d_shader_resource_view_desc
*desc
, struct wined3d_resource
*resource
,
284 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
288 GLenum texture_target
;
289 unsigned int view_flags
;
294 {GL_TEXTURE_2D
, 0, GL_TEXTURE_2D
},
295 {GL_TEXTURE_2D
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_ARRAY
},
296 {GL_TEXTURE_2D_ARRAY
, 0, GL_TEXTURE_2D
},
297 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_ARRAY
},
298 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_TEXTURE_CUBE
, GL_TEXTURE_CUBE_MAP
},
299 {GL_TEXTURE_3D
, 0, GL_TEXTURE_3D
},
302 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
303 const struct wined3d_format
*view_format
;
305 view_format
= wined3d_get_format(gl_info
, desc
->format_id
);
306 if (wined3d_format_is_typeless(view_format
))
308 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view_format
->id
));
313 view
->parent
= parent
;
314 view
->parent_ops
= parent_ops
;
316 view
->target
= GL_NONE
;
319 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
321 FIXME("Buffer shader resource views not supported.\n");
325 struct wined3d_texture
*texture
= texture_from_resource(resource
);
328 if (!desc
->u
.texture
.level_count
329 || desc
->u
.texture
.level_idx
>= texture
->level_count
330 || desc
->u
.texture
.level_count
> texture
->level_count
- desc
->u
.texture
.level_idx
331 || !desc
->u
.texture
.layer_count
332 || desc
->u
.texture
.layer_idx
>= texture
->layer_count
333 || desc
->u
.texture
.layer_count
> texture
->layer_count
- desc
->u
.texture
.layer_idx
)
336 view
->target
= texture
->target
;
337 for (i
= 0; i
< ARRAY_SIZE(view_types
); ++i
)
339 if (view_types
[i
].texture_target
== texture
->target
&& view_types
[i
].view_flags
== desc
->flags
)
341 view
->target
= view_types
[i
].view_target
;
345 if (i
== ARRAY_SIZE(view_types
))
346 FIXME("Unhandled view flags %#x for texture target %#x.\n", desc
->flags
, texture
->target
);
348 if (resource
->format
->id
== view_format
->id
&& texture
->target
== view
->target
349 && !desc
->u
.texture
.level_idx
&& desc
->u
.texture
.level_count
== texture
->level_count
350 && !desc
->u
.texture
.layer_idx
&& desc
->u
.texture
.layer_count
== texture
->layer_count
)
352 TRACE("Creating identity shader resource view.\n");
354 else if (texture
->swapchain
&& texture
->swapchain
->desc
.backbuffer_count
> 1)
356 FIXME("Swapchain shader resource views not supported.\n");
358 else if (resource
->format
->typeless_id
== view_format
->typeless_id
359 && resource
->format
->gl_view_class
== view_format
->gl_view_class
)
361 wined3d_shader_resource_view_create_texture_view(view
, desc
, texture
, view_format
);
365 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
366 debug_d3dformat(resource
->format
->id
), debug_d3dformat(view_format
->id
));
369 wined3d_resource_incref(view
->resource
= resource
);
374 HRESULT CDECL
wined3d_shader_resource_view_create(const struct wined3d_shader_resource_view_desc
*desc
,
375 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
376 struct wined3d_shader_resource_view
**view
)
378 struct wined3d_shader_resource_view
*object
;
381 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
382 desc
, resource
, parent
, parent_ops
, view
);
384 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
385 return E_OUTOFMEMORY
;
387 if (FAILED(hr
= wined3d_shader_resource_view_init(object
, desc
, resource
, parent
, parent_ops
)))
389 HeapFree(GetProcessHeap(), 0, object
);
390 WARN("Failed to initialise view, hr %#x.\n", hr
);
394 TRACE("Created shader resource view %p.\n", object
);
400 void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view
*view
,
401 struct wined3d_context
*context
)
403 struct wined3d_texture
*texture
;
407 context_bind_texture(context
, view
->target
, view
->object
);
411 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
413 FIXME("Buffer shader resources not supported.\n");
417 texture
= wined3d_texture_from_resource(view
->resource
);
418 wined3d_texture_bind(texture
, context
, FALSE
);
421 ULONG CDECL
wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view
*view
)
423 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
425 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
430 static void wined3d_unordered_access_view_destroy_object(void *object
)
432 HeapFree(GetProcessHeap(), 0, object
);
435 ULONG CDECL
wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view
*view
)
437 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
439 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
443 struct wined3d_resource
*resource
= view
->resource
;
444 struct wined3d_device
*device
= resource
->device
;
446 /* Call wined3d_object_destroyed() before releasing the resource,
447 * since releasing the resource may end up destroying the parent. */
448 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
449 wined3d_cs_emit_destroy_object(device
->cs
, wined3d_unordered_access_view_destroy_object
, view
);
450 wined3d_resource_decref(resource
);
456 void * CDECL
wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view
*view
)
458 TRACE("view %p.\n", view
);
463 static HRESULT
wined3d_unordered_access_view_init(struct wined3d_unordered_access_view
*view
,
464 const struct wined3d_unordered_access_view_desc
*desc
, struct wined3d_resource
*resource
,
465 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
467 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
470 view
->parent
= parent
;
471 view
->parent_ops
= parent_ops
;
473 view
->format
= wined3d_get_format(gl_info
, desc
->format_id
);
475 if (wined3d_format_is_typeless(view
->format
))
477 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view
->format
->id
));
481 if (resource
->type
!= WINED3D_RTYPE_BUFFER
)
483 struct wined3d_texture
*texture
= texture_from_resource(resource
);
484 unsigned int depth_or_layer_count
;
486 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
487 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
489 depth_or_layer_count
= texture
->layer_count
;
491 if (desc
->u
.texture
.level_idx
>= texture
->level_count
492 || desc
->u
.texture
.layer_idx
>= depth_or_layer_count
493 || !desc
->u
.texture
.layer_count
494 || desc
->u
.texture
.layer_count
> depth_or_layer_count
- desc
->u
.texture
.layer_idx
)
497 wined3d_resource_incref(view
->resource
= resource
);
502 HRESULT CDECL
wined3d_unordered_access_view_create(const struct wined3d_unordered_access_view_desc
*desc
,
503 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
504 struct wined3d_unordered_access_view
**view
)
506 struct wined3d_unordered_access_view
*object
;
509 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
510 desc
, resource
, parent
, parent_ops
, view
);
512 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
513 return E_OUTOFMEMORY
;
515 if (FAILED(hr
= wined3d_unordered_access_view_init(object
, desc
, resource
, parent
, parent_ops
)))
517 HeapFree(GetProcessHeap(), 0, object
);
518 WARN("Failed to initialise view, hr %#x.\n", hr
);
522 TRACE("Created unordered access view %p.\n", object
);