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 "main/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 struct gl_transform_feedback_object
*tfb_vertcount
,
105 struct gl_buffer_object
*indirect
)
107 struct st_context
*st
= st_context(ctx
);
108 struct pipe_context
*pipe
= st
->pipe
;
109 struct draw_context
*draw
= st_get_draw_context(st
);
110 const struct st_vertex_program
*vp
;
111 struct st_common_variant
*vp_variant
;
112 struct pipe_vertex_buffer vbuffers
[PIPE_MAX_SHADER_INPUTS
];
113 unsigned num_vbuffers
= 0;
114 struct pipe_vertex_element velements
[PIPE_MAX_ATTRIBS
];
115 struct pipe_transfer
*vb_transfer
[PIPE_MAX_ATTRIBS
] = {NULL
};
116 struct pipe_transfer
*ib_transfer
= NULL
;
118 const void *mapped_indices
= NULL
;
119 struct pipe_draw_info info
;
124 /* Initialize pipe_draw_info. */
125 info
.primitive_restart
= false;
126 info
.vertices_per_patch
= ctx
->TessCtrlProgram
.patch_vertices
;
127 info
.indirect
= NULL
;
128 info
.count_from_stream_output
= NULL
;
129 info
.restart_index
= 0;
131 st_flush_bitmap_cache(st
);
132 st_invalidate_readpix_cache(st
);
134 st_validate_state(st
, ST_PIPELINE_RENDER
);
136 if (!index_bounds_valid
)
137 vbo_get_minmax_indices(ctx
, prims
, ib
, &min_index
, &max_index
, nr_prims
);
139 /* must get these after state validation! */
140 struct st_common_variant_key key
;
141 /* We have to use memcpy to make sure that all bits are copied. */
142 memcpy(&key
, &st
->vp_variant
->key
, sizeof(key
));
143 key
.is_draw_shader
= true;
145 vp
= (struct st_vertex_program
*)st
->vp
;
146 vp_variant
= st_get_vp_variant(st
, st
->vp
, &key
);
149 * Set up the draw module's state.
151 * We'd like to do this less frequently, but the normal state-update
152 * code sends state updates to the pipe, not to our private draw module.
155 draw_set_viewport_states(draw
, 0, 1, &st
->state
.viewport
[0]);
156 draw_set_clip_state(draw
, &st
->state
.clip
);
157 draw_set_rasterizer_state(draw
, &st
->state
.rasterizer
, NULL
);
158 draw_bind_vertex_shader(draw
, vp_variant
->base
.driver_shader
);
159 set_feedback_vertex_format(ctx
);
161 /* Must setup these after state validation! */
163 bool uses_user_vertex_buffers
;
164 st_setup_arrays(st
, vp
, vp_variant
, velements
, vbuffers
, &num_vbuffers
,
165 &uses_user_vertex_buffers
);
166 /* Setup current values as userspace arrays */
167 st_setup_current_user(st
, vp
, vp_variant
, velements
, vbuffers
, &num_vbuffers
);
169 /* Map all buffers and tell draw about their mapping */
170 for (unsigned buf
= 0; buf
< num_vbuffers
; ++buf
) {
171 struct pipe_vertex_buffer
*vbuffer
= &vbuffers
[buf
];
173 if (vbuffer
->is_user_buffer
) {
174 draw_set_mapped_vertex_buffer(draw
, buf
, vbuffer
->buffer
.user
, ~0);
176 void *map
= pipe_buffer_map(pipe
, vbuffer
->buffer
.resource
,
177 PIPE_TRANSFER_READ
, &vb_transfer
[buf
]);
178 draw_set_mapped_vertex_buffer(draw
, buf
, map
,
179 vbuffer
->buffer
.resource
->width0
);
183 draw_set_vertex_buffers(draw
, 0, num_vbuffers
, vbuffers
);
184 draw_set_vertex_elements(draw
, vp
->num_inputs
, velements
);
189 struct gl_buffer_object
*bufobj
= ib
->obj
;
190 unsigned index_size
= ib
->index_size
;
193 goto out_unref_vertex
;
195 if (bufobj
&& bufobj
->Name
) {
196 struct st_buffer_object
*stobj
= st_buffer_object(bufobj
);
198 start
= pointer_to_offset(ib
->ptr
) / index_size
;
199 mapped_indices
= pipe_buffer_map(pipe
, stobj
->buffer
,
200 PIPE_TRANSFER_READ
, &ib_transfer
);
203 mapped_indices
= ib
->ptr
;
206 info
.index_size
= ib
->index_size
;
207 info
.min_index
= min_index
;
208 info
.max_index
= max_index
;
209 info
.has_user_indices
= true;
210 info
.index
.user
= mapped_indices
;
212 draw_set_indexes(draw
,
213 (ubyte
*) mapped_indices
,
216 if (ctx
->Array
._PrimitiveRestart
) {
217 info
.primitive_restart
= true;
218 info
.restart_index
= _mesa_primitive_restart_index(ctx
, info
.index_size
);
222 info
.has_user_indices
= false;
225 /* set constant buffers */
226 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 0,
227 st
->state
.constants
[PIPE_SHADER_VERTEX
].ptr
,
228 st
->state
.constants
[PIPE_SHADER_VERTEX
].size
);
230 const struct gl_program
*prog
= &vp
->Base
.Base
;
231 struct pipe_transfer
*ubo_transfer
[PIPE_MAX_CONSTANT_BUFFERS
] = {0};
232 assert(prog
->info
.num_ubos
<= ARRAY_SIZE(ubo_transfer
));
234 for (unsigned i
= 0; i
< prog
->info
.num_ubos
; i
++) {
235 struct gl_buffer_binding
*binding
=
236 &st
->ctx
->UniformBufferBindings
[prog
->sh
.UniformBlocks
[i
]->Binding
];
237 struct st_buffer_object
*st_obj
= st_buffer_object(binding
->BufferObject
);
238 struct pipe_resource
*buf
= st_obj
->buffer
;
243 unsigned offset
= binding
->Offset
;
244 unsigned size
= buf
->width0
- offset
;
246 /* AutomaticSize is FALSE if the buffer was set with BindBufferRange.
247 * Take the minimum just to be sure.
249 if (!binding
->AutomaticSize
)
250 size
= MIN2(size
, (unsigned) binding
->Size
);
252 void *ptr
= pipe_buffer_map_range(pipe
, buf
, offset
, size
,
253 PIPE_TRANSFER_READ
, &ubo_transfer
[i
]);
255 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 1 + i
, ptr
,
260 /* TODO: atomic counter buffers */
261 struct pipe_transfer
*ssbo_transfer
[PIPE_MAX_SHADER_BUFFERS
] = {0};
263 for (unsigned i
= 0; i
< prog
->info
.num_ssbos
; i
++) {
264 struct gl_buffer_binding
*binding
=
265 &st
->ctx
->ShaderStorageBufferBindings
[
266 prog
->sh
.ShaderStorageBlocks
[i
]->Binding
];
267 struct st_buffer_object
*st_obj
= st_buffer_object(binding
->BufferObject
);
268 struct pipe_resource
*buf
= st_obj
->buffer
;
273 unsigned offset
= binding
->Offset
;
274 unsigned size
= buf
->width0
- binding
->Offset
;
276 /* AutomaticSize is FALSE if the buffer was set with BindBufferRange.
277 * Take the minimum just to be sure.
279 if (!binding
->AutomaticSize
)
280 size
= MIN2(size
, (unsigned) binding
->Size
);
282 void *ptr
= pipe_buffer_map_range(pipe
, buf
, offset
, size
,
283 PIPE_TRANSFER_READ
, &ssbo_transfer
[i
]);
285 draw_set_mapped_shader_buffer(draw
, PIPE_SHADER_VERTEX
,
290 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
291 for (unsigned i
= 0; i
< st
->state
.num_vert_samplers
; i
++)
292 samplers
[i
] = &st
->state
.vert_samplers
[i
];
294 draw_set_samplers(draw
, PIPE_SHADER_VERTEX
, samplers
,
295 st
->state
.num_vert_samplers
);
298 draw_set_sampler_views(draw
, PIPE_SHADER_VERTEX
,
299 st
->state
.vert_sampler_views
,
300 st
->state
.num_sampler_views
[PIPE_SHADER_VERTEX
]);
302 struct pipe_transfer
*sv_transfer
[PIPE_MAX_SAMPLERS
][PIPE_MAX_TEXTURE_LEVELS
];
304 for (unsigned i
= 0; i
< st
->state
.num_sampler_views
[PIPE_SHADER_VERTEX
]; i
++) {
305 struct pipe_sampler_view
*view
= st
->state
.vert_sampler_views
[i
];
309 struct pipe_resource
*res
= view
->texture
;
310 unsigned width0
= res
->width0
;
311 unsigned num_layers
= res
->depth0
;
312 unsigned first_level
= 0;
313 unsigned last_level
= 0;
314 uint32_t row_stride
[PIPE_MAX_TEXTURE_LEVELS
];
315 uint32_t img_stride
[PIPE_MAX_TEXTURE_LEVELS
];
316 uint32_t mip_offset
[PIPE_MAX_TEXTURE_LEVELS
];
317 uintptr_t mip_addr
[PIPE_MAX_TEXTURE_LEVELS
];
320 if (res
->target
!= PIPE_BUFFER
) {
321 first_level
= view
->u
.tex
.first_level
;
322 last_level
= view
->u
.tex
.last_level
;
323 num_layers
= view
->u
.tex
.last_layer
- view
->u
.tex
.first_layer
+ 1;
324 base_addr
= UINTPTR_MAX
;
326 for (unsigned j
= first_level
; j
<= last_level
; j
++) {
327 unsigned map_layers
= res
->target
== PIPE_TEXTURE_3D
?
328 util_num_layers(res
, j
) : num_layers
;
330 sv_transfer
[i
][j
] = NULL
;
331 mip_addr
[j
] = (uintptr_t)
332 pipe_transfer_map_3d(pipe
, res
, j
,
333 PIPE_TRANSFER_READ
, 0, 0,
334 view
->u
.tex
.first_layer
,
335 u_minify(res
->width0
, j
),
336 u_minify(res
->height0
, j
),
337 map_layers
, &sv_transfer
[i
][j
]);
338 row_stride
[j
] = sv_transfer
[i
][j
]->stride
;
339 img_stride
[j
] = sv_transfer
[i
][j
]->layer_stride
;
341 /* Get the minimum address, because the draw module takes only
342 * 1 address for the whole texture + uint32 offsets for mip levels,
343 * so we need to convert mapped resource pointers into that scheme.
345 base_addr
= MIN2(base_addr
, mip_addr
[j
]);
347 for (unsigned j
= first_level
; j
<= last_level
; j
++) {
348 /* TODO: The draw module should accept pointers for mipmap levels
349 * instead of offsets. This is unlikely to work on 64-bit archs.
351 assert(mip_addr
[j
] - base_addr
<= UINT32_MAX
);
352 mip_offset
[j
] = mip_addr
[j
] - base_addr
;
355 width0
= view
->u
.buf
.size
/ util_format_get_blocksize(view
->format
);
357 /* probably don't really need to fill that out */
362 sv_transfer
[i
][0] = NULL
;
363 base_addr
= (uintptr_t)
364 pipe_buffer_map_range(pipe
, res
, view
->u
.buf
.offset
,
370 draw_set_mapped_texture(draw
, PIPE_SHADER_VERTEX
, i
, width0
,
371 res
->height0
, num_layers
, first_level
,
372 last_level
, (void*)base_addr
, row_stride
,
373 img_stride
, mip_offset
);
377 struct pipe_image_view images
[PIPE_MAX_SHADER_IMAGES
];
378 struct pipe_transfer
*img_transfer
[PIPE_MAX_SHADER_IMAGES
] = {0};
380 for (unsigned i
= 0; i
< prog
->info
.num_images
; i
++) {
381 struct pipe_image_view
*img
= &images
[i
];
383 st_convert_image_from_unit(st
, img
, prog
->sh
.ImageUnits
[i
],
384 prog
->sh
.ImageAccess
[i
]);
386 struct pipe_resource
*res
= img
->resource
;
390 unsigned width
, height
, num_layers
, row_stride
, img_stride
;
393 if (res
->target
!= PIPE_BUFFER
) {
394 width
= u_minify(res
->width0
, img
->u
.tex
.level
);
395 height
= u_minify(res
->height0
, img
->u
.tex
.level
);
396 num_layers
= img
->u
.tex
.last_layer
- img
->u
.tex
.first_layer
+ 1;
398 addr
= pipe_transfer_map_3d(pipe
, res
, img
->u
.tex
.level
,
399 PIPE_TRANSFER_READ
, 0, 0,
400 img
->u
.tex
.first_layer
,
401 width
, height
, num_layers
,
403 row_stride
= img_transfer
[i
]->stride
;
404 img_stride
= img_transfer
[i
]->layer_stride
;
406 width
= img
->u
.buf
.size
/ util_format_get_blocksize(img
->format
);
408 /* probably don't really need to fill that out */
411 height
= num_layers
= 1;
413 addr
= pipe_buffer_map_range(pipe
, res
, img
->u
.buf
.offset
,
414 img
->u
.buf
.size
, PIPE_TRANSFER_READ
,
418 draw_set_mapped_image(draw
, PIPE_SHADER_VERTEX
, i
, width
, height
,
419 num_layers
, addr
, row_stride
, img_stride
);
421 draw_set_images(draw
, PIPE_SHADER_VERTEX
, images
, prog
->info
.num_images
);
424 for (i
= 0; i
< nr_prims
; i
++) {
425 info
.count
= prims
[i
].count
;
430 info
.mode
= prims
[i
].mode
;
431 info
.start
= start
+ prims
[i
].start
;
432 info
.start_instance
= prims
[i
].base_instance
;
433 info
.instance_count
= prims
[i
].num_instances
;
434 info
.index_bias
= prims
[i
].basevertex
;
435 info
.drawid
= prims
[i
].draw_id
;
437 info
.min_index
= info
.start
;
438 info
.max_index
= info
.start
+ info
.count
- 1;
441 draw_vbo(draw
, &info
);
445 for (unsigned i
= 0; i
< prog
->info
.num_images
; i
++) {
446 if (img_transfer
[i
]) {
447 draw_set_mapped_image(draw
, PIPE_SHADER_VERTEX
, i
, 0, 0, 0, NULL
, 0, 0);
448 pipe_transfer_unmap(pipe
, img_transfer
[i
]);
452 /* unmap sampler views */
453 for (unsigned i
= 0; i
< st
->state
.num_sampler_views
[PIPE_SHADER_VERTEX
]; i
++) {
454 struct pipe_sampler_view
*view
= st
->state
.vert_sampler_views
[i
];
457 if (view
->texture
->target
!= PIPE_BUFFER
) {
458 for (unsigned j
= view
->u
.tex
.first_level
;
459 j
<= view
->u
.tex
.last_level
; j
++) {
460 pipe_transfer_unmap(pipe
, sv_transfer
[i
][j
]);
463 pipe_transfer_unmap(pipe
, sv_transfer
[i
][0]);
468 draw_set_samplers(draw
, PIPE_SHADER_VERTEX
, NULL
, 0);
469 draw_set_sampler_views(draw
, PIPE_SHADER_VERTEX
, NULL
, 0);
471 for (unsigned i
= 0; i
< prog
->info
.num_ssbos
; i
++) {
472 if (ssbo_transfer
[i
]) {
473 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 1 + i
,
475 pipe_buffer_unmap(pipe
, ssbo_transfer
[i
]);
479 for (unsigned i
= 0; i
< prog
->info
.num_ubos
; i
++) {
480 if (ubo_transfer
[i
]) {
481 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 1 + i
,
483 pipe_buffer_unmap(pipe
, ubo_transfer
[i
]);
488 * unmap vertex/index buffers
491 draw_set_indexes(draw
, NULL
, 0, 0);
493 pipe_buffer_unmap(pipe
, ib_transfer
);
497 for (unsigned buf
= 0; buf
< num_vbuffers
; ++buf
) {
498 if (vb_transfer
[buf
])
499 pipe_buffer_unmap(pipe
, vb_transfer
[buf
]);
500 draw_set_mapped_vertex_buffer(draw
, buf
, NULL
, 0);
502 draw_set_vertex_buffers(draw
, 0, num_vbuffers
, NULL
);