1 /**************************************************************************
3 * Copyright 2007 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "util/imports.h"
29 #include "main/arrayobj.h"
30 #include "main/image.h"
31 #include "main/macros.h"
32 #include "main/varray.h"
36 #include "st_context.h"
38 #include "st_cb_bitmap.h"
39 #include "st_cb_bufferobjects.h"
41 #include "st_program.h"
44 #include "pipe/p_context.h"
45 #include "pipe/p_defines.h"
46 #include "util/u_inlines.h"
47 #include "util/u_draw.h"
48 #include "util/format/u_format.h"
50 #include "draw/draw_private.h"
51 #include "draw/draw_context.h"
55 * Set the (private) draw module's post-transformed vertex format when in
56 * GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
59 set_feedback_vertex_format(struct gl_context
*ctx
)
62 struct st_context
*st
= st_context(ctx
);
63 struct vertex_info vinfo
;
66 memset(&vinfo
, 0, sizeof(vinfo
));
68 if (ctx
->RenderMode
== GL_SELECT
) {
69 assert(ctx
->RenderMode
== GL_SELECT
);
70 vinfo
.num_attribs
= 1;
71 vinfo
.format
[0] = FORMAT_4F
;
72 vinfo
.interp_mode
[0] = INTERP_LINEAR
;
75 /* GL_FEEDBACK, or glRasterPos */
76 /* emit all attribs (pos, color, texcoord) as GLfloat[4] */
77 vinfo
.num_attribs
= st
->state
.vs
->cso
->state
.num_outputs
;
78 for (i
= 0; i
< vinfo
.num_attribs
; i
++) {
79 vinfo
.format
[i
] = FORMAT_4F
;
80 vinfo
.interp_mode
[i
] = INTERP_LINEAR
;
84 draw_set_vertex_info(st
->draw
, &vinfo
);
90 * Called by VBO to draw arrays when in selection or feedback mode and
91 * to implement glRasterPos.
92 * This function mirrors the normal st_draw_vbo().
93 * Look at code refactoring some day.
96 st_feedback_draw_vbo(struct gl_context
*ctx
,
97 const struct _mesa_prim
*prims
,
99 const struct _mesa_index_buffer
*ib
,
100 GLboolean index_bounds_valid
,
103 GLuint num_instances
,
104 GLuint base_instance
,
105 struct gl_transform_feedback_object
*tfb_vertcount
,
108 struct st_context
*st
= st_context(ctx
);
109 struct pipe_context
*pipe
= st
->pipe
;
110 struct draw_context
*draw
= st_get_draw_context(st
);
111 const struct st_vertex_program
*vp
;
112 struct st_common_variant
*vp_variant
;
113 struct pipe_vertex_buffer vbuffers
[PIPE_MAX_SHADER_INPUTS
];
114 unsigned num_vbuffers
= 0;
115 struct cso_velems_state velements
;
116 struct pipe_transfer
*vb_transfer
[PIPE_MAX_ATTRIBS
] = {NULL
};
117 struct pipe_transfer
*ib_transfer
= NULL
;
119 const void *mapped_indices
= NULL
;
120 struct pipe_draw_info info
;
125 /* Initialize pipe_draw_info. */
126 info
.primitive_restart
= false;
127 info
.vertices_per_patch
= ctx
->TessCtrlProgram
.patch_vertices
;
128 info
.indirect
= NULL
;
129 info
.count_from_stream_output
= NULL
;
130 info
.restart_index
= 0;
132 st_flush_bitmap_cache(st
);
133 st_invalidate_readpix_cache(st
);
135 st_validate_state(st
, ST_PIPELINE_RENDER
);
137 if (ib
&& !index_bounds_valid
)
138 vbo_get_minmax_indices(ctx
, prims
, ib
, &min_index
, &max_index
, nr_prims
);
140 /* must get these after state validation! */
141 struct st_common_variant_key key
;
142 /* We have to use memcpy to make sure that all bits are copied. */
143 memcpy(&key
, &st
->vp_variant
->key
, sizeof(key
));
144 key
.is_draw_shader
= true;
146 vp
= (struct st_vertex_program
*)st
->vp
;
147 vp_variant
= st_get_vp_variant(st
, st
->vp
, &key
);
150 * Set up the draw module's state.
152 * We'd like to do this less frequently, but the normal state-update
153 * code sends state updates to the pipe, not to our private draw module.
156 draw_set_viewport_states(draw
, 0, 1, &st
->state
.viewport
[0]);
157 draw_set_clip_state(draw
, &st
->state
.clip
);
158 draw_set_rasterizer_state(draw
, &st
->state
.rasterizer
, NULL
);
159 draw_bind_vertex_shader(draw
, vp_variant
->base
.driver_shader
);
160 set_feedback_vertex_format(ctx
);
162 /* Must setup these after state validation! */
164 bool uses_user_vertex_buffers
;
165 st_setup_arrays(st
, vp
, vp_variant
, &velements
, vbuffers
, &num_vbuffers
,
166 &uses_user_vertex_buffers
);
167 /* Setup current values as userspace arrays */
168 st_setup_current_user(st
, vp
, vp_variant
, &velements
, vbuffers
, &num_vbuffers
);
170 /* Map all buffers and tell draw about their mapping */
171 for (unsigned buf
= 0; buf
< num_vbuffers
; ++buf
) {
172 struct pipe_vertex_buffer
*vbuffer
= &vbuffers
[buf
];
174 if (vbuffer
->is_user_buffer
) {
175 draw_set_mapped_vertex_buffer(draw
, buf
, vbuffer
->buffer
.user
, ~0);
177 void *map
= pipe_buffer_map(pipe
, vbuffer
->buffer
.resource
,
178 PIPE_TRANSFER_READ
, &vb_transfer
[buf
]);
179 draw_set_mapped_vertex_buffer(draw
, buf
, map
,
180 vbuffer
->buffer
.resource
->width0
);
184 draw_set_vertex_buffers(draw
, 0, num_vbuffers
, vbuffers
);
185 draw_set_vertex_elements(draw
, vp
->num_inputs
, velements
.velems
);
190 struct gl_buffer_object
*bufobj
= ib
->obj
;
191 unsigned index_size
= 1 << ib
->index_size_shift
;
194 goto out_unref_vertex
;
196 if (bufobj
&& bufobj
->Name
) {
197 struct st_buffer_object
*stobj
= st_buffer_object(bufobj
);
199 start
= pointer_to_offset(ib
->ptr
) >> ib
->index_size_shift
;
200 mapped_indices
= pipe_buffer_map(pipe
, stobj
->buffer
,
201 PIPE_TRANSFER_READ
, &ib_transfer
);
204 mapped_indices
= ib
->ptr
;
207 info
.index_size
= index_size
;
208 info
.min_index
= min_index
;
209 info
.max_index
= max_index
;
210 info
.has_user_indices
= true;
211 info
.index
.user
= mapped_indices
;
213 draw_set_indexes(draw
,
214 (ubyte
*) mapped_indices
,
217 if (ctx
->Array
._PrimitiveRestart
) {
218 info
.primitive_restart
= true;
219 info
.restart_index
= ctx
->Array
._RestartIndex
[index_size
- 1];
223 info
.has_user_indices
= false;
226 /* set constant buffers */
227 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 0,
228 st
->state
.constants
[PIPE_SHADER_VERTEX
].ptr
,
229 st
->state
.constants
[PIPE_SHADER_VERTEX
].size
);
231 const struct gl_program
*prog
= &vp
->Base
.Base
;
232 struct pipe_transfer
*ubo_transfer
[PIPE_MAX_CONSTANT_BUFFERS
] = {0};
233 assert(prog
->info
.num_ubos
<= ARRAY_SIZE(ubo_transfer
));
235 for (unsigned i
= 0; i
< prog
->info
.num_ubos
; i
++) {
236 struct gl_buffer_binding
*binding
=
237 &st
->ctx
->UniformBufferBindings
[prog
->sh
.UniformBlocks
[i
]->Binding
];
238 struct st_buffer_object
*st_obj
= st_buffer_object(binding
->BufferObject
);
239 struct pipe_resource
*buf
= st_obj
->buffer
;
244 unsigned offset
= binding
->Offset
;
245 unsigned size
= buf
->width0
- offset
;
247 /* AutomaticSize is FALSE if the buffer was set with BindBufferRange.
248 * Take the minimum just to be sure.
250 if (!binding
->AutomaticSize
)
251 size
= MIN2(size
, (unsigned) binding
->Size
);
253 void *ptr
= pipe_buffer_map_range(pipe
, buf
, offset
, size
,
254 PIPE_TRANSFER_READ
, &ubo_transfer
[i
]);
256 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 1 + i
, ptr
,
261 /* TODO: atomic counter buffers */
262 struct pipe_transfer
*ssbo_transfer
[PIPE_MAX_SHADER_BUFFERS
] = {0};
264 for (unsigned i
= 0; i
< prog
->info
.num_ssbos
; i
++) {
265 struct gl_buffer_binding
*binding
=
266 &st
->ctx
->ShaderStorageBufferBindings
[
267 prog
->sh
.ShaderStorageBlocks
[i
]->Binding
];
268 struct st_buffer_object
*st_obj
= st_buffer_object(binding
->BufferObject
);
269 struct pipe_resource
*buf
= st_obj
->buffer
;
274 unsigned offset
= binding
->Offset
;
275 unsigned size
= buf
->width0
- binding
->Offset
;
277 /* AutomaticSize is FALSE if the buffer was set with BindBufferRange.
278 * Take the minimum just to be sure.
280 if (!binding
->AutomaticSize
)
281 size
= MIN2(size
, (unsigned) binding
->Size
);
283 void *ptr
= pipe_buffer_map_range(pipe
, buf
, offset
, size
,
284 PIPE_TRANSFER_READ
, &ssbo_transfer
[i
]);
286 draw_set_mapped_shader_buffer(draw
, PIPE_SHADER_VERTEX
,
291 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
292 for (unsigned i
= 0; i
< st
->state
.num_vert_samplers
; i
++)
293 samplers
[i
] = &st
->state
.vert_samplers
[i
];
295 draw_set_samplers(draw
, PIPE_SHADER_VERTEX
, samplers
,
296 st
->state
.num_vert_samplers
);
299 draw_set_sampler_views(draw
, PIPE_SHADER_VERTEX
,
300 st
->state
.vert_sampler_views
,
301 st
->state
.num_sampler_views
[PIPE_SHADER_VERTEX
]);
303 struct pipe_transfer
*sv_transfer
[PIPE_MAX_SAMPLERS
][PIPE_MAX_TEXTURE_LEVELS
];
305 for (unsigned i
= 0; i
< st
->state
.num_sampler_views
[PIPE_SHADER_VERTEX
]; i
++) {
306 struct pipe_sampler_view
*view
= st
->state
.vert_sampler_views
[i
];
310 struct pipe_resource
*res
= view
->texture
;
311 unsigned width0
= res
->width0
;
312 unsigned num_layers
= res
->depth0
;
313 unsigned first_level
= 0;
314 unsigned last_level
= 0;
315 uint32_t row_stride
[PIPE_MAX_TEXTURE_LEVELS
];
316 uint32_t img_stride
[PIPE_MAX_TEXTURE_LEVELS
];
317 uint32_t mip_offset
[PIPE_MAX_TEXTURE_LEVELS
];
318 uintptr_t mip_addr
[PIPE_MAX_TEXTURE_LEVELS
];
321 if (res
->target
!= PIPE_BUFFER
) {
322 first_level
= view
->u
.tex
.first_level
;
323 last_level
= view
->u
.tex
.last_level
;
324 num_layers
= view
->u
.tex
.last_layer
- view
->u
.tex
.first_layer
+ 1;
325 base_addr
= UINTPTR_MAX
;
327 for (unsigned j
= first_level
; j
<= last_level
; j
++) {
328 unsigned map_layers
= res
->target
== PIPE_TEXTURE_3D
?
329 util_num_layers(res
, j
) : num_layers
;
331 sv_transfer
[i
][j
] = NULL
;
332 mip_addr
[j
] = (uintptr_t)
333 pipe_transfer_map_3d(pipe
, res
, j
,
334 PIPE_TRANSFER_READ
, 0, 0,
335 view
->u
.tex
.first_layer
,
336 u_minify(res
->width0
, j
),
337 u_minify(res
->height0
, j
),
338 map_layers
, &sv_transfer
[i
][j
]);
339 row_stride
[j
] = sv_transfer
[i
][j
]->stride
;
340 img_stride
[j
] = sv_transfer
[i
][j
]->layer_stride
;
342 /* Get the minimum address, because the draw module takes only
343 * 1 address for the whole texture + uint32 offsets for mip levels,
344 * so we need to convert mapped resource pointers into that scheme.
346 base_addr
= MIN2(base_addr
, mip_addr
[j
]);
348 for (unsigned j
= first_level
; j
<= last_level
; j
++) {
349 /* TODO: The draw module should accept pointers for mipmap levels
350 * instead of offsets. This is unlikely to work on 64-bit archs.
352 assert(mip_addr
[j
] - base_addr
<= UINT32_MAX
);
353 mip_offset
[j
] = mip_addr
[j
] - base_addr
;
356 width0
= view
->u
.buf
.size
/ util_format_get_blocksize(view
->format
);
358 /* probably don't really need to fill that out */
363 sv_transfer
[i
][0] = NULL
;
364 base_addr
= (uintptr_t)
365 pipe_buffer_map_range(pipe
, res
, view
->u
.buf
.offset
,
371 draw_set_mapped_texture(draw
, PIPE_SHADER_VERTEX
, i
, width0
,
372 res
->height0
, num_layers
, first_level
,
373 last_level
, (void*)base_addr
, row_stride
,
374 img_stride
, mip_offset
);
378 struct pipe_image_view images
[PIPE_MAX_SHADER_IMAGES
];
379 struct pipe_transfer
*img_transfer
[PIPE_MAX_SHADER_IMAGES
] = {0};
381 for (unsigned i
= 0; i
< prog
->info
.num_images
; i
++) {
382 struct pipe_image_view
*img
= &images
[i
];
384 st_convert_image_from_unit(st
, img
, prog
->sh
.ImageUnits
[i
],
385 prog
->sh
.ImageAccess
[i
]);
387 struct pipe_resource
*res
= img
->resource
;
391 unsigned width
, height
, num_layers
, row_stride
, img_stride
;
394 if (res
->target
!= PIPE_BUFFER
) {
395 width
= u_minify(res
->width0
, img
->u
.tex
.level
);
396 height
= u_minify(res
->height0
, img
->u
.tex
.level
);
397 num_layers
= img
->u
.tex
.last_layer
- img
->u
.tex
.first_layer
+ 1;
399 addr
= pipe_transfer_map_3d(pipe
, res
, img
->u
.tex
.level
,
400 PIPE_TRANSFER_READ
, 0, 0,
401 img
->u
.tex
.first_layer
,
402 width
, height
, num_layers
,
404 row_stride
= img_transfer
[i
]->stride
;
405 img_stride
= img_transfer
[i
]->layer_stride
;
407 width
= img
->u
.buf
.size
/ util_format_get_blocksize(img
->format
);
409 /* probably don't really need to fill that out */
412 height
= num_layers
= 1;
414 addr
= pipe_buffer_map_range(pipe
, res
, img
->u
.buf
.offset
,
415 img
->u
.buf
.size
, PIPE_TRANSFER_READ
,
419 draw_set_mapped_image(draw
, PIPE_SHADER_VERTEX
, i
, width
, height
,
420 num_layers
, addr
, row_stride
, img_stride
);
422 draw_set_images(draw
, PIPE_SHADER_VERTEX
, images
, prog
->info
.num_images
);
424 info
.start_instance
= base_instance
;
425 info
.instance_count
= num_instances
;
428 for (i
= 0; i
< nr_prims
; i
++) {
429 info
.count
= prims
[i
].count
;
434 info
.mode
= prims
[i
].mode
;
435 info
.start
= start
+ prims
[i
].start
;
436 info
.index_bias
= prims
[i
].basevertex
;
437 info
.drawid
= prims
[i
].draw_id
;
439 info
.min_index
= info
.start
;
440 info
.max_index
= info
.start
+ info
.count
- 1;
443 draw_vbo(draw
, &info
);
447 for (unsigned i
= 0; i
< prog
->info
.num_images
; i
++) {
448 if (img_transfer
[i
]) {
449 draw_set_mapped_image(draw
, PIPE_SHADER_VERTEX
, i
, 0, 0, 0, NULL
, 0, 0);
450 pipe_transfer_unmap(pipe
, img_transfer
[i
]);
454 /* unmap sampler views */
455 for (unsigned i
= 0; i
< st
->state
.num_sampler_views
[PIPE_SHADER_VERTEX
]; i
++) {
456 struct pipe_sampler_view
*view
= st
->state
.vert_sampler_views
[i
];
459 if (view
->texture
->target
!= PIPE_BUFFER
) {
460 for (unsigned j
= view
->u
.tex
.first_level
;
461 j
<= view
->u
.tex
.last_level
; j
++) {
462 pipe_transfer_unmap(pipe
, sv_transfer
[i
][j
]);
465 pipe_transfer_unmap(pipe
, sv_transfer
[i
][0]);
470 draw_set_samplers(draw
, PIPE_SHADER_VERTEX
, NULL
, 0);
471 draw_set_sampler_views(draw
, PIPE_SHADER_VERTEX
, NULL
, 0);
473 for (unsigned i
= 0; i
< prog
->info
.num_ssbos
; i
++) {
474 if (ssbo_transfer
[i
]) {
475 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 1 + i
,
477 pipe_buffer_unmap(pipe
, ssbo_transfer
[i
]);
481 for (unsigned i
= 0; i
< prog
->info
.num_ubos
; i
++) {
482 if (ubo_transfer
[i
]) {
483 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 1 + i
,
485 pipe_buffer_unmap(pipe
, ubo_transfer
[i
]);
490 * unmap vertex/index buffers
493 draw_set_indexes(draw
, NULL
, 0, 0);
495 pipe_buffer_unmap(pipe
, ib_transfer
);
499 for (unsigned buf
= 0; buf
< num_vbuffers
; ++buf
) {
500 if (vb_transfer
[buf
])
501 pipe_buffer_unmap(pipe
, vb_transfer
[buf
]);
502 draw_set_mapped_vertex_buffer(draw
, buf
, NULL
, 0);
504 draw_set_vertex_buffers(draw
, 0, num_vbuffers
, NULL
);