1 /****************************************************************************
2 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 ***************************************************************************/
24 #include "util/u_memory.h"
25 #include "util/u_inlines.h"
26 #include "util/u_format.h"
29 #include "util/u_transfer.h"
30 #include "util/u_surface.h"
33 #include "swr_context.h"
34 #include "swr_memory.h"
35 #include "swr_screen.h"
36 #include "swr_resource.h"
37 #include "swr_scratch.h"
38 #include "swr_query.h"
43 static struct pipe_surface
*
44 swr_create_surface(struct pipe_context
*pipe
,
45 struct pipe_resource
*pt
,
46 const struct pipe_surface
*surf_tmpl
)
48 struct pipe_surface
*ps
;
50 ps
= CALLOC_STRUCT(pipe_surface
);
52 pipe_reference_init(&ps
->reference
, 1);
53 pipe_resource_reference(&ps
->texture
, pt
);
55 ps
->format
= surf_tmpl
->format
;
56 if (pt
->target
!= PIPE_BUFFER
) {
57 assert(surf_tmpl
->u
.tex
.level
<= pt
->last_level
);
58 ps
->width
= u_minify(pt
->width0
, surf_tmpl
->u
.tex
.level
);
59 ps
->height
= u_minify(pt
->height0
, surf_tmpl
->u
.tex
.level
);
60 ps
->u
.tex
.level
= surf_tmpl
->u
.tex
.level
;
61 ps
->u
.tex
.first_layer
= surf_tmpl
->u
.tex
.first_layer
;
62 ps
->u
.tex
.last_layer
= surf_tmpl
->u
.tex
.last_layer
;
63 if (ps
->u
.tex
.first_layer
!= ps
->u
.tex
.last_layer
) {
64 debug_printf("creating surface with multiple layers, rendering "
65 "to first layer only\n");
68 /* setting width as number of elements should get us correct
69 * renderbuffer width */
70 ps
->width
= surf_tmpl
->u
.buf
.last_element
71 - surf_tmpl
->u
.buf
.first_element
+ 1;
72 ps
->height
= pt
->height0
;
73 ps
->u
.buf
.first_element
= surf_tmpl
->u
.buf
.first_element
;
74 ps
->u
.buf
.last_element
= surf_tmpl
->u
.buf
.last_element
;
75 assert(ps
->u
.buf
.first_element
<= ps
->u
.buf
.last_element
);
76 assert(ps
->u
.buf
.last_element
< ps
->width
);
83 swr_surface_destroy(struct pipe_context
*pipe
, struct pipe_surface
*surf
)
85 assert(surf
->texture
);
86 struct pipe_resource
*resource
= surf
->texture
;
88 /* If the surface being destroyed is a current render target,
89 * call StoreTiles to resolve the hotTile state then set attachment
92 if (resource
->bind
& (PIPE_BIND_RENDER_TARGET
| PIPE_BIND_DEPTH_STENCIL
93 | PIPE_BIND_DISPLAY_TARGET
)) {
94 struct swr_context
*ctx
= swr_context(pipe
);
95 struct swr_resource
*spr
= swr_resource(resource
);
96 swr_draw_context
*pDC
= &ctx
->swrDC
;
97 SWR_SURFACE_STATE
*renderTargets
= pDC
->renderTargets
;
98 for (uint32_t i
= 0; i
< SWR_NUM_ATTACHMENTS
; i
++)
99 if (renderTargets
[i
].pBaseAddress
== spr
->swr
.pBaseAddress
) {
100 swr_store_render_target(ctx
, i
, SWR_TILE_RESOLVED
);
103 * Mesa thinks depth/stencil are fused, so we'll never get an
104 * explicit resource for stencil. So, if checking depth, then
105 * also check for stencil.
107 if (spr
->has_stencil
&& (i
== SWR_ATTACHMENT_DEPTH
)) {
108 swr_store_render_target(
109 ctx
, SWR_ATTACHMENT_STENCIL
, SWR_TILE_RESOLVED
);
112 SwrWaitForIdle(ctx
->swrContext
);
117 pipe_resource_reference(&surf
->texture
, NULL
);
123 swr_transfer_map(struct pipe_context
*pipe
,
124 struct pipe_resource
*resource
,
127 const struct pipe_box
*box
,
128 struct pipe_transfer
**transfer
)
130 struct swr_resource
*spr
= swr_resource(resource
);
131 struct pipe_transfer
*pt
;
132 enum pipe_format format
= resource
->format
;
135 assert(level
<= resource
->last_level
);
138 * If mapping any attached rendertarget, store tiles and wait for idle
139 * before giving CPU access to the surface.
140 * (set postStoreTileState to SWR_TILE_INVALID so tiles are reloaded)
142 if (resource
->bind
& (PIPE_BIND_RENDER_TARGET
| PIPE_BIND_DEPTH_STENCIL
143 | PIPE_BIND_DISPLAY_TARGET
)) {
144 struct swr_context
*ctx
= swr_context(pipe
);
145 swr_draw_context
*pDC
= &ctx
->swrDC
;
146 SWR_SURFACE_STATE
*renderTargets
= pDC
->renderTargets
;
147 for (uint32_t i
= 0; i
< SWR_NUM_ATTACHMENTS
; i
++)
148 if (renderTargets
[i
].pBaseAddress
== spr
->swr
.pBaseAddress
) {
149 swr_store_render_target(ctx
, i
, SWR_TILE_INVALID
);
151 * Mesa thinks depth/stencil are fused, so we'll never get an
152 * explicit map for stencil. So, if mapping depth, then also
153 * store tile for stencil.
155 if (spr
->has_stencil
&& (i
== SWR_ATTACHMENT_DEPTH
))
156 swr_store_render_target(
157 ctx
, SWR_ATTACHMENT_STENCIL
, SWR_TILE_INVALID
);
158 SwrWaitForIdle(ctx
->swrContext
);
163 pt
= CALLOC_STRUCT(pipe_transfer
);
166 pipe_resource_reference(&pt
->resource
, resource
);
169 pt
->stride
= spr
->row_stride
[level
];
170 pt
->layer_stride
= spr
->img_stride
[level
];
172 /* if we're mapping the depth/stencil, copy in stencil */
173 if (spr
->base
.format
== PIPE_FORMAT_Z24_UNORM_S8_UINT
174 && spr
->has_stencil
) {
175 for (unsigned i
= 0; i
< spr
->alignedWidth
* spr
->alignedHeight
; i
++) {
176 spr
->swr
.pBaseAddress
[4 * i
+ 3] = spr
->secondary
.pBaseAddress
[i
];
178 } else if (spr
->base
.format
== PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
179 && spr
->has_stencil
) {
180 for (unsigned i
= 0; i
< spr
->alignedWidth
* spr
->alignedHeight
; i
++) {
181 spr
->swr
.pBaseAddress
[8 * i
+ 4] = spr
->secondary
.pBaseAddress
[i
];
185 unsigned offset
= box
->z
* pt
->layer_stride
+ box
->y
* pt
->stride
186 + box
->x
* util_format_get_blocksize(format
);
190 return spr
->swr
.pBaseAddress
+ offset
+ spr
->mip_offsets
[level
];
194 swr_transfer_unmap(struct pipe_context
*pipe
, struct pipe_transfer
*transfer
)
196 assert(transfer
->resource
);
199 * XXX TODO: use fences and come up with a real resource manager.
201 * If this resource has been mapped/unmapped, it's probably in use. Tag it
202 *with this context so
203 * we'll know to check dependencies when it's deleted.
205 struct swr_resource
*res
= swr_resource(transfer
->resource
);
206 res
->bound_to_context
= (void *)pipe
;
208 /* if we're mapping the depth/stencil, copy out stencil */
209 if (res
->base
.format
== PIPE_FORMAT_Z24_UNORM_S8_UINT
210 && res
->has_stencil
) {
211 for (unsigned i
= 0; i
< res
->alignedWidth
* res
->alignedHeight
; i
++) {
212 res
->secondary
.pBaseAddress
[i
] = res
->swr
.pBaseAddress
[4 * i
+ 3];
214 } else if (res
->base
.format
== PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
215 && res
->has_stencil
) {
216 for (unsigned i
= 0; i
< res
->alignedWidth
* res
->alignedHeight
; i
++) {
217 res
->secondary
.pBaseAddress
[i
] = res
->swr
.pBaseAddress
[8 * i
+ 4];
221 pipe_resource_reference(&transfer
->resource
, NULL
);
227 swr_resource_copy(struct pipe_context
*pipe
,
228 struct pipe_resource
*dst
,
233 struct pipe_resource
*src
,
235 const struct pipe_box
*src_box
)
237 if ((dst
->target
== PIPE_BUFFER
&& src
->target
== PIPE_BUFFER
)
238 || (dst
->target
!= PIPE_BUFFER
&& src
->target
!= PIPE_BUFFER
)) {
239 util_resource_copy_region(
240 pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
, src_level
, src_box
);
244 debug_printf("unhandled swr_resource_copy\n");
249 swr_blit(struct pipe_context
*pipe
, const struct pipe_blit_info
*blit_info
)
251 struct swr_context
*ctx
= swr_context(pipe
);
252 struct pipe_blit_info info
= *blit_info
;
254 if (blit_info
->render_condition_enable
&& !swr_check_render_cond(pipe
))
257 if (info
.src
.resource
->nr_samples
> 1 && info
.dst
.resource
->nr_samples
<= 1
258 && !util_format_is_depth_or_stencil(info
.src
.resource
->format
)
259 && !util_format_is_pure_integer(info
.src
.resource
->format
)) {
260 debug_printf("swr: color resolve unimplemented\n");
264 if (util_try_blit_via_copy_region(pipe
, &info
)) {
268 if (info
.mask
& PIPE_MASK_S
) {
269 debug_printf("swr: cannot blit stencil, skipping\n");
270 info
.mask
&= ~PIPE_MASK_S
;
273 if (!util_blitter_is_blit_supported(ctx
->blitter
, &info
)) {
274 debug_printf("swr: blit unsupported %s -> %s\n",
275 util_format_short_name(info
.src
.resource
->format
),
276 util_format_short_name(info
.dst
.resource
->format
));
280 /* XXX turn off occlusion and streamout queries */
282 util_blitter_save_vertex_buffer_slot(ctx
->blitter
, ctx
->vertex_buffer
);
283 util_blitter_save_vertex_elements(ctx
->blitter
, (void *)ctx
->velems
);
284 util_blitter_save_vertex_shader(ctx
->blitter
, (void *)ctx
->vs
);
285 /*util_blitter_save_geometry_shader(ctx->blitter, (void*)ctx->gs);*/
286 util_blitter_save_so_targets(
289 (struct pipe_stream_output_target
**)ctx
->so_targets
);
290 util_blitter_save_rasterizer(ctx
->blitter
, (void *)ctx
->rasterizer
);
291 util_blitter_save_viewport(ctx
->blitter
, &ctx
->viewport
);
292 util_blitter_save_scissor(ctx
->blitter
, &ctx
->scissor
);
293 util_blitter_save_fragment_shader(ctx
->blitter
, ctx
->fs
);
294 util_blitter_save_blend(ctx
->blitter
, (void *)ctx
->blend
);
295 util_blitter_save_depth_stencil_alpha(ctx
->blitter
,
296 (void *)ctx
->depth_stencil
);
297 util_blitter_save_stencil_ref(ctx
->blitter
, &ctx
->stencil_ref
);
298 util_blitter_save_sample_mask(ctx
->blitter
, ctx
->sample_mask
);
299 util_blitter_save_framebuffer(ctx
->blitter
, &ctx
->framebuffer
);
300 util_blitter_save_fragment_sampler_states(
302 ctx
->num_samplers
[PIPE_SHADER_FRAGMENT
],
303 (void **)ctx
->samplers
[PIPE_SHADER_FRAGMENT
]);
304 util_blitter_save_fragment_sampler_views(
306 ctx
->num_sampler_views
[PIPE_SHADER_FRAGMENT
],
307 ctx
->sampler_views
[PIPE_SHADER_FRAGMENT
]);
308 util_blitter_save_render_condition(ctx
->blitter
,
309 ctx
->render_cond_query
,
310 ctx
->render_cond_cond
,
311 ctx
->render_cond_mode
);
313 util_blitter_blit(ctx
->blitter
, &info
);
318 swr_destroy(struct pipe_context
*pipe
)
320 struct swr_context
*ctx
= swr_context(pipe
);
323 util_blitter_destroy(ctx
->blitter
);
326 SwrDestroyContext(ctx
->swrContext
);
328 delete ctx
->blendJIT
;
330 swr_destroy_scratch_buffers(ctx
);
337 swr_render_condition(struct pipe_context
*pipe
,
338 struct pipe_query
*query
,
342 struct swr_context
*ctx
= swr_context(pipe
);
344 ctx
->render_cond_query
= query
;
345 ctx
->render_cond_mode
= mode
;
346 ctx
->render_cond_cond
= condition
;
350 struct pipe_context
*
351 swr_create_context(struct pipe_screen
*screen
, void *priv
, unsigned flags
)
353 struct swr_context
*ctx
= CALLOC_STRUCT(swr_context
);
355 new std::unordered_map
<BLEND_COMPILE_STATE
, PFN_BLEND_JIT_FUNC
>;
357 SWR_CREATECONTEXT_INFO createInfo
;
358 createInfo
.driver
= GL
;
359 createInfo
.privateStateSize
= sizeof(swr_draw_context
);
360 createInfo
.maxSubContexts
= 0;
361 createInfo
.pfnLoadTile
= swr_LoadHotTile
;
362 createInfo
.pfnStoreTile
= swr_StoreHotTile
;
363 createInfo
.pfnClearTile
= swr_StoreHotTileClear
;
364 ctx
->swrContext
= SwrCreateContext(&createInfo
);
366 /* Init Load/Store/ClearTiles Tables */
367 swr_InitMemoryModule();
369 InitBackendFuncTables();
371 if (ctx
->swrContext
== NULL
)
374 ctx
->pipe
.screen
= screen
;
375 ctx
->pipe
.destroy
= swr_destroy
;
376 ctx
->pipe
.priv
= priv
;
377 ctx
->pipe
.create_surface
= swr_create_surface
;
378 ctx
->pipe
.surface_destroy
= swr_surface_destroy
;
379 ctx
->pipe
.transfer_map
= swr_transfer_map
;
380 ctx
->pipe
.transfer_unmap
= swr_transfer_unmap
;
382 ctx
->pipe
.transfer_flush_region
= u_default_transfer_flush_region
;
383 ctx
->pipe
.transfer_inline_write
= u_default_transfer_inline_write
;
385 ctx
->pipe
.resource_copy_region
= swr_resource_copy
;
386 ctx
->pipe
.render_condition
= swr_render_condition
;
388 swr_state_init(&ctx
->pipe
);
389 swr_clear_init(&ctx
->pipe
);
390 swr_draw_init(&ctx
->pipe
);
391 swr_query_init(&ctx
->pipe
);
393 ctx
->pipe
.blit
= swr_blit
;
394 ctx
->blitter
= util_blitter_create(&ctx
->pipe
);
399 swr_init_scratch_buffers(ctx
);
404 /* Should really validate the init steps and fail gracefully */
405 swr_destroy(&ctx
->pipe
);