#include "util/u_stream.h"
#include "util/u_math.h"
#include "util/u_tile.h"
+#include "util/u_prim.h"
#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
}
+
+static const struct debug_named_value pipe_prim_names[] = {
+#ifdef DEBUG
+ DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_LINES),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP),
+ DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON),
+#endif
+ DEBUG_NAMED_VALUE_END
+};
+
+
+const char *u_prim_name( unsigned prim )
+{
+ return debug_dump_enum(pipe_prim_names, prim);
+}
+
+
+
+
#ifdef DEBUG
void debug_dump_image(const char *prefix,
unsigned format, unsigned cpp,
}
}
+const char *u_prim_name( unsigned pipe_prim );
+
#endif
#ifndef U_UPLOAD_MGR_H
#define U_UPLOAD_MGR_H
+#include "pipe/p_error.h"
+
struct pipe_screen;
struct pipe_buffer;
struct u_upload_mgr;
brw_wm_state.c \
brw_wm_surface_state.c \
brw_bo.c \
- intel_batchbuffer.c \
+ brw_batchbuffer.c \
intel_tex_layout.c
include ../../Makefile.template
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "brw_batchbuffer.h"
+#include "brw_decode.h"
+#include "brw_reg.h"
+#include "brw_winsys.h"
+
+
+void
+brw_batchbuffer_reset(struct brw_batchbuffer *batch)
+{
+ struct intel_context *intel = batch->intel;
+
+ if (batch->buf != NULL) {
+ brw->sws->bo_unreference(batch->buf);
+ batch->buf = NULL;
+ }
+
+ if (!batch->buffer && intel->ttm == GL_TRUE)
+ batch->buffer = malloc (intel->maxBatchSize);
+
+ batch->buf = batch->sws->bo_alloc(batch->sws,
+ BRW_BUFFER_TYPE_BATCH,
+ intel->maxBatchSize, 4096);
+ if (batch->buffer)
+ batch->map = batch->buffer;
+ else {
+ batch->sws->bo_map(batch->buf, GL_TRUE);
+ batch->map = batch->buf->virtual;
+ }
+ batch->size = intel->maxBatchSize;
+ batch->ptr = batch->map;
+ batch->dirty_state = ~0;
+ batch->cliprect_mode = IGNORE_CLIPRECTS;
+}
+
+struct brw_batchbuffer *
+brw_batchbuffer_alloc(struct brw_winsys_screen *sws)
+{
+ struct brw_batchbuffer *batch = CALLOC_STRUCT(brw_batchbuffer);
+
+ batch->sws = sws;
+ brw_batchbuffer_reset(batch);
+
+ return batch;
+}
+
+void
+brw_batchbuffer_free(struct brw_batchbuffer *batch)
+{
+ if (batch->map) {
+ dri_bo_unmap(batch->buf);
+ batch->map = NULL;
+ }
+
+ brw->sws->bo_unreference(batch->buf);
+ batch->buf = NULL;
+ FREE(batch);
+}
+
+
+void
+_brw_batchbuffer_flush(struct brw_batchbuffer *batch, const char *file,
+ int line)
+{
+ struct intel_context *intel = batch->intel;
+ GLuint used = batch->ptr - batch->map;
+
+ if (used == 0)
+ return;
+
+ if (intel->first_post_swapbuffers_batch == NULL) {
+ intel->first_post_swapbuffers_batch = intel->batch->buf;
+ batch->sws->bo_reference(intel->first_post_swapbuffers_batch);
+ }
+
+ if (intel->first_post_swapbuffers_batch == NULL) {
+ intel->first_post_swapbuffers_batch = intel->batch->buf;
+ batch->sws->bo_reference(intel->first_post_swapbuffers_batch);
+ }
+
+
+ if (INTEL_DEBUG & DEBUG_BATCH)
+ fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line,
+ used);
+
+ /* Emit a flush if the bufmgr doesn't do it for us. */
+ if (intel->always_flush_cache || !intel->ttm) {
+ *(GLuint *) (batch->ptr) = intel->vtbl.flush_cmd();
+ batch->ptr += 4;
+ used = batch->ptr - batch->map;
+ }
+
+ /* Round batchbuffer usage to 2 DWORDs. */
+
+ if ((used & 4) == 0) {
+ *(GLuint *) (batch->ptr) = 0; /* noop */
+ batch->ptr += 4;
+ used = batch->ptr - batch->map;
+ }
+
+ /* Mark the end of the buffer. */
+ *(GLuint *) (batch->ptr) = MI_BATCH_BUFFER_END; /* noop */
+ batch->ptr += 4;
+ used = batch->ptr - batch->map;
+
+ batch->sws->bo_unmap(batch->buf);
+
+ batch->map = NULL;
+ batch->ptr = NULL;
+
+ batch->sws->bo_exec(batch->buf, used, NULL, 0, 0 );
+
+ if (INTEL_DEBUG & DEBUG_BATCH) {
+ dri_bo_map(batch->buf, GL_FALSE);
+ intel_decode(batch->buf->virtual, used / 4, batch->buf->offset,
+ brw->brw_screen->pci_id);
+ dri_bo_unmap(batch->buf);
+ }
+
+ if (INTEL_DEBUG & DEBUG_SYNC) {
+ fprintf(stderr, "waiting for idle\n");
+ dri_bo_map(batch->buf, GL_TRUE);
+ dri_bo_unmap(batch->buf);
+ }
+
+ /* Reset the buffer:
+ */
+ brw_batchbuffer_reset(batch);
+}
+
+
+/* This is the only way buffers get added to the validate list.
+ */
+GLboolean
+brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch,
+ struct brw_winsys_buffer *buffer,
+ uint32_t read_domains, uint32_t write_domain,
+ uint32_t delta)
+{
+ int ret;
+
+ if (batch->ptr - batch->map > batch->buf->size)
+ _mesa_printf ("bad relocation ptr %p map %p offset %d size %d\n",
+ batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
+
+ ret = batch->sws->bo_emit_reloc(batch->buf,
+ read_domains,
+ write_domain,
+ delta,
+ batch->ptr - batch->map,
+ buffer);
+
+ /*
+ * Using the old buffer offset, write in what the right data would be, in case
+ * the buffer doesn't move and we can short-circuit the relocation processing
+ * in the kernel
+ */
+ brw_batchbuffer_emit_dword (batch, buffer->offset + delta);
+
+ return GL_TRUE;
+}
+
+void
+brw_batchbuffer_data(struct brw_batchbuffer *batch,
+ const void *data, GLuint bytes,
+ enum cliprect_mode cliprect_mode)
+{
+ assert((bytes & 3) == 0);
+ brw_batchbuffer_require_space(batch, bytes);
+ __memcpy(batch->ptr, data, bytes);
+ batch->ptr += bytes;
+}
* Consider it a convenience function wrapping multple
* intel_buffer_dword() calls.
*/
-void brw_batchbuffer_data(struct brw_batchbuffer *batch,
+int brw_batchbuffer_data(struct brw_batchbuffer *batch,
const void *data, GLuint bytes,
enum cliprect_mode cliprect_mode);
-void brw_batchbuffer_release_space(struct brw_batchbuffer *batch,
- GLuint bytes);
-GLboolean brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch,
- struct brw_winsys_buffer *buffer,
- uint32_t read_domains,
- uint32_t write_domain,
- uint32_t offset);
+int brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch,
+ struct brw_winsys_buffer *buffer,
+ uint32_t read_domains,
+ uint32_t write_domain,
+ uint32_t offset);
/* Inline functions - might actually be better off with these
* non-inlined. Certainly better off switching all command packets to
svp->far = 1;
}
-static void prepare_cc_vp( struct brw_context *brw )
+static int prepare_cc_vp( struct brw_context *brw )
{
struct brw_cc_viewport ccv;
struct sane_viewport svp;
brw->sws->bo_unreference(brw->cc.vp_bo);
brw->cc.vp_bo = brw_cache_data( &brw->cache, BRW_CC_VP, &ccv, NULL, 0 );
+
+ return 0;
}
const struct brw_tracked_state brw_cc_vp = {
return bo;
}
-static void prepare_cc_unit( struct brw_context *brw )
+static int prepare_cc_unit( struct brw_context *brw )
{
struct brw_cc_unit_key key;
if (brw->cc.state_bo == NULL)
brw->cc.state_bo = cc_unit_create_from_key(brw, &key);
+
+ return 0;
}
const struct brw_tracked_state brw_cc_unit = {
/* Calculate interpolants for triangle and line rasterization.
*/
-static void upload_clip_prog(struct brw_context *brw)
+static int upload_clip_prog(struct brw_context *brw)
{
struct brw_clip_prog_key key;
&brw->clip.prog_data);
if (brw->clip.prog_bo == NULL)
compile_clip_prog( brw, &key );
+
+ return 0;
}
return bo;
}
-static void upload_clip_unit( struct brw_context *brw )
+static int upload_clip_unit( struct brw_context *brw )
{
struct brw_clip_unit_key key;
if (brw->clip.state_bo == NULL) {
brw->clip.state_bo = clip_unit_create_from_key(brw, &key);
}
+
+ return 0;
}
const struct brw_tracked_state brw_clip_unit = {
brw->state.dirty.mesa = ~0;
brw->state.dirty.brw = ~0;
- brw->emit_state_always = 0;
+ brw->flags.always_emit_state = 0;
make_empty_list(&brw->query.active_head);
#define PIPE_NEW_FRAGMENT_CONSTANTS 0x2
#define PIPE_NEW_VERTEX_CONSTANTS 0x2
#define PIPE_NEW_CLIP 0x2
+#define PIPE_NEW_INDEX_BUFFER 0x2
+#define PIPE_NEW_INDEX_RANGE 0x2
#define BRW_NEW_URB_FENCE 0x1
*/
struct brw_tracked_state {
struct brw_state_flags dirty;
- void (*prepare)( struct brw_context *brw );
- void (*emit)( struct brw_context *brw );
+ int (*prepare)( struct brw_context *brw );
+ int (*emit)( struct brw_context *brw );
};
/* Flags for brw->state.cache.
GLuint primitive;
GLuint reduced_primitive;
- GLboolean emit_state_always;
-
- /* Active vertex program:
+ /* Active state from the state tracker:
*/
struct {
const struct brw_vertex_shader *vertex_shader;
const struct brw_blend_state *blend;
const struct brw_rasterizer_state *rast;
const struct brw_depth_stencil_alpha_state *zstencil;
+
+ struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
+ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ unsigned num_vertex_elements;
+ unsigned num_vertex_buffers;
+
struct pipe_framebuffer_state fb;
struct pipe_viewport_state vp;
struct pipe_clip_state ucp;
struct pipe_buffer *vertex_constants;
struct pipe_buffer *fragment_constants;
+
+ /**
+ * Index buffer for this draw_prims call.
+ *
+ * Updates are signaled by PIPE_NEW_INDEX_BUFFER.
+ */
+ struct pipe_buffer *index_buffer;
+ unsigned index_size;
+
+ /* Updates are signalled by PIPE_NEW_INDEX_RANGE:
+ */
+ unsigned min_index;
+ unsigned max_index;
+
} curr;
struct {
struct brw_cached_batch_item *cached_batch_items;
struct {
- struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
- struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
- unsigned num_vertex_element;
- unsigned num_vertex_buffer;
-
struct u_upload_mgr *upload_vertex;
struct u_upload_mgr *upload_index;
-
- /* Summary of size and varying of active arrays, so we can check
- * for changes to this state:
+ /* Information on uploaded vertex buffers:
*/
- struct brw_vertex_info info;
- unsigned int min_index, max_index;
+ struct {
+ unsigned stride; /* in bytes between successive vertices */
+ unsigned offset; /* in bytes, of first vertex in bo */
+ unsigned vertex_count; /* count of valid vertices which may be accessed */
+ struct brw_winsys_buffer *bo;
+ } vb[PIPE_MAX_ATTRIBS];
+
+ struct {
+ } ve[PIPE_MAX_ATTRIBS];
+
+ unsigned nr_vb; /* currently the same as curr.num_vertex_buffers */
+ unsigned nr_ve; /* currently the same as curr.num_vertex_elements */
} vb;
struct {
- /**
- * Index buffer for this draw_prims call.
- *
- * Updates are signaled by BRW_NEW_INDICES.
- */
- const struct _mesa_index_buffer *ib;
-
/* Updates to these fields are signaled by BRW_NEW_INDEX_BUFFER. */
struct brw_winsys_buffer *bo;
unsigned int offset;
int index;
GLboolean active;
} query;
+
+ struct {
+ unsigned always_emit_state:1;
+ unsigned always_flush_batch:1;
+ unsigned force_swtnl:1;
+ unsigned no_swtnl:1;
+ } flags;
+
/* Used to give every program string a unique id
*/
GLuint program_id;
* constants. That greatly reduces the demand for space in the CURBE.
* Some of the comments within are dated...
*/
-static void calculate_curbe_offsets( struct brw_context *brw )
+static int calculate_curbe_offsets( struct brw_context *brw )
{
/* CACHE_NEW_WM_PROG */
const GLuint nr_fp_regs = (brw->wm.prog_data->nr_params + 15) / 16;
brw->state.dirty.brw |= BRW_NEW_CURBE_OFFSETS;
}
+
+ return 0;
}
* cache mechanism, but maybe would benefit from a comparison against
* the current uploaded set of constants.
*/
-static void prepare_constant_buffer(struct brw_context *brw)
+static int prepare_constant_buffer(struct brw_context *brw)
{
const GLuint sz = brw->curbe.total_size;
const GLuint bufsz = sz * 16 * sizeof(GLfloat);
brw->curbe.last_buf = NULL;
brw->curbe.last_bufsz = 0;
}
- return;
+ return 0;
}
buf = (GLfloat *) CALLOC(bufsz, 1);
* flushes as necessary when doublebuffering of CURBEs isn't
* possible.
*/
+
+ return 0;
}
-static void emit_constant_buffer(struct brw_context *brw)
+static int emit_constant_buffer(struct brw_context *brw)
{
GLuint sz = brw->curbe.total_size;
(sz - 1) + brw->curbe.curbe_offset);
}
ADVANCE_BATCH();
+ return 0;
}
const struct brw_tracked_state brw_constant_buffer = {
**************************************************************************/
+#include "util/u_prim.h"
+#include "util/u_upload_mgr.h"
+
#include "brw_draw.h"
#include "brw_defines.h"
#include "brw_context.h"
#include "brw_state.h"
#include "brw_debug.h"
+#include "brw_screen.h"
#include "brw_batchbuffer.h"
-#define FILE_DEBUG_FLAG DEBUG_BATCH
static uint32_t prim_to_hw_prim[PIPE_PRIM_POLYGON+1] = {
_3DPRIM_POINTLIST,
* programs be immune to the active primitive (ie. cope with all
* possibilities). That may not be realistic however.
*/
-static GLuint brw_set_prim(struct brw_context *brw, unsigned prim)
+static int brw_set_prim(struct brw_context *brw, unsigned prim )
{
if (BRW_DEBUG & DEBUG_PRIMS)
debug_printf("PRIM: %s\n", u_prim_name(prim));
if (prim != brw->primitive) {
+ unsigned reduced_prim;
+
brw->primitive = prim;
brw->state.dirty.brw |= BRW_NEW_PRIMITIVE;
- if (reduced_prim[prim] != brw->reduced_primitive) {
- brw->reduced_primitive = reduced_prim[prim];
+ reduced_prim = u_reduced_prim(prim);
+ if (reduced_prim != brw->reduced_primitive) {
+ brw->reduced_primitive = reduced_prim;
brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE;
}
}
-static enum pipe_error brw_emit_prim(struct brw_context *brw,
- unsigned prim,
- unsigned start,
- unsigned count,
- boolean indexed,
- uint32_t hw_prim)
+static int brw_emit_prim(struct brw_context *brw,
+ unsigned start,
+ unsigned count,
+ boolean indexed,
+ uint32_t hw_prim)
{
struct brw_3d_primitive prim_packet;
-
- if (INTEL_DEBUG & DEBUG_PRIMS)
- debug_printf("PRIM: %s %d %d\n", u_prim_name(prim), start, count);
+ int ret;
prim_packet.header.opcode = CMD_3D_PRIM;
prim_packet.header.length = sizeof(prim_packet)/4 - 2;
prim_packet.start_vert_location += brw->ib.start_vertex_offset;
prim_packet.instance_count = 1;
prim_packet.start_instance_location = 0;
- prim_packet.base_vert_location = prim->basevertex;
+ prim_packet.base_vert_location = 0; // prim->basevertex; XXX: add this to gallium
/* If we're set to always flush, do it before and after the primitive emit.
* and missed flushes of the render cache as it heads to other parts of
* the besides the draw code.
*/
- if (intel->always_flush_cache) {
- BEGIN_BATCH(1, IGNORE_CLIPRECTS)
- OUT_BATCH(intel->vtbl.flush_cmd());
+ if (0) {
+ BEGIN_BATCH(1, IGNORE_CLIPRECTS);
+ OUT_BATCH((CMD_MI_FLUSH << 16) | BRW_FLUSH_STATE_CACHE);
ADVANCE_BATCH();
}
if (prim_packet.verts_per_instance) {
- ret = brw_batchbuffer_data( brw->intel.batch, &prim_packet,
+ ret = brw_batchbuffer_data( brw->batch, &prim_packet,
sizeof(prim_packet), LOOP_CLIPRECTS);
if (ret)
return ret;
}
- if (intel->always_flush_cache) {
+ if (0) {
BEGIN_BATCH(1, IGNORE_CLIPRECTS);
- OUT_BATCH(intel->vtbl.flush_cmd());
+ OUT_BATCH((CMD_MI_FLUSH << 16) | BRW_FLUSH_STATE_CACHE);
ADVANCE_BATCH();
}
/* May fail if out of video memory for texture or vbo upload, or on
* fallback conditions.
*/
-static GLboolean brw_try_draw_prims( struct brw_context *brw,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index )
+static int
+try_draw_range_elements(struct brw_context *brw,
+ struct pipe_buffer *index_buffer,
+ unsigned hw_prim,
+ unsigned start, unsigned count)
{
- struct brw_context *brw = brw_context(ctx);
- GLboolean retval = GL_FALSE;
- GLboolean warn = GL_FALSE;
- GLboolean first_time = GL_TRUE;
- uint32_t hw_prim;
- GLuint i;
-
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- /* Bind all inputs, derive varying and size information:
- */
- brw_merge_inputs( brw, arrays );
-
- brw->ib.ib = ib;
- brw->state.dirty.brw |= BRW_NEW_INDICES;
-
- brw->vb.min_index = min_index;
- brw->vb.max_index = max_index;
- brw->state.dirty.brw |= BRW_NEW_VERTICES;
-
- hw_prim = brw_set_prim(brw, prim[i].mode);
+ int ret;
- brw_validate_state(brw);
+ ret = brw_validate_state(brw);
+ if (ret)
+ return ret;
/* Check that we can fit our state in with our existing batchbuffer, or
* flush otherwise.
*/
- ret = dri_bufmgr_check_aperture_space(brw->state.validated_bos,
- brw->state.validated_bo_count);
+ ret = brw->sws->check_aperture_space(brw->sws,
+ brw->state.validated_bos,
+ brw->state.validated_bo_count);
if (ret)
return ret;
if (ret)
return ret;
- ret = brw_emit_prim(brw, &prim[i], hw_prim);
+ ret = brw_emit_prim(brw, start, count, index_buffer != NULL, hw_prim);
if (ret)
return ret;
- if (intel->always_flush_batch)
- brw_batchbuffer_flush(intel->batch);
+ if (brw->flags.always_flush_batch)
+ brw_batchbuffer_flush(brw->batch);
return 0;
}
unsigned max_index,
unsigned mode, unsigned start, unsigned count)
{
- enum pipe_error ret;
+ struct brw_context *brw = brw_context(pipe);
+ int ret;
+ uint32_t hw_prim;
+
+ hw_prim = brw_set_prim(brw, mode);
- if (!vbo_all_varyings_in_vbos(arrays)) {
- if (!index_bounds_valid)
- vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+ if (BRW_DEBUG & DEBUG_PRIMS)
+ debug_printf("PRIM: %s %d %d\n", u_prim_name(mode), start, count);
+
+ /* Potentially trigger upload of new index buffer.
+ *
+ * XXX: do we need to go through state validation to achieve this?
+ * Could just call upload code directly.
+ */
+ if (brw->curr.index_buffer != index_buffer) {
+ pipe_buffer_reference( &brw->curr.index_buffer, index_buffer );
+ brw->state.dirty.mesa |= PIPE_NEW_INDEX_BUFFER;
+ }
+
+ /* XXX: do we really care?
+ */
+ if (brw->curr.min_index != min_index ||
+ brw->curr.max_index != max_index)
+ {
+ brw->curr.min_index = min_index;
+ brw->curr.max_index = max_index;
+ brw->state.dirty.mesa |= PIPE_NEW_INDEX_RANGE;
}
+
/* Make a first attempt at drawing:
*/
- ret = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+ ret = try_draw_range_elements(brw, index_buffer, hw_prim, start, count );
/* Otherwise, flush and retry:
*/
if (ret != 0) {
- brw_batchbuffer_flush(intel->batch);
- ret = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+ brw_batchbuffer_flush(brw->batch);
+ ret = try_draw_range_elements(brw, index_buffer, hw_prim, start, count );
assert(ret == 0);
}
-void brw_draw_init( struct brw_context *brw )
+boolean brw_draw_init( struct brw_context *brw )
{
/* Register our drawing function:
*/
brw->base.draw_arrays = brw_draw_arrays;
brw->base.draw_elements = brw_draw_elements;
brw->base.draw_range_elements = brw_draw_range_elements;
-}
-void brw_draw_destroy( struct brw_context *brw )
-{
- int i;
+ /* Create helpers for uploading data in user buffers:
+ */
+ brw->vb.upload_vertex = u_upload_create( &brw->brw_screen->base,
+ 128 * 1024,
+ 64,
+ PIPE_BUFFER_USAGE_VERTEX );
+ if (brw->vb.upload_vertex == NULL)
+ return FALSE;
+
+ brw->vb.upload_index = u_upload_create( &brw->brw_screen->base,
+ 128 * 1024,
+ 64,
+ PIPE_BUFFER_USAGE_INDEX );
+ if (brw->vb.upload_index == NULL)
+ return FALSE;
- if (brw->vb.upload.bo != NULL) {
- brw->sws->bo_unreference(brw->vb.upload.bo);
- brw->vb.upload.bo = NULL;
- }
+ return TRUE;
+}
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- brw->sws->bo_unreference(brw->vb.inputs[i].bo);
- brw->vb.inputs[i].bo = NULL;
- }
+void brw_draw_cleanup( struct brw_context *brw )
+{
+ u_upload_destroy( brw->vb.upload_vertex );
+ u_upload_destroy( brw->vb.upload_index );
brw->sws->bo_unreference(brw->ib.bo);
brw->ib.bo = NULL;
struct brw_context;
-
-void brw_draw_init( struct brw_context *brw );
+boolean brw_draw_init( struct brw_context *brw );
void brw_draw_cleanup( struct brw_context *brw );
**************************************************************************/
#include "pipe/p_context.h"
+#include "pipe/p_error.h"
#include "util/u_upload_mgr.h"
+#include "util/u_math.h"
#include "brw_draw.h"
#include "brw_defines.h"
#include "brw_context.h"
#include "brw_state.h"
-#include "brw_fallback.h"
-
+#include "brw_screen.h"
#include "brw_batchbuffer.h"
+#include "brw_debug.h"
-unsigned brw_translate_surface_format( unsigned id )
+static unsigned brw_translate_surface_format( unsigned id )
{
switch (id) {
case PIPE_FORMAT_R64_FLOAT:
}
-
-static boolean brw_prepare_vertices(struct brw_context *brw)
+static int brw_prepare_vertices(struct brw_context *brw)
{
- GLbitfield vs_inputs = brw->vs.prog_data->inputs_read;
+ unsigned int min_index = brw->curr.min_index;
+ unsigned int max_index = brw->curr.max_index;
GLuint i;
- const unsigned char *ptr = NULL;
- GLuint interleave = 0;
- unsigned int min_index = brw->vb.min_index;
- unsigned int max_index = brw->vb.max_index;
-
- struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
- GLuint nr_uploads = 0;
-
- /* First build an array of pointers to ve's in vb.inputs_read
- */
- if (0)
- _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
-
+ int ret;
+ if (BRW_DEBUG & DEBUG_VERTS)
+ debug_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
- for (i = 0; i < brw->vb.num_vertex_buffer; i++) {
- struct brw_vertex_buffer *vb = brw->vb.vertex_buffer[i];
- unsigned size = (vb->stride == 0 ?
- vb->size :
- vb->stride * (max_index + 1 - min_index));
-
- if (brw_is_user_buffer(vb)) {
- u_upload_buffer( brw->upload_vertex,
- min_index * vb->stride,
- size,
- &offset,
- &buffer );
+ for (i = 0; i < brw->curr.num_vertex_buffers; i++) {
+ struct pipe_vertex_buffer *vb = &brw->curr.vertex_buffer[i];
+ struct brw_winsys_buffer *bo;
+ struct pipe_buffer *upload_buf;
+ unsigned offset;
+
+ if (BRW_DEBUG & DEBUG_VERTS)
+ debug_printf("%s vb[%d] user:%d offset:0x%x sz:0x%x stride:0x%x\n",
+ __FUNCTION__, i,
+ brw_buffer_is_user_buffer(vb->buffer),
+ vb->buffer_offset,
+ vb->buffer->size,
+ vb->stride);
+
+ if (brw_buffer_is_user_buffer(vb->buffer)) {
+
+ /* XXX: simplify this. Stop the state trackers from generating
+ * zero-stride buffers & have them use additional constants (or
+ * add support for >1 constant buffer) instead.
+ */
+ unsigned size = (vb->stride == 0 ?
+ vb->buffer->size - vb->buffer_offset :
+ MAX2(vb->buffer->size - vb->buffer_offset,
+ vb->stride * (max_index + 1 - min_index)));
+
+ ret = u_upload_buffer( brw->vb.upload_vertex,
+ vb->buffer_offset + min_index * vb->stride,
+ size,
+ vb->buffer,
+ &offset,
+ &upload_buf );
+ if (ret)
+ return ret;
+
+ bo = brw_buffer(upload_buf)->bo;
+
+ assert(offset + size <= bo->size);
}
else
{
- offset = 0;
- buffer = vb->buffer;
+ offset = vb->buffer_offset;
+ bo = brw_buffer(vb->buffer)->bo;
}
+
+ assert(offset < bo->size);
/* Set up post-upload info about this vertex buffer:
*/
- input->offset = (unsigned long)offset;
- input->stride = vb->stride;
- input->count = count;
- brw->sws->bo_unreference(input->bo);
- input->bo = intel_bufferobj_buffer(intel, intel_buffer,
- INTEL_READ);
- brw->sws->bo_reference(input->bo);
-
- assert(input->offset < input->bo->size);
- assert(input->offset + size <= input->bo->size);
+ brw->vb.vb[i].offset = offset;
+ brw->vb.vb[i].stride = vb->stride;
+ brw->vb.vb[i].vertex_count = (vb->stride == 0 ?
+ 1 :
+ (bo->size - offset) / vb->stride);
+ brw->sws->bo_unreference(brw->vb.vb[i].bo);
+ brw->vb.vb[i].bo = bo;
+ brw->sws->bo_reference(brw->vb.vb[i].bo);
+
+ /* Don't need to retain this reference. We have a reference on
+ * the underlying winsys buffer:
+ */
+ pipe_buffer_reference( &upload_buf, NULL );
}
+ brw->vb.nr_vb = i;
brw_prepare_query_begin(brw);
- for (i = 0; i < brw->vb.nr_enabled; i++) {
- struct brw_vertex_element *input = brw->vb.enabled[i];
+ for (i = 0; i < brw->vb.nr_vb; i++) {
+ brw_add_validated_bo(brw, brw->vb.vb[i].bo);
+ }
+
+ return 0;
+}
+
+static int brw_emit_vertex_buffers( struct brw_context *brw )
+{
+ int i;
+
+ /* If the VS doesn't read any inputs (calculating vertex position from
+ * a state variable for some reason, for example), just bail.
+ *
+ * The stale VB state stays in place, but they don't do anything unless
+ * a VE loads from them.
+ */
+ if (brw->vb.nr_vb == 0) {
+ if (BRW_DEBUG & DEBUG_VERTS)
+ debug_printf("%s: no active vertex buffers\n", __FUNCTION__);
- brw_add_validated_bo(brw, input->bo);
+ return 0;
+ }
+
+ /* Emit VB state packets.
+ */
+ BEGIN_BATCH(1 + brw->vb.nr_vb * 4, IGNORE_CLIPRECTS);
+ OUT_BATCH((CMD_VERTEX_BUFFER << 16) |
+ ((1 + brw->vb.nr_vb * 4) - 2));
+
+ for (i = 0; i < brw->vb.nr_vb; i++) {
+ OUT_BATCH((i << BRW_VB0_INDEX_SHIFT) |
+ BRW_VB0_ACCESS_VERTEXDATA |
+ (brw->vb.vb[i].stride << BRW_VB0_PITCH_SHIFT));
+ OUT_RELOC(brw->vb.vb[i].bo,
+ I915_GEM_DOMAIN_VERTEX, 0,
+ brw->vb.vb[i].offset);
+ if (BRW_IS_IGDNG(brw)) {
+ OUT_RELOC(brw->vb.vb[i].bo,
+ I915_GEM_DOMAIN_VERTEX, 0,
+ brw->vb.vb[i].bo->size - 1);
+ } else
+ OUT_BATCH(brw->vb.vb[i].stride ? brw->vb.vb[i].vertex_count : 0);
+ OUT_BATCH(0); /* Instance data step rate */
}
+ ADVANCE_BATCH();
+ return 0;
}
-static void brw_emit_vertices(struct brw_context *brw)
+
+
+
+static int brw_emit_vertex_elements(struct brw_context *brw)
{
GLuint i;
* The stale VB state stays in place, but they don't do anything unless
* a VE loads from them.
*/
- if (brw->vb.nr_enabled == 0) {
+ if (brw->vb.nr_ve == 0) {
BEGIN_BATCH(3, IGNORE_CLIPRECTS);
OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | 1);
OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
(BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT));
ADVANCE_BATCH();
- return;
+ return 0;
}
- /* Now emit VB and VEP state packets.
+ /* Now emit vertex element (VEP) state packets.
*
- * This still defines a hardware VB for each input, even if they
- * are interleaved or from the same VBO. TBD if this makes a
- * performance difference.
*/
- BEGIN_BATCH(1 + brw->vb.nr_enabled * 4, IGNORE_CLIPRECTS);
- OUT_BATCH((CMD_VERTEX_BUFFER << 16) |
- ((1 + brw->vb.nr_enabled * 4) - 2));
-
- for (i = 0; i < brw->vb.nr_enabled; i++) {
- struct brw_vertex_element *input = brw->vb.enabled[i];
-
- OUT_BATCH((i << BRW_VB0_INDEX_SHIFT) |
- BRW_VB0_ACCESS_VERTEXDATA |
- (input->stride << BRW_VB0_PITCH_SHIFT));
- OUT_RELOC(input->bo,
- I915_GEM_DOMAIN_VERTEX, 0,
- input->offset);
- if (BRW_IS_IGDNG(brw)) {
- if (input->stride) {
- OUT_RELOC(input->bo,
- I915_GEM_DOMAIN_VERTEX, 0,
- input->offset + input->stride * input->count - 1);
- } else {
- assert(input->count == 1);
- OUT_RELOC(input->bo,
- I915_GEM_DOMAIN_VERTEX, 0,
- input->offset + input->element_size - 1);
- }
- } else
- OUT_BATCH(input->stride ? input->count : 0);
- OUT_BATCH(0); /* Instance data step rate */
- }
- ADVANCE_BATCH();
-
- BEGIN_BATCH(1 + brw->vb.nr_enabled * 2, IGNORE_CLIPRECTS);
- OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + brw->vb.nr_enabled * 2) - 2));
- for (i = 0; i < brw->vb.nr_enabled; i++) {
- struct brw_vertex_element *input = brw->vb.enabled[i];
- uint32_t format = get_surface_type(input->glarray->Type,
- input->glarray->Size,
- input->glarray->Format,
- input->glarray->Normalized);
+ BEGIN_BATCH(1 + brw->curr.num_vertex_elements * 2, IGNORE_CLIPRECTS);
+ OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + brw->vb.nr_ve * 2) - 2));
+ for (i = 0; i < brw->vb.nr_ve; i++) {
+ const struct pipe_vertex_element *input = &brw->curr.vertex_element[i];
+ uint32_t format = brw_translate_surface_format( input->src_format );
uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC;
uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC;
uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC;
uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC;
- switch (input->glarray->Size) {
+ switch (input->nr_components) {
case 0: comp0 = BRW_VE1_COMPONENT_STORE_0;
case 1: comp1 = BRW_VE1_COMPONENT_STORE_0;
case 2: comp2 = BRW_VE1_COMPONENT_STORE_0;
((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
}
ADVANCE_BATCH();
+ return 0;
+}
+
+
+static int brw_emit_vertices( struct brw_context *brw )
+{
+ int ret;
+
+ ret = brw_emit_vertex_buffers( brw );
+ if (ret)
+ return ret;
+
+ ret = brw_emit_vertex_elements( brw );
+ if (ret)
+ return ret;
+
+ return 0;
}
+
const struct brw_tracked_state brw_vertices = {
.dirty = {
- .mesa = 0,
+ .mesa = PIPE_NEW_INDEX_RANGE,
.brw = BRW_NEW_BATCH | BRW_NEW_VERTICES,
.cache = 0,
},
.emit = brw_emit_vertices,
};
-static void brw_prepare_indices(struct brw_context *brw)
+
+static int brw_prepare_indices(struct brw_context *brw)
{
- const struct _mesa_index_buffer *index_buffer = brw->ib.ib;
- GLuint ib_size;
+ struct pipe_buffer *index_buffer = brw->curr.index_buffer;
struct brw_winsys_buffer *bo = NULL;
- struct gl_buffer_object *bufferobj;
GLuint offset;
- GLuint ib_type_size;
+ GLuint index_size;
+ GLuint ib_size;
+ int ret;
if (index_buffer == NULL)
- return;
+ return 0;
- ib_type_size = get_size(index_buffer->type);
- ib_size = ib_type_size * index_buffer->count;
- bufferobj = index_buffer->obj;;
+ if (DEBUG & DEBUG_VERTS)
+ debug_printf("%s: index_size:%d index_buffer->size:%d\n",
+ __FUNCTION__,
+ brw->curr.index_size,
+ brw->curr.index_buffer->size);
- /* Turn into a proper VBO:
- */
- if (!_mesa_is_bufferobj(bufferobj)) {
- brw->ib.start_vertex_offset = 0;
+ ib_size = index_buffer->size;
+ index_size = brw->curr.index_size;
- /* Get new bufferobj, offset:
- */
- get_space(brw, ib_size, &bo, &offset);
-
- /* Straight upload
+ /* Turn userbuffer into a proper hardware buffer?
+ */
+ if (brw_buffer_is_user_buffer(index_buffer)) {
+ struct pipe_buffer *upload_buf;
+
+ ret = u_upload_buffer( brw->vb.upload_index,
+ 0,
+ ib_size,
+ index_buffer,
+ &offset,
+ &upload_buf );
+ if (ret)
+ return ret;
+
+ bo = brw_buffer(upload_buf)->bo;
+ brw->sws->bo_reference(bo);
+ pipe_buffer_reference( &upload_buf, NULL );
+
+ /* XXX: annotate the userbuffer with the upload information so
+ * that successive calls don't get re-uploaded.
*/
- brw_bo_subdata(bo, offset, ib_size, index_buffer->ptr);
-
- } else {
- offset = (GLuint) (unsigned long) index_buffer->ptr;
- brw->ib.start_vertex_offset = 0;
+ }
+ else {
+ bo = brw_buffer(index_buffer)->bo;
+ brw->sws->bo_reference(bo);
+
+ ib_size = bo->size;
+ offset = 0;
+ }
- /* If the index buffer isn't aligned to its element size, we have to
- * rebase it into a temporary.
- */
- if ((get_size(index_buffer->type) - 1) & offset) {
- GLubyte *map = ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_DYNAMIC_DRAW_ARB,
- bufferobj);
- map += offset;
-
- get_space(brw, ib_size, &bo, &offset);
-
- dri_bo_subdata(bo, offset, ib_size, map);
-
- ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobj);
- } else {
- bo = intel_bufferobj_buffer(intel, intel_buffer_object(bufferobj),
- INTEL_READ);
- brw->sws->bo_reference(bo);
-
- /* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading
- * the index buffer state when we're just moving the start index
- * of our drawing.
- */
- brw->ib.start_vertex_offset = offset / ib_type_size;
- offset = 0;
- ib_size = bo->size;
- }
+ /* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading the
+ * index buffer state when we're just moving the start index of our
+ * drawing.
+ *
+ * In gallium this will happen in the case where successive draw
+ * calls are made with (distinct?) userbuffers, but the upload_mgr
+ * places the data into a single winsys buffer.
+ *
+ * This statechange doesn't raise any state flags and is always
+ * just merged into the final draw packet:
+ */
+ if (1) {
+ assert((offset & (index_size - 1)) == 0);
+ brw->ib.start_vertex_offset = offset / index_size;
}
+ /* These statechanges trigger a new CMD_INDEX_BUFFER packet:
+ */
if (brw->ib.bo != bo ||
- brw->ib.offset != offset ||
brw->ib.size != ib_size)
{
- drm_intel_bo_unreference(brw->ib.bo);
+ brw->sws->bo_unreference(brw->ib.bo);
brw->ib.bo = bo;
- brw->ib.offset = offset;
brw->ib.size = ib_size;
-
brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER;
- } else {
- drm_intel_bo_unreference(bo);
+ }
+ else {
+ brw->sws->bo_unreference(bo);
}
brw_add_validated_bo(brw, brw->ib.bo);
+ return 0;
}
const struct brw_tracked_state brw_indices = {
.dirty = {
- .mesa = 0,
- .brw = BRW_NEW_INDICES,
+ .mesa = PIPE_NEW_INDEX_BUFFER,
+ .brw = 0,
.cache = 0,
},
.prepare = brw_prepare_indices,
};
-static void brw_emit_index_buffer(struct brw_context *brw)
+static int brw_emit_index_buffer(struct brw_context *brw)
{
- const struct _mesa_index_buffer *index_buffer = brw->ib.ib;
-
- if (index_buffer == NULL)
- return;
-
/* Emit the indexbuffer packet:
*/
+ if (brw->ib.bo)
{
struct brw_indexbuffer ib;
ib.header.bits.opcode = CMD_INDEX_BUFFER;
ib.header.bits.length = sizeof(ib)/4 - 2;
- ib.header.bits.index_format = get_index_type(index_buffer->type);
+ ib.header.bits.index_format = get_index_type(brw->ib.size);
ib.header.bits.cut_index_enable = 0;
BEGIN_BATCH(4, IGNORE_CLIPRECTS);
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
+
+ return 0;
}
const struct brw_tracked_state brw_index_buffer = {
* Keith Whitwell <keith@tungstengraphics.com>
*/
+#include "util/u_memory.h"
#include "brw_context.h"
#include "brw_defines.h"
struct brw_glsl_call *call, *next;
for (call = c->first_call; call; call = next) {
next = call->next;
- _mesa_free(call);
+ FREE(call);
}
c->first_call = NULL;
}
struct brw_glsl_label *label, *next;
for (label = c->first_label; label; label = next) {
next = label->next;
- _mesa_free(label);
+ FREE(label);
}
c->first_label = NULL;
}
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
-
+
+#include "util/u_debug.h"
#include "brw_eu.h"
"f"
};
- _mesa_printf("%s%s",
+ debug_printf("%s%s",
hwreg.abs ? "abs/" : "",
hwreg.negate ? "-" : "");
hwreg.hstride == BRW_HORIZONTAL_STRIDE_1 &&
hwreg.type == BRW_REGISTER_TYPE_F) {
/* vector register */
- _mesa_printf("vec%d", hwreg.nr);
+ debug_printf("vec%d", hwreg.nr);
}
else if (hwreg.file == BRW_GENERAL_REGISTER_FILE &&
hwreg.vstride == BRW_VERTICAL_STRIDE_0 &&
hwreg.hstride == BRW_HORIZONTAL_STRIDE_0 &&
hwreg.type == BRW_REGISTER_TYPE_F) {
/* "scalar" register */
- _mesa_printf("scl%d.%d", hwreg.nr, hwreg.subnr / 4);
+ debug_printf("scl%d.%d", hwreg.nr, hwreg.subnr / 4);
}
else if (hwreg.file == BRW_IMMEDIATE_VALUE) {
- _mesa_printf("imm %f", hwreg.dw1.f);
+ debug_printf("imm %f", hwreg.dw1.f);
}
else {
- _mesa_printf("%s%d.%d<%d;%d,%d>:%s",
+ debug_printf("%s%d.%d<%d;%d,%d>:%s",
file[hwreg.file],
hwreg.nr,
hwreg.subnr / type_sz(hwreg.type),
static void upload_polygon_stipple_offset(struct brw_context *brw)
{
- __DRIdrawablePrivate *dPriv = brw->intel.driDrawable;
struct brw_polygon_stipple_offset bpso;
memset(&bpso, 0, sizeof(bpso));
bpso.header.opcode = CMD_POLY_STIPPLE_OFFSET;
bpso.header.length = sizeof(bpso)/4-2;
- /* If we're drawing to a system window (ctx->DrawBuffer->Name == 0),
- * we have to invert the Y axis in order to match the OpenGL
- * pixel coordinate system, and our offset must be matched
- * to the window position. If we're drawing to a FBO
- * (ctx->DrawBuffer->Name != 0), then our native pixel coordinate
- * system works just fine, and there's no window system to
- * worry about.
+ /* Never need to offset stipple coordinates.
+ *
+ * XXX: is it ever necessary to invert Y values?
*/
- if (brw->intel.ctx.DrawBuffer->Name == 0) {
- bpso.bits0.x_offset = (32 - (dPriv->x & 31)) & 31;
- bpso.bits0.y_offset = (32 - ((dPriv->y + dPriv->h) & 31)) & 31;
+ if (0) {
+ int x = 0, y = 0, h = 0;
+ bpso.bits0.x_offset = (32 - (x & 31)) & 31;
+ bpso.bits0.y_offset = (32 - ((y + h) & 31)) & 31;
}
else {
bpso.bits0.y_offset = 0;
static GLuint brw_flush_cmd( void )
{
struct brw_mi_flush flush;
+
+ return ;
+
flush.opcode = CMD_MI_FLUSH;
flush.pad = 0;
flush.flags = BRW_FLUSH_STATE_CACHE;
#include "brw_util.h"
#include "brw_wm.h"
+
+/**
+ * Determine if the given fragment program uses GLSL features such
+ * as flow conditionals, loops, subroutines.
+ * Some GLSL shaders may use these features, others might not.
+ */
+GLboolean brw_wm_is_glsl(const struct brw_fragment_shader *fp)
+{
+ return (fp->info.insn_count[TGSI_OPCODE_ARL] > 0 ||
+ fp->info.insn_count[TGSI_OPCODE_IF] > 0 ||
+ fp->info.insn_count[TGSI_OPCODE_ENDIF] > 0 || /* redundant - IF */
+ fp->info.insn_count[TGSI_OPCODE_CAL] > 0 ||
+ fp->info.insn_count[TGSI_OPCODE_BRK] > 0 || /* redundant - BGNLOOP */
+ fp->info.insn_count[TGSI_OPCODE_RET] > 0 || /* redundant - CAL */
+ fp->info.insn_count[TGSI_OPCODE_BGNLOOP] > 0);
+}
+
+
+
static void brwBindProgram( struct brw_context *brw,
GLenum target,
struct gl_program *prog )
-static void brw_merge_inputs( struct brw_context *brw,
- const struct gl_client_array *arrays[])
-{
- struct brw_vertex_info old = brw->vb.info;
- GLuint i;
-
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
- brw->sws->bo_unreference(brw->vb.inputs[i].bo);
- memset(&brw->vb.inputs, 0, sizeof(brw->vb.inputs));
- memset(&brw->vb.info, 0, sizeof(brw->vb.info));
+void
+brw_pipe_vertex_cleanup( struct brw_context *brw )
+{
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- brw->vb.inputs[i].glarray = arrays[i];
- brw->vb.inputs[i].attrib = (gl_vert_attrib) i;
-
- if (arrays[i]->StrideB != 0)
- brw->vb.info.sizes[i/16] |= (brw->vb.inputs[i].glarray->Size - 1) <<
- ((i%16) * 2);
+ brw->sws->bo_unreference(brw->vb.inputs[i].bo);
+ brw->vb.inputs[i].bo = NULL;
}
-
- /* Raise statechanges if input sizes have changed. */
- if (memcmp(brw->vb.info.sizes, old.sizes, sizeof(old.sizes)) != 0)
- brw->state.dirty.brw |= BRW_NEW_INPUT_DIMENSIONS;
}
unsigned offset;
};
+struct brw_buffer
+{
+ struct pipe_buffer base;
+ struct brw_winsys_buffer *bo;
+ void *ptr;
+ boolean is_user_buffer;
+};
+
/*
* Cast wrappers
return (struct brw_transfer *)transfer;
}
+static INLINE struct brw_buffer *
+brw_buffer(struct pipe_buffer *buffer)
+{
+ return (struct brw_buffer *)buffer;
+}
+
+
+/* Pipe buffer helpers
+ */
+static INLINE boolean
+brw_buffer_is_user_buffer( const struct pipe_buffer *buf )
+{
+ return ((const struct brw_buffer *)buf)->is_user_buffer;
+}
#endif /* BRW_SCREEN_H */
key.attrs = brw->vs.prog_data->outputs_written;
/* BRW_NEW_REDUCED_PRIMITIVE */
- switch (brw->intel.reduced_primitive) {
+ switch (brw->reduced_primitive) {
case GL_TRIANGLES:
/* NOTE: We just use the edgeflag attribute as an indicator that
* unfilled triangles are active. We don't actually do the
const GLfloat depth_scale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
struct brw_sf_viewport sfv;
GLfloat y_scale, y_bias;
- const GLboolean render_to_fbo = (ctx->DrawBuffer->Name != 0);
const GLfloat *v = ctx->Viewport._WindowMap.m;
memset(&sfv, 0, sizeof(sfv));
- if (render_to_fbo) {
- y_scale = 1.0;
- y_bias = 0;
- }
- else {
- y_scale = -1.0;
- y_bias = ctx->DrawBuffer->Height;
- }
+ y_scale = 1.0;
+ y_bias = 0;
/* _NEW_VIEWPORT */
* Note that the hardware's coordinates are inclusive, while Mesa's min is
* inclusive but max is exclusive.
*/
- if (render_to_fbo) {
- /* texmemory: Y=0=bottom */
- sfv.scissor.xmin = ctx->DrawBuffer->_Xmin;
- sfv.scissor.xmax = ctx->DrawBuffer->_Xmax - 1;
- sfv.scissor.ymin = ctx->DrawBuffer->_Ymin;
- sfv.scissor.ymax = ctx->DrawBuffer->_Ymax - 1;
- }
- else {
- /* memory: Y=0=top */
- sfv.scissor.xmin = ctx->DrawBuffer->_Xmin;
- sfv.scissor.xmax = ctx->DrawBuffer->_Xmax - 1;
- sfv.scissor.ymin = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax;
- sfv.scissor.ymax = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin - 1;
- }
+ /* Y=0=bottom */
+ sfv.scissor.xmin = ctx->DrawBuffer->_Xmin;
+ sfv.scissor.xmax = ctx->DrawBuffer->_Xmax - 1;
+ sfv.scissor.ymin = ctx->DrawBuffer->_Ymin;
+ sfv.scissor.ymax = ctx->DrawBuffer->_Ymax - 1;
brw->sws->bo_unreference(brw->sf.vp_bo);
brw->sf.vp_bo = brw_cache_data( &brw->cache, BRW_SF_VP, &sfv, NULL, 0 );
/* _NEW_LIGHT */
key->provoking_vertex = ctx->Light.ProvokingVertex;
- key->render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0;
+ key->render_to_fbo = 1;
}
static struct brw_winsys_buffer *
else
sf.sf5.front_winding = BRW_FRONTWINDING_CW;
- /* The viewport is inverted for rendering to a FBO, and that inverts
- * polygon front/back orientation.
- */
- sf.sf5.front_winding ^= key->render_to_fbo;
-
switch (key->cull_face) {
case GL_FRONT:
sf.sf6.cull_mode = BRW_CULLMODE_FRONT;
sf.sf6.line_width = 0;
/* _NEW_BUFFERS */
- key->render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0;
+ key->render_to_fbo = 1;
if (!key->render_to_fbo) {
/* Rendering to an OpenGL window */
sf.sf6.point_rast_rule = BRW_RASTRULE_UPPER_RIGHT;
/***********************************************************************
* brw_state.c
*/
-void brw_validate_state(struct brw_context *brw);
-void brw_upload_state(struct brw_context *brw);
+int brw_validate_state(struct brw_context *brw);
+int brw_upload_state(struct brw_context *brw);
void brw_init_state(struct brw_context *brw);
void brw_destroy_state(struct brw_context *brw);
/***********************************************************************
* brw_state_batch.c
*/
-#define BRW_BATCH_STRUCT(brw, s) brw_batchbuffer_data( brw->intel.batch, (s), sizeof(*(s)), IGNORE_CLIPRECTS)
+#define BRW_BATCH_STRUCT(brw, s) brw_batchbuffer_data( brw->batch, (s), sizeof(*(s)), IGNORE_CLIPRECTS)
#define BRW_CACHED_BATCH_STRUCT(brw, s) brw_cached_batch_struct( brw, (s), sizeof(*(s)) )
GLboolean brw_cached_batch_struct( struct brw_context *brw,
struct header *newheader = (struct header *)data;
if (brw->emit_state_always) {
- brw_batchbuffer_data(brw->intel.batch, data, sz, IGNORE_CLIPRECTS);
+ brw_batchbuffer_data(brw->batch, data, sz, IGNORE_CLIPRECTS);
return GL_TRUE;
}
emit:
memcpy(item->header, newheader, sz);
- brw_batchbuffer_data(brw->intel.batch, data, sz, IGNORE_CLIPRECTS);
+ brw_batchbuffer_data(brw->batch, data, sz, IGNORE_CLIPRECTS);
return GL_TRUE;
}
* use fallbacks. If we're forcing fallbacks, always
* use fallfacks.
*/
- if (brw->intel.conformance_mode == 0)
+ if (brw->flags.no_swtnl)
return GL_FALSE;
- if (brw->intel.conformance_mode == 2)
+ if (brw->flags.force_swtnl)
return GL_TRUE;
- if (ctx->Polygon.SmoothFlag) {
+ if (brw->curr.rast->tmpl.smooth_polys) {
for (i = 0; i < nr_prims; i++)
if (reduced_prim[prim[i].mode] == GL_TRIANGLES)
return GL_TRUE;
size_t size,
const void *data);
+ /* XXX: couldn't this be handled by returning true/false on
+ * bo_emit_reloc?
+ */
+ boolean (*check_aperture_space)( struct brw_winsys_screen *iws,
+ struct brw_winsys_buffer **buffers,
+ unsigned count );
+
/**
* Map a buffer.
*/
memcpy(&c->key, key, sizeof(*key));
c->fp = fp;
- c->env_param = brw->intel.ctx.FragmentProgram.Parameters;
+ c->env_param = NULL; /*brw->intel.ctx.FragmentProgram.Parameters;*/
brw_init_compile(brw, &c->func);
GLuint insn:24;
};
-struct brw_wm_constref {
+struct brw_wm_imm_ref {
const struct brw_wm_ref *ref;
- GLfloat constval;
+ GLfloat imm1f;
};
struct brw_wm_instruction instruction[BRW_WM_MAX_INSN];
GLuint nr_insns;
- struct brw_wm_constref constref[BRW_WM_MAX_CONST];
- GLuint nr_constrefs;
+ struct brw_wm_imm_ref imm_ref[BRW_WM_MAX_CONST];
+ GLuint nr_imm_refs;
struct brw_wm_grf pass2_grf[BRW_WM_MAX_GRF/2];
const struct prog_instruction *inst,
GLuint component);
-/**
- * Determine if the given fragment program uses GLSL features such
- * as flow conditionals, loops, subroutines.
- * Some GLSL shaders may use these features, others might not.
- */
-GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp)
-{
- int i;
-
- for (i = 0; i < fp->Base.NumInstructions; i++) {
- const struct prog_instruction *inst = &fp->Base.Instructions[i];
- switch (inst->Opcode) {
- case OPCODE_ARL:
- case OPCODE_IF:
- case OPCODE_ENDIF:
- case OPCODE_CAL:
- case OPCODE_BRK:
- case OPCODE_RET:
- case OPCODE_BGNLOOP:
- return GL_TRUE;
- default:
- break;
- }
- }
- return GL_FALSE;
-}
-
-
static void
reclaim_temps(struct brw_wm_compile *c);
}
-/** Return a ref to a constant/literal value */
-static const struct brw_wm_ref *get_const_ref( struct brw_wm_compile *c,
- const GLfloat *constval )
+/** Return a ref to an immediate value */
+static const struct brw_wm_ref *get_imm_ref( struct brw_wm_compile *c,
+ const GLfloat *imm1f )
{
GLuint i;
/* Search for an existing const value matching the request:
*/
- for (i = 0; i < c->nr_constrefs; i++) {
- if (c->constref[i].constval == *constval)
- return c->constref[i].ref;
+ for (i = 0; i < c->nr_imm_refs; i++) {
+ if (c->imm_ref[i].imm_val == *imm1f)
+ return c->imm_ref[i].ref;
}
/* Else try to add a new one:
*/
- if (c->nr_constrefs < BRW_WM_MAX_CONST) {
- GLuint i = c->nr_constrefs++;
+ if (c->nr_imm_refs < BRW_WM_MAX_IMM) {
+ GLuint i = c->nr_imm_refs++;
- /* A constant is a special type of parameter:
+ /* An immediate is a special type of parameter:
*/
- c->constref[i].constval = *constval;
- c->constref[i].ref = get_param_ref(c, constval);
+ c->imm_ref[i].imm_val = *imm_val;
+ c->imm_ref[i].ref = get_param_ref(c, imm_val);
- return c->constref[i].ref;
+ return c->imm_ref[i].ref;
}
else {
- _mesa_printf("%s: out of constrefs\n", __FUNCTION__);
+ _mesa_printf("%s: out of imm_refs\n", __FUNCTION__);
c->prog_data.error = 1;
return NULL;
}
case PROGRAM_CONSTANT:
/* These are invarient:
*/
- ref = get_const_ref(c, &plist->ParameterValues[idx][component]);
+ ref = get_imm_ref(c, &plist->ParameterValues[idx][component]);
break;
case PROGRAM_STATE_VAR:
static const GLfloat const_one = 1.0;
if (component == SWIZZLE_ZERO)
- src_ref = get_const_ref(c, &const_zero);
+ src_ref = get_imm_ref(c, &const_zero);
else if (component == SWIZZLE_ONE)
- src_ref = get_const_ref(c, &const_one);
+ src_ref = get_imm_ref(c, &const_one);
else
src_ref = pass0_get_reg(c, src.File, src.Index, component);
/* Gallium probably doesn't want this in some cases. */
if (!index_bounds_valid)
- vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+ if (!vbo_all_varyings_in_vbos(arrays))
+ vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
/* sanity check for pointer arithmetic below */
assert(sizeof(arrays[0]->Ptr[0]) == 1);