1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 **********************************************************/
28 #include "pipe/p_state.h"
29 #include "pipe/p_defines.h"
30 #include "util/u_inlines.h"
31 #include "os/os_thread.h"
32 #include "util/u_bitmask.h"
33 #include "util/u_format.h"
34 #include "util/u_math.h"
35 #include "util/u_memory.h"
37 #include "svga_format.h"
38 #include "svga_screen.h"
39 #include "svga_context.h"
40 #include "svga_sampler_view.h"
41 #include "svga_resource_texture.h"
42 #include "svga_surface.h"
43 #include "svga_debug.h"
45 static void svga_mark_surface_dirty(struct pipe_surface
*surf
);
48 svga_texture_copy_handle(struct svga_context
*svga
,
49 struct svga_winsys_surface
*src_handle
,
50 unsigned src_x
, unsigned src_y
, unsigned src_z
,
51 unsigned src_level
, unsigned src_layer
,
52 struct svga_winsys_surface
*dst_handle
,
53 unsigned dst_x
, unsigned dst_y
, unsigned dst_z
,
54 unsigned dst_level
, unsigned dst_layer
,
55 unsigned width
, unsigned height
, unsigned depth
)
57 struct svga_surface dst
, src
;
59 SVGA3dCopyBox box
, *boxes
;
63 src
.handle
= src_handle
;
64 src
.real_level
= src_level
;
65 src
.real_layer
= src_layer
;
68 dst
.handle
= dst_handle
;
69 dst
.real_level
= dst_level
;
70 dst
.real_layer
= dst_layer
;
84 SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n",
85 src_handle, src_level, src_x, src_y, src_z,
86 dst_handle, dst_level, dst_x, dst_y, dst_z);
89 ret
= SVGA3D_BeginSurfaceCopy(svga
->swc
,
94 svga_context_flush(svga
, NULL
);
95 ret
= SVGA3D_BeginSurfaceCopy(svga
->swc
,
99 assert(ret
== PIPE_OK
);
102 SVGA_FIFOCommitAll(svga
->swc
);
106 struct svga_winsys_surface
*
107 svga_texture_view_surface(struct svga_context
*svga
,
108 struct svga_texture
*tex
,
110 SVGA3dSurfaceFlags flags
,
111 SVGA3dSurfaceFormat format
,
117 struct svga_host_surface_cache_key
*key
) /* OUT */
119 struct svga_screen
*ss
= svga_screen(svga
->pipe
.screen
);
120 struct svga_winsys_surface
*handle
;
122 unsigned z_offset
= 0;
125 "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
126 layer_pick
, zslice_pick
, start_mip
, start_mip
+num_mip
-1);
129 key
->format
= format
;
130 key
->numMipLevels
= num_mip
;
131 key
->size
.width
= u_minify(tex
->b
.b
.width0
, start_mip
);
132 key
->size
.height
= u_minify(tex
->b
.b
.height0
, start_mip
);
133 key
->size
.depth
= zslice_pick
< 0 ? u_minify(tex
->b
.b
.depth0
, start_mip
) : 1;
137 key
->sampleCount
= tex
->b
.b
.nr_samples
;
139 if (key
->sampleCount
> 1) {
140 key
->flags
|= SVGA3D_SURFACE_MASKABLE_ANTIALIAS
;
143 if (tex
->b
.b
.target
== PIPE_TEXTURE_CUBE
&& layer_pick
< 0) {
144 key
->flags
|= SVGA3D_SURFACE_CUBEMAP
;
146 } else if (tex
->b
.b
.target
== PIPE_TEXTURE_1D_ARRAY
||
147 tex
->b
.b
.target
== PIPE_TEXTURE_2D_ARRAY
) {
148 key
->arraySize
= num_layers
;
151 if (key
->format
== SVGA3D_FORMAT_INVALID
) {
156 SVGA_DBG(DEBUG_DMA
, "surface_create for texture view\n");
157 handle
= svga_screen_surface_create(ss
, bind_flags
, PIPE_USAGE_DEFAULT
, key
);
163 SVGA_DBG(DEBUG_DMA
, " --> got sid %p (texture view)\n", handle
);
168 if (zslice_pick
>= 0)
169 z_offset
= zslice_pick
;
171 for (i
= 0; i
< key
->numMipLevels
; i
++) {
172 for (j
= 0; j
< key
->numFaces
* key
->arraySize
; j
++) {
173 if (svga_is_texture_level_defined(tex
, j
+ layer_pick
, i
+ start_mip
)) {
174 unsigned depth
= (zslice_pick
< 0 ?
175 u_minify(tex
->b
.b
.depth0
, i
+ start_mip
) :
178 svga_texture_copy_handle(svga
,
183 handle
, 0, 0, 0, i
, j
,
184 u_minify(tex
->b
.b
.width0
, i
+ start_mip
),
185 u_minify(tex
->b
.b
.height0
, i
+ start_mip
),
196 * A helper function to create a surface view.
197 * The view boolean flag specifies whether svga_texture_view_surface()
198 * will be called to create a cloned surface and resource for the view.
200 static struct pipe_surface
*
201 svga_create_surface_view(struct pipe_context
*pipe
,
202 struct pipe_resource
*pt
,
203 const struct pipe_surface
*surf_tmpl
,
206 struct svga_context
*svga
= svga_context(pipe
);
207 struct svga_texture
*tex
= svga_texture(pt
);
208 struct pipe_screen
*screen
= pipe
->screen
;
209 struct svga_screen
*ss
= svga_screen(screen
);
210 struct svga_surface
*s
;
211 unsigned layer
, zslice
, bind
;
212 unsigned nlayers
= 1;
213 SVGA3dSurfaceFlags flags
= 0;
214 SVGA3dSurfaceFormat format
;
216 s
= CALLOC_STRUCT(svga_surface
);
220 if (pt
->target
== PIPE_TEXTURE_CUBE
) {
221 layer
= surf_tmpl
->u
.tex
.first_layer
;
224 else if (pt
->target
== PIPE_TEXTURE_1D_ARRAY
||
225 pt
->target
== PIPE_TEXTURE_2D_ARRAY
) {
226 layer
= surf_tmpl
->u
.tex
.first_layer
;
228 nlayers
= surf_tmpl
->u
.tex
.last_layer
- surf_tmpl
->u
.tex
.first_layer
+ 1;
232 zslice
= surf_tmpl
->u
.tex
.first_layer
;
235 pipe_reference_init(&s
->base
.reference
, 1);
236 pipe_resource_reference(&s
->base
.texture
, pt
);
237 s
->base
.context
= pipe
;
238 s
->base
.format
= surf_tmpl
->format
;
239 s
->base
.width
= u_minify(pt
->width0
, surf_tmpl
->u
.tex
.level
);
240 s
->base
.height
= u_minify(pt
->height0
, surf_tmpl
->u
.tex
.level
);
241 s
->base
.u
.tex
.level
= surf_tmpl
->u
.tex
.level
;
242 s
->base
.u
.tex
.first_layer
= surf_tmpl
->u
.tex
.first_layer
;
243 s
->base
.u
.tex
.last_layer
= surf_tmpl
->u
.tex
.last_layer
;
244 s
->view_id
= SVGA3D_INVALID_ID
;
248 if (util_format_is_depth_or_stencil(surf_tmpl
->format
)) {
249 flags
= SVGA3D_SURFACE_HINT_DEPTHSTENCIL
|
250 SVGA3D_SURFACE_BIND_DEPTH_STENCIL
;
251 bind
= PIPE_BIND_DEPTH_STENCIL
;
254 flags
= SVGA3D_SURFACE_HINT_RENDERTARGET
|
255 SVGA3D_SURFACE_BIND_RENDER_TARGET
;
256 bind
= PIPE_BIND_RENDER_TARGET
;
260 format
= tex
->key
.format
;
262 format
= svga_translate_format(ss
, surf_tmpl
->format
, bind
);
264 assert(format
!= SVGA3D_FORMAT_INVALID
);
267 SVGA_DBG(DEBUG_VIEWS
, "svga: Surface view: yes %p, level %u layer %u z %u, %p\n",
268 pt
, surf_tmpl
->u
.tex
.level
, layer
, zslice
, s
);
270 if (svga_have_vgpu10(svga
)) {
271 switch (pt
->target
) {
272 case PIPE_TEXTURE_1D
:
273 flags
|= SVGA3D_SURFACE_1D
;
275 case PIPE_TEXTURE_1D_ARRAY
:
276 flags
|= SVGA3D_SURFACE_1D
| SVGA3D_SURFACE_ARRAY
;
278 case PIPE_TEXTURE_2D_ARRAY
:
279 flags
|= SVGA3D_SURFACE_ARRAY
;
281 case PIPE_TEXTURE_3D
:
282 flags
|= SVGA3D_SURFACE_VOLUME
;
284 case PIPE_TEXTURE_CUBE
:
286 flags
|= SVGA3D_SURFACE_CUBEMAP
;
293 /* When we clone the surface view resource, use the format used in
294 * the creation of the original resource.
296 s
->handle
= svga_texture_view_surface(svga
, tex
, bind
, flags
, tex
->key
.format
,
297 surf_tmpl
->u
.tex
.level
, 1,
298 layer
, nlayers
, zslice
, &s
->key
);
304 s
->key
.format
= format
;
309 SVGA_DBG(DEBUG_VIEWS
, "svga: Surface view: no %p, level %u, layer %u, z %u, %p\n",
310 pt
, surf_tmpl
->u
.tex
.level
, layer
, zslice
, s
);
312 memset(&s
->key
, 0, sizeof s
->key
);
313 s
->key
.format
= format
;
314 s
->handle
= tex
->handle
;
315 s
->real_layer
= layer
;
316 s
->real_zslice
= zslice
;
317 s
->real_level
= surf_tmpl
->u
.tex
.level
;
320 svga
->hud
.num_surface_views
++;
326 static struct pipe_surface
*
327 svga_create_surface(struct pipe_context
*pipe
,
328 struct pipe_resource
*pt
,
329 const struct pipe_surface
*surf_tmpl
)
331 struct svga_context
*svga
= svga_context(pipe
);
332 struct pipe_screen
*screen
= pipe
->screen
;
333 boolean view
= FALSE
;
335 if (svga_screen(screen
)->debug
.force_surface_view
)
338 if (surf_tmpl
->u
.tex
.level
!= 0 &&
339 svga_screen(screen
)->debug
.force_level_surface_view
)
342 if (pt
->target
== PIPE_TEXTURE_3D
)
345 if (svga_have_vgpu10(svga
) || svga_screen(screen
)->debug
.no_surface_view
)
348 return svga_create_surface_view(pipe
, pt
, surf_tmpl
, view
);
353 * Clone the surface view and its associated resource.
355 static struct svga_surface
*
356 create_backed_surface_view(struct svga_context
*svga
, struct svga_surface
*s
)
358 struct svga_surface
*bs
= s
->backed
;
361 struct svga_texture
*tex
= svga_texture(s
->base
.texture
);
362 struct pipe_surface
*backed_view
;
364 backed_view
= svga_create_surface_view(&svga
->pipe
,
371 bs
= svga_surface(backed_view
);
375 svga_mark_surface_dirty(&bs
->base
);
381 * Create a DX RenderTarget/DepthStencil View for the given surface,
384 struct pipe_surface
*
385 svga_validate_surface_view(struct svga_context
*svga
, struct svga_surface
*s
)
387 enum pipe_error ret
= PIPE_OK
;
390 assert(svga_have_vgpu10(svga
));
393 * DX spec explicitly specifies that no resource can be bound to a render
394 * target view and a shader resource view simultanously.
395 * So first check if the resource bound to this surface view collides with
396 * a sampler view. If so, then we will clone this surface view and its
397 * associated resource. We will then use the cloned surface view for
400 for (shader
= PIPE_SHADER_VERTEX
; shader
<= PIPE_SHADER_GEOMETRY
; shader
++) {
401 if (svga_check_sampler_view_resource_collision(svga
, s
->handle
, shader
)) {
402 SVGA_DBG(DEBUG_VIEWS
,
403 "same resource used in shaderResource and renderTarget 0x%x\n",
405 s
= create_backed_surface_view(svga
, s
);
413 if (s
->view_id
== SVGA3D_INVALID_ID
) {
414 SVGA3dResourceType resType
;
415 SVGA3dRenderTargetViewDesc desc
;
417 desc
.tex
.mipSlice
= s
->real_level
;
418 desc
.tex
.firstArraySlice
= s
->real_layer
+ s
->real_zslice
;
420 s
->base
.u
.tex
.last_layer
- s
->base
.u
.tex
.first_layer
+ 1;
422 s
->view_id
= util_bitmask_add(svga
->surface_view_id_bm
);
424 switch (s
->base
.texture
->target
) {
425 case PIPE_TEXTURE_1D
:
426 case PIPE_TEXTURE_1D_ARRAY
:
427 resType
= SVGA3D_RESOURCE_TEXTURE1D
;
429 case PIPE_TEXTURE_RECT
:
430 case PIPE_TEXTURE_2D
:
431 case PIPE_TEXTURE_2D_ARRAY
:
432 case PIPE_TEXTURE_CUBE
:
433 /* drawing to cube map is treated as drawing to 2D array */
434 resType
= SVGA3D_RESOURCE_TEXTURE2D
;
436 case PIPE_TEXTURE_3D
:
437 resType
= SVGA3D_RESOURCE_TEXTURE3D
;
440 assert(!"Unexpected texture target");
441 resType
= SVGA3D_RESOURCE_TEXTURE2D
;
444 if (util_format_is_depth_or_stencil(s
->base
.format
)) {
445 ret
= SVGA3D_vgpu10_DefineDepthStencilView(svga
->swc
,
453 ret
= SVGA3D_vgpu10_DefineRenderTargetView(svga
->swc
,
461 if (ret
!= PIPE_OK
) {
462 util_bitmask_clear(svga
->surface_view_id_bm
, s
->view_id
);
463 s
->view_id
= SVGA3D_INVALID_ID
;
473 svga_surface_destroy(struct pipe_context
*pipe
,
474 struct pipe_surface
*surf
)
476 struct svga_context
*svga
= svga_context(pipe
);
477 struct svga_surface
*s
= svga_surface(surf
);
478 struct svga_texture
*t
= svga_texture(surf
->texture
);
479 struct svga_screen
*ss
= svga_screen(surf
->texture
->screen
);
480 enum pipe_error ret
= PIPE_OK
;
482 /* Destroy the backed view surface if it exists */
484 svga_surface_destroy(pipe
, &s
->backed
->base
);
488 if (s
->handle
!= t
->handle
) {
489 SVGA_DBG(DEBUG_DMA
, "unref sid %p (tex surface)\n", s
->handle
);
490 svga_screen_surface_destroy(ss
, &s
->key
, &s
->handle
);
493 if (s
->view_id
!= SVGA3D_INVALID_ID
) {
496 assert(svga_have_vgpu10(svga
));
497 for (try = 0; try < 2; try++) {
498 if (util_format_is_depth_or_stencil(s
->base
.format
)) {
499 ret
= SVGA3D_vgpu10_DestroyDepthStencilView(svga
->swc
, s
->view_id
);
502 ret
= SVGA3D_vgpu10_DestroyRenderTargetView(svga
->swc
, s
->view_id
);
506 svga_context_flush(svga
, NULL
);
508 assert(ret
== PIPE_OK
);
509 util_bitmask_clear(svga
->surface_view_id_bm
, s
->view_id
);
512 pipe_resource_reference(&surf
->texture
, NULL
);
515 svga
->hud
.num_surface_views
--;
520 svga_mark_surface_dirty(struct pipe_surface
*surf
)
522 struct svga_surface
*s
= svga_surface(surf
);
523 struct svga_texture
*tex
= svga_texture(surf
->texture
);
528 if (s
->handle
== tex
->handle
) {
529 /* hmm so 3d textures always have all their slices marked ? */
530 svga_define_texture_level(tex
, surf
->u
.tex
.first_layer
,
534 /* this will happen later in svga_propagate_surface */
538 /* Increment the view_age and texture age for this surface's mipmap
539 * level so that any sampler views into the texture are re-validated too.
541 svga_age_texture_view(tex
, surf
->u
.tex
.level
);
546 svga_mark_surfaces_dirty(struct svga_context
*svga
)
548 struct svga_screen
*svgascreen
= svga_screen(svga
->pipe
.screen
);
551 for (i
= 0; i
< svgascreen
->max_color_buffers
; i
++) {
552 if (svga
->curr
.framebuffer
.cbufs
[i
])
553 svga_mark_surface_dirty(svga
->curr
.framebuffer
.cbufs
[i
]);
555 if (svga
->curr
.framebuffer
.zsbuf
)
556 svga_mark_surface_dirty(svga
->curr
.framebuffer
.zsbuf
);
561 * Progagate any changes from surfaces to texture.
562 * pipe is optional context to inline the blit command in.
565 svga_propagate_surface(struct svga_context
*svga
, struct pipe_surface
*surf
)
567 struct svga_surface
*s
= svga_surface(surf
);
568 struct svga_texture
*tex
= svga_texture(surf
->texture
);
569 struct svga_screen
*ss
= svga_screen(surf
->texture
->screen
);
570 unsigned zslice
, layer
;
571 unsigned nlayers
= 1;
577 if (surf
->texture
->target
== PIPE_TEXTURE_CUBE
) {
579 layer
= surf
->u
.tex
.first_layer
;
581 else if (surf
->texture
->target
== PIPE_TEXTURE_1D_ARRAY
||
582 surf
->texture
->target
== PIPE_TEXTURE_2D_ARRAY
) {
584 layer
= surf
->u
.tex
.first_layer
;
585 nlayers
= surf
->u
.tex
.last_layer
- surf
->u
.tex
.first_layer
+ 1;
588 zslice
= surf
->u
.tex
.first_layer
;
593 ss
->texture_timestamp
++;
594 svga_age_texture_view(tex
, surf
->u
.tex
.level
);
596 if (s
->handle
!= tex
->handle
) {
597 SVGA_DBG(DEBUG_VIEWS
,
598 "svga: Surface propagate: tex %p, level %u, from %p\n",
599 tex
, surf
->u
.tex
.level
, surf
);
600 for (i
= 0; i
< nlayers
; i
++) {
601 svga_texture_copy_handle(svga
,
602 s
->handle
, 0, 0, 0, s
->real_level
, s
->real_layer
+ i
,
603 tex
->handle
, 0, 0, zslice
, surf
->u
.tex
.level
, layer
+ i
,
604 u_minify(tex
->b
.b
.width0
, surf
->u
.tex
.level
),
605 u_minify(tex
->b
.b
.height0
, surf
->u
.tex
.level
), 1);
606 svga_define_texture_level(tex
, layer
+ i
, surf
->u
.tex
.level
);
613 * Check if we should call svga_propagate_surface on the surface.
616 svga_surface_needs_propagation(const struct pipe_surface
*surf
)
618 const struct svga_surface
*s
= svga_surface_const(surf
);
619 struct svga_texture
*tex
= svga_texture(surf
->texture
);
621 return s
->dirty
&& s
->handle
!= tex
->handle
;
626 svga_get_sample_position(struct pipe_context
*context
,
627 unsigned sample_count
, unsigned sample_index
,
630 /* We can't actually query the device to learn the sample positions.
631 * These were grabbed from nvidia's driver.
633 static const float pos1
[1][2] = {
636 static const float pos4
[4][2] = {
637 { 0.375000, 0.125000 },
638 { 0.875000, 0.375000 },
639 { 0.125000, 0.625000 },
640 { 0.625000, 0.875000 }
642 static const float pos8
[8][2] = {
643 { 0.562500, 0.312500 },
644 { 0.437500, 0.687500 },
645 { 0.812500, 0.562500 },
646 { 0.312500, 0.187500 },
647 { 0.187500, 0.812500 },
648 { 0.062500, 0.437500 },
649 { 0.687500, 0.937500 },
650 { 0.937500, 0.062500 }
652 static const float pos16
[16][2] = {
653 { 0.187500, 0.062500 },
654 { 0.437500, 0.187500 },
655 { 0.062500, 0.312500 },
656 { 0.312500, 0.437500 },
657 { 0.687500, 0.062500 },
658 { 0.937500, 0.187500 },
659 { 0.562500, 0.312500 },
660 { 0.812500, 0.437500 },
661 { 0.187500, 0.562500 },
662 { 0.437500, 0.687500 },
663 { 0.062500, 0.812500 },
664 { 0.312500, 0.937500 },
665 { 0.687500, 0.562500 },
666 { 0.937500, 0.687500 },
667 { 0.562500, 0.812500 },
668 { 0.812500, 0.937500 }
670 const float (*positions
)[2];
672 switch (sample_count
) {
686 pos_out
[0] = positions
[sample_index
][0];
687 pos_out
[1] = positions
[sample_index
][1];
692 svga_init_surface_functions(struct svga_context
*svga
)
694 svga
->pipe
.create_surface
= svga_create_surface
;
695 svga
->pipe
.surface_destroy
= svga_surface_destroy
;
696 svga
->pipe
.get_sample_position
= svga_get_sample_position
;