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 #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
)
40 GLenum texture_target
;
41 unsigned int view_flags
;
43 enum wined3d_gl_extension extension
;
47 {GL_TEXTURE_CUBE_MAP
, 0, GL_TEXTURE_CUBE_MAP
},
48 {GL_TEXTURE_RECTANGLE
, 0, GL_TEXTURE_RECTANGLE
},
49 {GL_TEXTURE_3D
, 0, GL_TEXTURE_3D
},
51 {GL_TEXTURE_2D
, 0, GL_TEXTURE_2D
},
52 {GL_TEXTURE_2D
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_ARRAY
},
53 {GL_TEXTURE_2D_ARRAY
, 0, GL_TEXTURE_2D
},
54 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_ARRAY
},
55 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_TEXTURE_CUBE
, GL_TEXTURE_CUBE_MAP
},
56 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_CUBE_ARRAY
, GL_TEXTURE_CUBE_MAP_ARRAY
, ARB_TEXTURE_CUBE_MAP_ARRAY
},
58 {GL_TEXTURE_2D_MULTISAMPLE
, 0, GL_TEXTURE_2D_MULTISAMPLE
},
59 {GL_TEXTURE_2D_MULTISAMPLE
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_MULTISAMPLE_ARRAY
},
60 {GL_TEXTURE_2D_MULTISAMPLE_ARRAY
, 0, GL_TEXTURE_2D_MULTISAMPLE
},
61 {GL_TEXTURE_2D_MULTISAMPLE_ARRAY
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_MULTISAMPLE_ARRAY
},
63 {GL_TEXTURE_1D
, 0, GL_TEXTURE_1D
},
64 {GL_TEXTURE_1D
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_1D_ARRAY
},
65 {GL_TEXTURE_1D_ARRAY
, 0, GL_TEXTURE_1D
},
66 {GL_TEXTURE_1D_ARRAY
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_1D_ARRAY
},
70 for (i
= 0; i
< ARRAY_SIZE(view_types
); ++i
)
72 if (view_types
[i
].texture_target
!= texture
->target
|| view_types
[i
].view_flags
!= desc
->flags
)
74 if (gl_info
->supported
[view_types
[i
].extension
])
75 return view_types
[i
].view_target
;
77 FIXME("Extension %#x not supported.\n", view_types
[i
].extension
);
80 FIXME("Unhandled view flags %#x for texture target %#x.\n", desc
->flags
, texture
->target
);
81 return texture
->target
;
84 static const struct wined3d_format
*validate_resource_view(const struct wined3d_view_desc
*desc
,
85 struct wined3d_resource
*resource
, BOOL mip_slice
, BOOL allow_srgb_toggle
)
87 const struct wined3d_adapter
*adapter
= resource
->device
->adapter
;
88 const struct wined3d_format
*format
;
90 format
= wined3d_get_format(adapter
, desc
->format_id
, resource
->usage
);
91 if (resource
->type
== WINED3D_RTYPE_BUFFER
&& (desc
->flags
& WINED3D_VIEW_BUFFER_RAW
))
93 if (format
->id
!= WINED3DFMT_R32_TYPELESS
)
95 WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(format
->id
));
99 format
= wined3d_get_format(adapter
, WINED3DFMT_R32_UINT
, resource
->usage
);
102 if (wined3d_format_is_typeless(format
))
104 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(format
->id
));
108 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
110 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
111 unsigned int buffer_size
, element_size
;
113 if (buffer
->desc
.structure_byte_stride
)
115 if (desc
->format_id
!= WINED3DFMT_UNKNOWN
)
117 WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc
->format_id
));
121 format
= wined3d_get_format(adapter
, WINED3DFMT_R32_UINT
, resource
->usage
);
122 element_size
= buffer
->desc
.structure_byte_stride
;
126 element_size
= format
->byte_count
;
132 buffer_size
= buffer
->resource
.size
/ element_size
;
133 if (desc
->u
.buffer
.start_idx
>= buffer_size
134 || desc
->u
.buffer
.count
> buffer_size
- desc
->u
.buffer
.start_idx
)
139 struct wined3d_texture
*texture
= texture_from_resource(resource
);
140 unsigned int depth_or_layer_count
;
142 if (resource
->format
->id
!= format
->id
&& !wined3d_format_is_typeless(resource
->format
)
143 && (!allow_srgb_toggle
|| !wined3d_formats_are_srgb_variants(resource
->format
->id
, format
->id
)))
145 WARN("Trying to create incompatible view for non typeless format %s.\n",
146 debug_d3dformat(format
->id
));
150 if (mip_slice
&& resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
151 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
153 depth_or_layer_count
= texture
->layer_count
;
155 if (!desc
->u
.texture
.level_count
156 || (mip_slice
&& desc
->u
.texture
.level_count
!= 1)
157 || desc
->u
.texture
.level_idx
>= texture
->level_count
158 || desc
->u
.texture
.level_count
> texture
->level_count
- desc
->u
.texture
.level_idx
159 || !desc
->u
.texture
.layer_count
160 || desc
->u
.texture
.layer_idx
>= depth_or_layer_count
161 || desc
->u
.texture
.layer_count
> depth_or_layer_count
- desc
->u
.texture
.layer_idx
)
168 static void create_texture_view(struct wined3d_gl_view
*view
, GLenum view_target
,
169 const struct wined3d_view_desc
*desc
, struct wined3d_texture
*texture
,
170 const struct wined3d_format
*view_format
)
172 unsigned int level_idx
, layer_idx
, layer_count
;
173 const struct wined3d_gl_info
*gl_info
;
174 struct wined3d_context
*context
;
177 view
->target
= view_target
;
179 context
= context_acquire(texture
->resource
.device
, NULL
, 0);
180 gl_info
= context
->gl_info
;
182 if (!gl_info
->supported
[ARB_TEXTURE_VIEW
])
184 context_release(context
);
185 FIXME("OpenGL implementation does not support texture views.\n");
189 wined3d_texture_prepare_texture(texture
, context
, FALSE
);
190 texture_name
= wined3d_texture_get_texture_name(texture
, context
, FALSE
);
192 level_idx
= desc
->u
.texture
.level_idx
;
193 layer_idx
= desc
->u
.texture
.layer_idx
;
194 layer_count
= desc
->u
.texture
.layer_count
;
195 if (view_target
== GL_TEXTURE_3D
)
197 if (layer_idx
|| layer_count
!= wined3d_texture_get_level_depth(texture
, level_idx
))
198 FIXME("Depth slice (%u-%u) not supported.\n", layer_idx
, layer_count
);
203 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &view
->name
);
204 GL_EXTCALL(glTextureView(view
->name
, view
->target
, texture_name
, view_format
->glInternal
,
205 level_idx
, desc
->u
.texture
.level_count
, layer_idx
, layer_count
));
206 checkGLcall("create texture view");
208 if (is_stencil_view_format(view_format
))
210 static const GLint swizzle
[] = {GL_ZERO
, GL_RED
, GL_ZERO
, GL_ZERO
};
212 if (!gl_info
->supported
[ARB_STENCIL_TEXTURING
])
214 context_release(context
);
215 FIXME("OpenGL implementation does not support stencil texturing.\n");
219 context_bind_texture(context
, view
->target
, view
->name
);
220 gl_info
->gl_ops
.gl
.p_glTexParameteriv(view
->target
, GL_TEXTURE_SWIZZLE_RGBA
, swizzle
);
221 gl_info
->gl_ops
.gl
.p_glTexParameteri(view
->target
, GL_DEPTH_STENCIL_TEXTURE_MODE
, GL_STENCIL_INDEX
);
222 checkGLcall("initialize stencil view");
224 context_invalidate_compute_state(context
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
225 context_invalidate_state(context
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
228 context_release(context
);
231 static void create_buffer_texture(struct wined3d_gl_view
*view
, struct wined3d_context
*context
,
232 struct wined3d_buffer
*buffer
, const struct wined3d_format
*view_format
,
233 unsigned int offset
, unsigned int size
)
235 const struct wined3d_gl_info
*gl_info
= context
->gl_info
;
237 if (!gl_info
->supported
[ARB_TEXTURE_BUFFER_OBJECT
])
239 FIXME("OpenGL implementation does not support buffer textures.\n");
243 if ((offset
& (gl_info
->limits
.texture_buffer_offset_alignment
- 1)))
245 FIXME("Buffer offset %u is not %u byte aligned.\n",
246 offset
, gl_info
->limits
.texture_buffer_offset_alignment
);
250 wined3d_buffer_load_location(buffer
, context
, WINED3D_LOCATION_BUFFER
);
252 view
->target
= GL_TEXTURE_BUFFER
;
253 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &view
->name
);
255 context_bind_texture(context
, GL_TEXTURE_BUFFER
, view
->name
);
256 if (gl_info
->supported
[ARB_TEXTURE_BUFFER_RANGE
])
258 GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER
, view_format
->glInternal
,
259 buffer
->buffer_object
, offset
, size
));
263 if (offset
|| size
!= buffer
->resource
.size
)
264 FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n");
265 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER
, view_format
->glInternal
, buffer
->buffer_object
));
267 checkGLcall("Create buffer texture");
269 context_invalidate_compute_state(context
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
270 context_invalidate_state(context
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
273 static void get_buffer_view_range(const struct wined3d_buffer
*buffer
,
274 const struct wined3d_view_desc
*desc
, const struct wined3d_format
*view_format
,
275 unsigned int *offset
, unsigned int *size
)
277 if (desc
->format_id
== WINED3DFMT_UNKNOWN
)
279 *offset
= desc
->u
.buffer
.start_idx
* buffer
->desc
.structure_byte_stride
;
280 *size
= desc
->u
.buffer
.count
* buffer
->desc
.structure_byte_stride
;
284 *offset
= desc
->u
.buffer
.start_idx
* view_format
->byte_count
;
285 *size
= desc
->u
.buffer
.count
* view_format
->byte_count
;
289 static void create_buffer_view(struct wined3d_gl_view
*view
, struct wined3d_context
*context
,
290 const struct wined3d_view_desc
*desc
, struct wined3d_buffer
*buffer
,
291 const struct wined3d_format
*view_format
)
293 unsigned int offset
, size
;
295 get_buffer_view_range(buffer
, desc
, view_format
, &offset
, &size
);
296 create_buffer_texture(view
, context
, buffer
, view_format
, offset
, size
);
299 static void wined3d_view_invalidate_location(struct wined3d_resource
*resource
,
300 const struct wined3d_view_desc
*desc
, DWORD location
)
302 unsigned int i
, sub_resource_idx
, layer_count
;
303 struct wined3d_texture
*texture
;
305 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
307 wined3d_buffer_invalidate_location(buffer_from_resource(resource
), location
);
311 texture
= texture_from_resource(resource
);
313 sub_resource_idx
= desc
->u
.texture
.layer_idx
* texture
->level_count
+ desc
->u
.texture
.level_idx
;
314 layer_count
= resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
? desc
->u
.texture
.layer_count
: 1;
315 for (i
= 0; i
< layer_count
; ++i
, sub_resource_idx
+= texture
->level_count
)
316 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, location
);
319 ULONG CDECL
wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view
*view
)
321 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
323 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
328 static void wined3d_rendertarget_view_destroy_object(void *object
)
330 struct wined3d_rendertarget_view
*view
= object
;
331 struct wined3d_device
*device
= view
->resource
->device
;
333 if (view
->gl_view
.name
)
335 const struct wined3d_gl_info
*gl_info
;
336 struct wined3d_context
*context
;
338 context
= context_acquire(device
, NULL
, 0);
339 gl_info
= context
->gl_info
;
340 context_gl_resource_released(device
, view
->gl_view
.name
, FALSE
);
341 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &view
->gl_view
.name
);
342 checkGLcall("glDeleteTextures");
343 context_release(context
);
349 ULONG CDECL
wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view
*view
)
351 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
353 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
357 struct wined3d_resource
*resource
= view
->resource
;
358 struct wined3d_device
*device
= resource
->device
;
360 /* Call wined3d_object_destroyed() before releasing the resource,
361 * since releasing the resource may end up destroying the parent. */
362 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
363 wined3d_cs_destroy_object(device
->cs
, wined3d_rendertarget_view_destroy_object
, view
);
364 wined3d_resource_decref(resource
);
370 void * CDECL
wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view
*view
)
372 TRACE("view %p.\n", view
);
377 void * CDECL
wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view
*view
)
379 struct wined3d_texture
*texture
;
381 TRACE("view %p.\n", view
);
383 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
384 return wined3d_buffer_get_parent(buffer_from_resource(view
->resource
));
386 texture
= texture_from_resource(view
->resource
);
388 return texture
->sub_resources
[view
->sub_resource_idx
].parent
;
391 void CDECL
wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view
*view
, void *parent
)
393 TRACE("view %p, parent %p.\n", view
, parent
);
395 view
->parent
= parent
;
398 struct wined3d_resource
* CDECL
wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view
*view
)
400 TRACE("view %p.\n", view
);
402 return view
->resource
;
405 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view
*view
,
406 const struct wined3d_context
*context
, unsigned int *width
, unsigned int *height
)
408 const struct wined3d_texture
*texture
;
410 if (view
->resource
->type
!= WINED3D_RTYPE_TEXTURE_2D
)
412 *width
= view
->width
;
413 *height
= view
->height
;
417 texture
= texture_from_resource(view
->resource
);
418 if (texture
->swapchain
)
420 /* The drawable size of an onscreen drawable is the surface size.
421 * (Actually: The window size, but the surface is created in window
423 *width
= texture
->resource
.width
;
424 *height
= texture
->resource
.height
;
426 else if (wined3d_settings
.offscreen_rendering_mode
== ORM_BACKBUFFER
)
428 const struct wined3d_swapchain
*swapchain
= context
->swapchain
;
430 /* The drawable size of a backbuffer / aux buffer offscreen target is
431 * the size of the current context's drawable, which is the size of
432 * the back buffer of the swapchain the active context belongs to. */
433 *width
= swapchain
->desc
.backbuffer_width
;
434 *height
= swapchain
->desc
.backbuffer_height
;
438 unsigned int level_idx
= view
->sub_resource_idx
% texture
->level_count
;
440 /* The drawable size of an FBO target is the OpenGL texture size,
441 * which is the power of two size. */
442 *width
= wined3d_texture_get_level_pow2_width(texture
, level_idx
);
443 *height
= wined3d_texture_get_level_pow2_height(texture
, level_idx
);
447 void wined3d_rendertarget_view_prepare_location(struct wined3d_rendertarget_view
*view
,
448 struct wined3d_context
*context
, DWORD location
)
450 struct wined3d_resource
*resource
= view
->resource
;
451 unsigned int i
, sub_resource_idx
, layer_count
;
452 struct wined3d_texture
*texture
;
454 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
456 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource
->type
));
460 texture
= texture_from_resource(resource
);
461 sub_resource_idx
= view
->sub_resource_idx
;
462 layer_count
= resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
? view
->layer_count
: 1;
463 for (i
= 0; i
< layer_count
; ++i
, sub_resource_idx
+= texture
->level_count
)
464 wined3d_texture_prepare_location(texture
, sub_resource_idx
, context
, location
);
467 void wined3d_rendertarget_view_load_location(struct wined3d_rendertarget_view
*view
,
468 struct wined3d_context
*context
, DWORD location
)
470 struct wined3d_resource
*resource
= view
->resource
;
471 unsigned int i
, sub_resource_idx
, layer_count
;
472 struct wined3d_texture
*texture
;
474 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
476 wined3d_buffer_load_location(buffer_from_resource(resource
), context
, location
);
480 texture
= texture_from_resource(resource
);
481 sub_resource_idx
= view
->sub_resource_idx
;
482 layer_count
= resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
? view
->layer_count
: 1;
483 for (i
= 0; i
< layer_count
; ++i
, sub_resource_idx
+= texture
->level_count
)
484 wined3d_texture_load_location(texture
, sub_resource_idx
, context
, location
);
487 void wined3d_rendertarget_view_validate_location(struct wined3d_rendertarget_view
*view
, DWORD location
)
489 struct wined3d_resource
*resource
= view
->resource
;
490 unsigned int i
, sub_resource_idx
, layer_count
;
491 struct wined3d_texture
*texture
;
493 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
495 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource
->type
));
499 texture
= texture_from_resource(resource
);
500 sub_resource_idx
= view
->sub_resource_idx
;
501 layer_count
= resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
? view
->layer_count
: 1;
502 for (i
= 0; i
< layer_count
; ++i
, sub_resource_idx
+= texture
->level_count
)
503 wined3d_texture_validate_location(texture
, sub_resource_idx
, location
);
506 void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view
*view
, DWORD location
)
508 wined3d_view_invalidate_location(view
->resource
, &view
->desc
, location
);
511 static void wined3d_render_target_view_cs_init(void *object
)
513 struct wined3d_rendertarget_view
*view
= object
;
514 struct wined3d_resource
*resource
= view
->resource
;
515 const struct wined3d_view_desc
*desc
= &view
->desc
;
517 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
519 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource
->type
));
523 struct wined3d_texture
*texture
= texture_from_resource(resource
);
524 unsigned int depth_or_layer_count
;
526 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
527 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
529 depth_or_layer_count
= texture
->layer_count
;
531 if (resource
->format
->id
!= view
->format
->id
532 || (view
->layer_count
!= 1 && view
->layer_count
!= depth_or_layer_count
))
534 if (resource
->format
->gl_view_class
!= view
->format
->gl_view_class
)
536 FIXME("Render target view not supported, resource format %s, view format %s.\n",
537 debug_d3dformat(resource
->format
->id
), debug_d3dformat(view
->format
->id
));
540 if (texture
->swapchain
&& texture
->swapchain
->desc
.backbuffer_count
> 1)
542 FIXME("Swapchain views not supported.\n");
546 create_texture_view(&view
->gl_view
, texture
->target
, desc
, texture
, view
->format
);
551 static HRESULT
wined3d_rendertarget_view_init(struct wined3d_rendertarget_view
*view
,
552 const struct wined3d_view_desc
*desc
, struct wined3d_resource
*resource
,
553 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
555 BOOL allow_srgb_toggle
= FALSE
;
558 view
->parent
= parent
;
559 view
->parent_ops
= parent_ops
;
561 if (resource
->type
!= WINED3D_RTYPE_BUFFER
)
563 struct wined3d_texture
*texture
= texture_from_resource(resource
);
565 if (texture
->swapchain
)
566 allow_srgb_toggle
= TRUE
;
568 if (!(view
->format
= validate_resource_view(desc
, resource
, TRUE
, allow_srgb_toggle
)))
570 view
->format_flags
= view
->format
->flags
[resource
->gl_type
];
573 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
575 view
->sub_resource_idx
= 0;
576 view
->layer_count
= 1;
577 view
->width
= desc
->u
.buffer
.count
;
582 struct wined3d_texture
*texture
= texture_from_resource(resource
);
584 view
->sub_resource_idx
= desc
->u
.texture
.level_idx
;
585 if (resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
)
586 view
->sub_resource_idx
+= desc
->u
.texture
.layer_idx
* texture
->level_count
;
587 view
->layer_count
= desc
->u
.texture
.layer_count
;
588 view
->width
= wined3d_texture_get_level_width(texture
, desc
->u
.texture
.level_idx
);
589 view
->height
= wined3d_texture_get_level_height(texture
, desc
->u
.texture
.level_idx
);
592 wined3d_resource_incref(view
->resource
= resource
);
594 wined3d_cs_init_object(resource
->device
->cs
, wined3d_render_target_view_cs_init
, view
);
599 HRESULT CDECL
wined3d_rendertarget_view_create(const struct wined3d_view_desc
*desc
,
600 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
601 struct wined3d_rendertarget_view
**view
)
603 struct wined3d_rendertarget_view
*object
;
606 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
607 desc
, resource
, parent
, parent_ops
, view
);
609 if (!(object
= heap_alloc_zero(sizeof(*object
))))
610 return E_OUTOFMEMORY
;
612 if (FAILED(hr
= wined3d_rendertarget_view_init(object
, desc
, resource
, parent
, parent_ops
)))
615 WARN("Failed to initialise view, hr %#x.\n", hr
);
619 TRACE("Created render target view %p.\n", object
);
625 HRESULT CDECL
wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture
*texture
,
626 unsigned int sub_resource_idx
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
627 struct wined3d_rendertarget_view
**view
)
629 struct wined3d_view_desc desc
;
631 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
632 texture
, sub_resource_idx
, parent
, parent_ops
, view
);
634 desc
.format_id
= texture
->resource
.format
->id
;
636 desc
.u
.texture
.level_idx
= sub_resource_idx
% texture
->level_count
;
637 desc
.u
.texture
.level_count
= 1;
638 desc
.u
.texture
.layer_idx
= sub_resource_idx
/ texture
->level_count
;
639 desc
.u
.texture
.layer_count
= 1;
641 return wined3d_rendertarget_view_create(&desc
, &texture
->resource
, parent
, parent_ops
, view
);
644 ULONG CDECL
wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view
*view
)
646 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
648 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
653 static void wined3d_shader_resource_view_destroy_object(void *object
)
655 struct wined3d_shader_resource_view
*view
= object
;
657 if (view
->gl_view
.name
)
659 const struct wined3d_gl_info
*gl_info
;
660 struct wined3d_context
*context
;
662 context
= context_acquire(view
->resource
->device
, NULL
, 0);
663 gl_info
= context
->gl_info
;
664 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &view
->gl_view
.name
);
665 checkGLcall("glDeleteTextures");
666 context_release(context
);
672 ULONG CDECL
wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view
*view
)
674 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
676 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
680 struct wined3d_resource
*resource
= view
->resource
;
681 struct wined3d_device
*device
= resource
->device
;
683 /* Call wined3d_object_destroyed() before releasing the resource,
684 * since releasing the resource may end up destroying the parent. */
685 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
686 wined3d_cs_destroy_object(device
->cs
, wined3d_shader_resource_view_destroy_object
, view
);
687 wined3d_resource_decref(resource
);
693 void * CDECL
wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view
*view
)
695 TRACE("view %p.\n", view
);
700 static void wined3d_shader_resource_view_cs_init(void *object
)
702 struct wined3d_shader_resource_view
*view
= object
;
703 struct wined3d_resource
*resource
= view
->resource
;
704 const struct wined3d_format
*view_format
;
705 const struct wined3d_gl_info
*gl_info
;
706 const struct wined3d_view_desc
*desc
;
709 view_format
= view
->format
;
710 gl_info
= &resource
->device
->adapter
->gl_info
;
713 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
715 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
716 struct wined3d_context
*context
;
718 context
= context_acquire(resource
->device
, NULL
, 0);
719 create_buffer_view(&view
->gl_view
, context
, desc
, buffer
, view_format
);
720 context_release(context
);
724 struct wined3d_texture
*texture
= texture_from_resource(resource
);
726 view_target
= get_texture_view_target(gl_info
, desc
, texture
);
728 if (resource
->format
->id
== view_format
->id
&& texture
->target
== view_target
729 && !desc
->u
.texture
.level_idx
&& desc
->u
.texture
.level_count
== texture
->level_count
730 && !desc
->u
.texture
.layer_idx
&& desc
->u
.texture
.layer_count
== texture
->layer_count
731 && !is_stencil_view_format(view_format
))
733 TRACE("Creating identity shader resource view.\n");
735 else if (texture
->swapchain
&& texture
->swapchain
->desc
.backbuffer_count
> 1)
737 FIXME("Swapchain shader resource views not supported.\n");
739 else if (resource
->format
->typeless_id
== view_format
->typeless_id
740 && resource
->format
->gl_view_class
== view_format
->gl_view_class
)
742 create_texture_view(&view
->gl_view
, view_target
, desc
, texture
, view_format
);
744 else if (wined3d_format_is_depth_view(resource
->format
->id
, view_format
->id
))
746 create_texture_view(&view
->gl_view
, view_target
, desc
, texture
, resource
->format
);
750 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
751 debug_d3dformat(resource
->format
->id
), debug_d3dformat(view_format
->id
));
756 static HRESULT
wined3d_shader_resource_view_init(struct wined3d_shader_resource_view
*view
,
757 const struct wined3d_view_desc
*desc
, struct wined3d_resource
*resource
,
758 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
761 view
->parent
= parent
;
762 view
->parent_ops
= parent_ops
;
764 if (!(view
->format
= validate_resource_view(desc
, resource
, FALSE
, FALSE
)))
768 wined3d_resource_incref(view
->resource
= resource
);
770 wined3d_cs_init_object(resource
->device
->cs
, wined3d_shader_resource_view_cs_init
, view
);
775 HRESULT CDECL
wined3d_shader_resource_view_create(const struct wined3d_view_desc
*desc
,
776 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
777 struct wined3d_shader_resource_view
**view
)
779 struct wined3d_shader_resource_view
*object
;
782 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
783 desc
, resource
, parent
, parent_ops
, view
);
785 if (!(object
= heap_alloc_zero(sizeof(*object
))))
786 return E_OUTOFMEMORY
;
788 if (FAILED(hr
= wined3d_shader_resource_view_init(object
, desc
, resource
, parent
, parent_ops
)))
791 WARN("Failed to initialise view, hr %#x.\n", hr
);
795 TRACE("Created shader resource view %p.\n", object
);
801 void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view
*view
,
802 unsigned int unit
, struct wined3d_sampler
*sampler
, struct wined3d_context
*context
)
804 const struct wined3d_gl_info
*gl_info
= context
->gl_info
;
805 struct wined3d_texture
*texture
;
807 context_active_texture(context
, gl_info
, unit
);
809 if (view
->gl_view
.name
)
811 context_bind_texture(context
, view
->gl_view
.target
, view
->gl_view
.name
);
812 wined3d_sampler_bind(sampler
, unit
, NULL
, context
);
816 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
818 FIXME("Buffer shader resources not supported.\n");
822 texture
= wined3d_texture_from_resource(view
->resource
);
823 wined3d_texture_bind(texture
, context
, FALSE
);
824 wined3d_sampler_bind(sampler
, unit
, texture
, context
);
827 /* Context activation is done by the caller. */
828 static void shader_resource_view_bind_and_dirtify(struct wined3d_shader_resource_view
*view
,
829 struct wined3d_context
*context
)
831 if (context
->active_texture
< ARRAY_SIZE(context
->rev_tex_unit_map
))
833 DWORD active_sampler
= context
->rev_tex_unit_map
[context
->active_texture
];
834 if (active_sampler
!= WINED3D_UNMAPPED_STAGE
)
835 context_invalidate_state(context
, STATE_SAMPLER(active_sampler
));
837 /* FIXME: Ideally we'd only do this when touching a binding that's used by
839 context_invalidate_compute_state(context
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
840 context_invalidate_state(context
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
842 context_bind_texture(context
, view
->gl_view
.target
, view
->gl_view
.name
);
845 void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view
*view
)
847 struct wined3d_texture
*texture
= texture_from_resource(view
->resource
);
848 unsigned int i
, j
, layer_count
, level_count
, base_level
, max_level
;
849 const struct wined3d_gl_info
*gl_info
;
850 struct wined3d_context
*context
;
851 struct gl_texture
*gl_tex
;
855 TRACE("view %p.\n", view
);
857 context
= context_acquire(view
->resource
->device
, NULL
, 0);
858 gl_info
= context
->gl_info
;
859 layer_count
= view
->desc
.u
.texture
.layer_count
;
860 level_count
= view
->desc
.u
.texture
.level_count
;
861 base_level
= view
->desc
.u
.texture
.level_idx
;
862 max_level
= base_level
+ level_count
- 1;
864 srgb
= !!(texture
->flags
& WINED3D_TEXTURE_IS_SRGB
);
865 location
= srgb
? WINED3D_LOCATION_TEXTURE_SRGB
: WINED3D_LOCATION_TEXTURE_RGB
;
866 for (i
= 0; i
< layer_count
; ++i
)
867 wined3d_texture_load_location(texture
, i
* level_count
+ base_level
, context
, location
);
869 if (view
->gl_view
.name
)
871 shader_resource_view_bind_and_dirtify(view
, context
);
875 wined3d_texture_bind_and_dirtify(texture
, context
, srgb
);
876 gl_info
->gl_ops
.gl
.p_glTexParameteri(texture
->target
, GL_TEXTURE_BASE_LEVEL
, base_level
);
877 gl_info
->gl_ops
.gl
.p_glTexParameteri(texture
->target
, GL_TEXTURE_MAX_LEVEL
, max_level
);
880 if (gl_info
->supported
[ARB_SAMPLER_OBJECTS
])
881 GL_EXTCALL(glBindSampler(context
->active_texture
, 0));
882 gl_tex
= wined3d_texture_get_gl_texture(texture
, srgb
);
883 if (context
->d3d_info
->wined3d_creation_flags
& WINED3D_SRGB_READ_WRITE_CONTROL
)
885 gl_info
->gl_ops
.gl
.p_glTexParameteri(texture
->target
, GL_TEXTURE_SRGB_DECODE_EXT
,
887 gl_tex
->sampler_desc
.srgb_decode
= FALSE
;
890 gl_info
->fbo_ops
.glGenerateMipmap(texture
->target
);
891 checkGLcall("glGenerateMipMap()");
893 for (i
= 0; i
< layer_count
; ++i
)
895 for (j
= base_level
+ 1; j
<= max_level
; ++j
)
897 wined3d_texture_validate_location(texture
, i
* level_count
+ j
, location
);
898 wined3d_texture_invalidate_location(texture
, i
* level_count
+ j
, ~location
);
902 if (!view
->gl_view
.name
)
904 gl_tex
->base_level
= base_level
;
905 gl_info
->gl_ops
.gl
.p_glTexParameteri(texture
->target
, GL_TEXTURE_MAX_LEVEL
, texture
->level_count
- 1);
908 context_release(context
);
911 void CDECL
wined3d_shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view
*view
)
913 struct wined3d_texture
*texture
;
915 TRACE("view %p.\n", view
);
917 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
919 WARN("Called on buffer resource %p.\n", view
->resource
);
923 texture
= texture_from_resource(view
->resource
);
924 if (!(texture
->flags
& WINED3D_TEXTURE_GENERATE_MIPMAPS
))
926 WARN("Texture without the WINED3D_TEXTURE_GENERATE_MIPMAPS flag, ignoring.\n");
930 wined3d_cs_emit_generate_mipmaps(view
->resource
->device
->cs
, view
);
933 ULONG CDECL
wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view
*view
)
935 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
937 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
942 static void wined3d_unordered_access_view_destroy_object(void *object
)
944 struct wined3d_unordered_access_view
*view
= object
;
946 if (view
->gl_view
.name
|| view
->counter_bo
)
948 const struct wined3d_gl_info
*gl_info
;
949 struct wined3d_context
*context
;
951 context
= context_acquire(view
->resource
->device
, NULL
, 0);
952 gl_info
= context
->gl_info
;
953 if (view
->gl_view
.name
)
954 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &view
->gl_view
.name
);
955 if (view
->counter_bo
)
956 GL_EXTCALL(glDeleteBuffers(1, &view
->counter_bo
));
957 checkGLcall("delete resources");
958 context_release(context
);
964 ULONG CDECL
wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view
*view
)
966 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
968 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
972 struct wined3d_resource
*resource
= view
->resource
;
973 struct wined3d_device
*device
= resource
->device
;
975 /* Call wined3d_object_destroyed() before releasing the resource,
976 * since releasing the resource may end up destroying the parent. */
977 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
978 wined3d_cs_destroy_object(device
->cs
, wined3d_unordered_access_view_destroy_object
, view
);
979 wined3d_resource_decref(resource
);
985 void * CDECL
wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view
*view
)
987 TRACE("view %p.\n", view
);
992 void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_access_view
*view
,
995 wined3d_view_invalidate_location(view
->resource
, &view
->desc
, location
);
998 void wined3d_unordered_access_view_clear_uint(struct wined3d_unordered_access_view
*view
,
999 const struct wined3d_uvec4
*clear_value
, struct wined3d_context
*context
)
1001 const struct wined3d_gl_info
*gl_info
= context
->gl_info
;
1002 const struct wined3d_format
*format
;
1003 struct wined3d_resource
*resource
;
1004 struct wined3d_buffer
*buffer
;
1005 unsigned int offset
, size
;
1007 resource
= view
->resource
;
1008 if (resource
->type
!= WINED3D_RTYPE_BUFFER
)
1010 FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource
->type
));
1014 if (!gl_info
->supported
[ARB_CLEAR_BUFFER_OBJECT
])
1016 FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n");
1020 format
= view
->format
;
1021 if (format
->id
!= WINED3DFMT_R32_UINT
&& format
->id
!= WINED3DFMT_R32_SINT
1022 && format
->id
!= WINED3DFMT_R32G32B32A32_UINT
1023 && format
->id
!= WINED3DFMT_R32G32B32A32_SINT
)
1025 FIXME("Not implemented for format %s.\n", debug_d3dformat(format
->id
));
1029 buffer
= buffer_from_resource(resource
);
1030 wined3d_buffer_load_location(buffer
, context
, WINED3D_LOCATION_BUFFER
);
1031 wined3d_unordered_access_view_invalidate_location(view
, ~WINED3D_LOCATION_BUFFER
);
1033 get_buffer_view_range(buffer
, &view
->desc
, format
, &offset
, &size
);
1034 context_bind_bo(context
, buffer
->buffer_type_hint
, buffer
->buffer_object
);
1035 GL_EXTCALL(glClearBufferSubData(buffer
->buffer_type_hint
, format
->glInternal
,
1036 offset
, size
, format
->glFormat
, format
->glType
, clear_value
));
1037 checkGLcall("clear unordered access view");
1040 void wined3d_unordered_access_view_set_counter(struct wined3d_unordered_access_view
*view
,
1043 const struct wined3d_gl_info
*gl_info
;
1044 struct wined3d_context
*context
;
1046 if (!view
->counter_bo
)
1049 context
= context_acquire(view
->resource
->device
, NULL
, 0);
1050 gl_info
= context
->gl_info
;
1051 GL_EXTCALL(glBindBuffer(GL_ATOMIC_COUNTER_BUFFER
, view
->counter_bo
));
1052 GL_EXTCALL(glBufferSubData(GL_ATOMIC_COUNTER_BUFFER
, 0, sizeof(value
), &value
));
1053 checkGLcall("set atomic counter");
1054 context_release(context
);
1057 void wined3d_unordered_access_view_copy_counter(struct wined3d_unordered_access_view
*view
,
1058 struct wined3d_buffer
*buffer
, unsigned int offset
, struct wined3d_context
*context
)
1060 struct wined3d_bo_address dst
, src
;
1063 if (!view
->counter_bo
)
1066 dst_location
= wined3d_buffer_get_memory(buffer
, &dst
, buffer
->locations
);
1069 src
.buffer_object
= view
->counter_bo
;
1072 context_copy_bo_address(context
, &dst
, buffer
->buffer_type_hint
,
1073 &src
, GL_ATOMIC_COUNTER_BUFFER
, sizeof(GLuint
));
1075 wined3d_buffer_invalidate_location(buffer
, ~dst_location
);
1078 static void wined3d_unordered_access_view_cs_init(void *object
)
1080 struct wined3d_unordered_access_view
*view
= object
;
1081 struct wined3d_resource
*resource
= view
->resource
;
1082 struct wined3d_view_desc
*desc
= &view
->desc
;
1083 const struct wined3d_gl_info
*gl_info
;
1085 gl_info
= &resource
->device
->adapter
->gl_info
;
1087 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
1089 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
1090 struct wined3d_context
*context
;
1092 context
= context_acquire(resource
->device
, NULL
, 0);
1093 gl_info
= context
->gl_info
;
1094 create_buffer_view(&view
->gl_view
, context
, desc
, buffer
, view
->format
);
1095 if (desc
->flags
& (WINED3D_VIEW_BUFFER_COUNTER
| WINED3D_VIEW_BUFFER_APPEND
))
1097 static const GLuint initial_value
= 0;
1098 GL_EXTCALL(glGenBuffers(1, &view
->counter_bo
));
1099 GL_EXTCALL(glBindBuffer(GL_ATOMIC_COUNTER_BUFFER
, view
->counter_bo
));
1100 GL_EXTCALL(glBufferData(GL_ATOMIC_COUNTER_BUFFER
,
1101 sizeof(initial_value
), &initial_value
, GL_STATIC_DRAW
));
1102 checkGLcall("create atomic counter buffer");
1104 context_release(context
);
1108 struct wined3d_texture
*texture
= texture_from_resource(resource
);
1109 unsigned int depth_or_layer_count
;
1111 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
1112 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
1114 depth_or_layer_count
= texture
->layer_count
;
1116 if (desc
->u
.texture
.layer_idx
|| desc
->u
.texture
.layer_count
!= depth_or_layer_count
)
1118 create_texture_view(&view
->gl_view
, get_texture_view_target(gl_info
, desc
, texture
),
1119 desc
, texture
, view
->format
);
1124 static HRESULT
wined3d_unordered_access_view_init(struct wined3d_unordered_access_view
*view
,
1125 const struct wined3d_view_desc
*desc
, struct wined3d_resource
*resource
,
1126 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
1129 view
->parent
= parent
;
1130 view
->parent_ops
= parent_ops
;
1132 if (!(view
->format
= validate_resource_view(desc
, resource
, TRUE
, FALSE
)))
1133 return E_INVALIDARG
;
1136 wined3d_resource_incref(view
->resource
= resource
);
1138 wined3d_cs_init_object(resource
->device
->cs
, wined3d_unordered_access_view_cs_init
, view
);
1143 HRESULT CDECL
wined3d_unordered_access_view_create(const struct wined3d_view_desc
*desc
,
1144 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1145 struct wined3d_unordered_access_view
**view
)
1147 struct wined3d_unordered_access_view
*object
;
1150 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
1151 desc
, resource
, parent
, parent_ops
, view
);
1153 if (!(object
= heap_alloc_zero(sizeof(*object
))))
1154 return E_OUTOFMEMORY
;
1156 if (FAILED(hr
= wined3d_unordered_access_view_init(object
, desc
, resource
, parent
, parent_ops
)))
1159 WARN("Failed to initialise view, hr %#x.\n", hr
);
1163 TRACE("Created unordered access view %p.\n", object
);