summaryrefslogtreecommitdiff
path: root/src/mesa/state_tracker
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r--src/mesa/state_tracker/st_atom.c46
-rw-r--r--src/mesa/state_tracker/st_atom_constbuf.c64
-rw-r--r--src/mesa/state_tracker/st_atom_framebuffer.c17
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c9
-rw-r--r--src/mesa/state_tracker/st_atom_rasterizer.c20
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c57
-rw-r--r--src/mesa/state_tracker/st_cb_accum.c271
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c70
-rw-r--r--src/mesa/state_tracker/st_cb_bufferobjects.c90
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c27
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c112
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.c295
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.h16
-rw-r--r--src/mesa/state_tracker/st_cb_flush.c13
-rw-r--r--src/mesa/state_tracker/st_cb_rasterpos.c3
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c37
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c604
-rw-r--r--src/mesa/state_tracker/st_context.c32
-rw-r--r--src/mesa/state_tracker/st_context.h10
-rw-r--r--src/mesa/state_tracker/st_draw.c13
-rw-r--r--src/mesa/state_tracker/st_draw.h3
-rw-r--r--src/mesa/state_tracker/st_draw_feedback.c24
-rw-r--r--src/mesa/state_tracker/st_extensions.c4
-rw-r--r--src/mesa/state_tracker/st_format.c34
-rw-r--r--src/mesa/state_tracker/st_format.h8
-rw-r--r--src/mesa/state_tracker/st_framebuffer.c142
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c30
-rw-r--r--src/mesa/state_tracker/st_inlines.h154
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c20
-rw-r--r--src/mesa/state_tracker/st_program.c59
-rw-r--r--src/mesa/state_tracker/st_public.h12
-rw-r--r--src/mesa/state_tracker/st_texture.c45
-rw-r--r--src/mesa/state_tracker/st_texture.h10
33 files changed, 1621 insertions, 730 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c
index f79092291b..ca15ce1b47 100644
--- a/src/mesa/state_tracker/st_atom.c
+++ b/src/mesa/state_tracker/st_atom.c
@@ -37,11 +37,8 @@
-/* This is used to initialize st->atoms[]. We could use this list
- * directly except for a single atom, st_update_constants, which has a
- * .dirty value which changes according to the parameters of the
- * current fragment and vertex programs, and so cannot be a static
- * value.
+/**
+ * This is used to initialize st->atoms[].
*/
static const struct st_tracked_state *atoms[] =
{
@@ -67,34 +64,13 @@ static const struct st_tracked_state *atoms[] =
void st_init_atoms( struct st_context *st )
{
- GLuint i;
-
- st->atoms = _mesa_malloc(sizeof(atoms));
- st->nr_atoms = sizeof(atoms)/sizeof(*atoms);
- memcpy(st->atoms, atoms, sizeof(atoms));
-
- /* Patch in a pointer to the dynamic state atom:
- */
- for (i = 0; i < st->nr_atoms; i++) {
- if (st->atoms[i] == &st_update_vs_constants) {
- st->atoms[i] = &st->constants.tracked_state[PIPE_SHADER_VERTEX];
- st->atoms[i][0] = st_update_vs_constants;
- }
-
- if (st->atoms[i] == &st_update_fs_constants) {
- st->atoms[i] = &st->constants.tracked_state[PIPE_SHADER_FRAGMENT];
- st->atoms[i][0] = st_update_fs_constants;
- }
- }
+ /* no-op */
}
void st_destroy_atoms( struct st_context *st )
{
- if (st->atoms) {
- _mesa_free(st->atoms);
- st->atoms = NULL;
- }
+ /* no-op */
}
@@ -172,8 +148,8 @@ void st_validate_state( struct st_context *st )
memset(&examined, 0, sizeof(examined));
prev = *state;
- for (i = 0; i < st->nr_atoms; i++) {
- const struct st_tracked_state *atom = st->atoms[i];
+ for (i = 0; i < Elements(atoms); i++) {
+ const struct st_tracked_state *atom = atoms[i];
struct st_state_flags generated;
// _mesa_printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st);
@@ -185,7 +161,7 @@ void st_validate_state( struct st_context *st )
}
if (check_state(state, &atom->dirty)) {
- st->atoms[i]->update( st );
+ atoms[i]->update( st );
// _mesa_printf("after: %x\n", atom->dirty.mesa);
}
@@ -203,11 +179,9 @@ void st_validate_state( struct st_context *st )
}
else {
- const GLuint nr = st->nr_atoms;
-
- for (i = 0; i < nr; i++) {
- if (check_state(state, &st->atoms[i]->dirty))
- st->atoms[i]->update( st );
+ for (i = 0; i < Elements(atoms); i++) {
+ if (check_state(state, &atoms[i]->dirty))
+ atoms[i]->update( st );
}
}
diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
index fd81ac36d2..5d4d8eee02 100644
--- a/src/mesa/state_tracker/st_atom_constbuf.c
+++ b/src/mesa/state_tracker/st_atom_constbuf.c
@@ -24,11 +24,12 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- * Brian Paul
- */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
#include "main/imports.h"
#include "shader/prog_parameter.h"
@@ -42,63 +43,61 @@
#include "st_atom.h"
#include "st_atom_constbuf.h"
#include "st_program.h"
+#include "st_inlines.h"
/**
* Pass the given program parameters to the graphics pipe as a
* constant buffer.
- * \param id either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT
+ * \param shader_type either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT
*/
void st_upload_constants( struct st_context *st,
struct gl_program_parameter_list *params,
- unsigned id)
+ unsigned shader_type)
{
struct pipe_context *pipe = st->pipe;
- struct pipe_constant_buffer *cbuf = &st->state.constants[id];
+ struct pipe_constant_buffer *cbuf = &st->state.constants[shader_type];
- assert(id == PIPE_SHADER_VERTEX || id == PIPE_SHADER_FRAGMENT);
+ assert(shader_type == PIPE_SHADER_VERTEX ||
+ shader_type == PIPE_SHADER_FRAGMENT);
/* update constants */
if (params && params->NumParameters) {
const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4;
- /* Update our own dependency flags. This works because this
- * function will also be called whenever the program changes.
- */
- st->constants.tracked_state[id].dirty.mesa =
- (params->StateFlags | _NEW_PROGRAM);
-
_mesa_load_state_parameters(st->ctx, params);
/* We always need to get a new buffer, to keep the drivers simple and
* avoid gratuitous rendering synchronization.
*/
pipe_buffer_reference(&cbuf->buffer, NULL );
- cbuf->buffer = pipe_buffer_create(pipe->screen, 16, PIPE_BUFFER_USAGE_CONSTANT,
+ cbuf->buffer = pipe_buffer_create(pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
paramBytes );
- if (0)
- {
- printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n",
- __FUNCTION__, id, params->NumParameters, params->StateFlags);
+ if (0) {
+ debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n",
+ __FUNCTION__, shader_type, params->NumParameters,
+ params->StateFlags);
_mesa_print_parameter_list(params);
}
/* load Mesa constants into the constant buffer */
if (cbuf->buffer)
- pipe_buffer_write(pipe->screen, cbuf->buffer,
- 0, paramBytes,
- params->ParameterValues);
+ st_no_flush_pipe_buffer_write(st, cbuf->buffer,
+ 0, paramBytes,
+ params->ParameterValues);
- st->pipe->set_constant_buffer(st->pipe, id, 0, cbuf);
+ st->pipe->set_constant_buffer(st->pipe, shader_type, 0, cbuf);
}
else {
- st->constants.tracked_state[id].dirty.mesa = 0;
- // st->pipe->set_constant_buffer(st->pipe, id, 0, NULL);
+ st->constants.tracked_state[shader_type].dirty.mesa = 0x0;
}
}
-/* Vertex shader:
+
+/**
+ * Vertex shader:
*/
static void update_vs_constants(struct st_context *st )
{
@@ -108,16 +107,20 @@ static void update_vs_constants(struct st_context *st )
st_upload_constants( st, params, PIPE_SHADER_VERTEX );
}
+
const struct st_tracked_state st_update_vs_constants = {
"st_update_vs_constants", /* name */
{ /* dirty */
- 0, /* set dynamically above */ /* mesa */
+ (_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */
ST_NEW_VERTEX_PROGRAM, /* st */
},
update_vs_constants /* update */
};
-/* Fragment shader:
+
+
+/**
+ * Fragment shader:
*/
static void update_fs_constants(struct st_context *st )
{
@@ -127,10 +130,11 @@ static void update_fs_constants(struct st_context *st )
st_upload_constants( st, params, PIPE_SHADER_FRAGMENT );
}
+
const struct st_tracked_state st_update_fs_constants = {
"st_update_fs_constants", /* name */
{ /* dirty */
- 0, /* set dynamically above */ /* mesa */
+ (_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */
ST_NEW_FRAGMENT_PROGRAM, /* st */
},
update_fs_constants /* update */
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
index df0f0931ea..4d897b677e 100644
--- a/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -98,8 +98,6 @@ update_framebuffer_state( struct st_context *st )
struct st_renderbuffer *strb;
GLuint i;
- memset(framebuffer, 0, sizeof(*framebuffer));
-
framebuffer->width = fb->Width;
framebuffer->height = fb->Height;
@@ -120,12 +118,20 @@ update_framebuffer_state( struct st_context *st )
}
if (strb->surface) {
- framebuffer->cbufs[framebuffer->nr_cbufs] = strb->surface;
+ pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs],
+ strb->surface);
framebuffer->nr_cbufs++;
}
+ strb->defined = GL_TRUE; /* we'll be drawing something */
}
}
+ for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&framebuffer->cbufs[i], NULL);
+ }
+ /*
+ * Depth/Stencil renderbuffer/surface.
+ */
strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
if (strb) {
strb = st_renderbuffer(strb->Base.Wrapped);
@@ -133,15 +139,14 @@ update_framebuffer_state( struct st_context *st )
/* rendering to a GL texture, may have to update surface */
update_renderbuffer_surface(st, strb);
}
-
- framebuffer->zsbuf = strb->surface;
+ pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
}
else {
strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
if (strb) {
strb = st_renderbuffer(strb->Base.Wrapped);
assert(strb->surface);
- framebuffer->zsbuf = strb->surface;
+ pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
}
}
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index 8d0029dde5..eff3666ca8 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -45,6 +45,7 @@
#include "st_format.h"
#include "st_program.h"
#include "st_texture.h"
+#include "st_inlines.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
@@ -125,8 +126,7 @@ create_color_map_texture(GLcontext *ctx)
/* create texture for color map/table */
pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0,
- texSize, texSize, 1, 0,
- PIPE_TEXTURE_USAGE_SAMPLER);
+ texSize, texSize, 1, PIPE_TEXTURE_USAGE_SAMPLER);
return pt;
}
@@ -148,8 +148,9 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt)
uint *dest;
uint i, j;
- transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
- 0, 0, texSize, texSize);
+ transfer = st_cond_flush_get_tex_transfer(st_context(ctx),
+ pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
+ 0, 0, texSize, texSize);
dest = (uint *) screen->transfer_map(screen, transfer);
/* Pack four 1D maps into a 2D texture:
diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c
index 61687fbc3e..5c7206409c 100644
--- a/src/mesa/state_tracker/st_atom_rasterizer.c
+++ b/src/mesa/state_tracker/st_atom_rasterizer.c
@@ -180,22 +180,7 @@ static void update_raster_state( struct st_context *st )
if (ctx->Polygon.StippleFlag)
raster->poly_stipple_enable = 1;
-
-
- /* _NEW_BUFFERS, _NEW_POLYGON
- */
- if (raster->fill_cw != PIPE_POLYGON_MODE_FILL ||
- raster->fill_ccw != PIPE_POLYGON_MODE_FILL)
- {
- GLfloat mrd = (ctx->DrawBuffer ?
- ctx->DrawBuffer->_MRD :
- 1.0f);
-
- raster->offset_units = ctx->Polygon.OffsetFactor * mrd;
- raster->offset_scale = (ctx->Polygon.OffsetUnits * mrd *
- st->polygon_offset_scale);
- }
-
+
/* _NEW_POINT
*/
raster->point_size = ctx->Point.Size;
@@ -207,7 +192,8 @@ static void update_raster_state( struct st_context *st )
raster->point_sprite = ctx->Point.PointSprite;
for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
if (ctx->Point.CoordReplace[i]) {
- if (ctx->Point.SpriteOrigin == GL_UPPER_LEFT)
+ if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^
+ (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM))
raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_UPPER_LEFT;
else
raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_LOWER_LEFT;
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index fc1ff5be04..ee649be885 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -175,11 +175,12 @@ find_translated_vp(struct st_context *st,
/* See if we need to translate vertex program to TGSI form */
if (xvp->serialNo != stvp->serialNo) {
- GLuint outAttr, dummySlot;
+ GLuint outAttr;
const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
GLuint numVpOuts = 0;
GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
- GLint maxGeneric;
+ GLbitfield usedGenerics = 0x0;
+ GLbitfield usedOutputSlots = 0x0;
/* Compute mapping of vertex program outputs to slots, which depends
* on the fragment program's input->slot mapping.
@@ -192,10 +193,12 @@ find_translated_vp(struct st_context *st,
if (outAttr == VERT_RESULT_HPOS) {
/* always put xformed position into slot zero */
- xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
+ GLuint slot = 0;
+ xvp->output_to_slot[VERT_RESULT_HPOS] = slot;
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
xvp->output_to_semantic_index[outAttr] = 0;
numVpOuts++;
+ usedOutputSlots |= (1 << slot);
}
else if (outputsWritten & (1 << outAttr)) {
/* see if the frag prog wants this vert output */
@@ -209,6 +212,12 @@ find_translated_vp(struct st_context *st,
xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
numVpOuts++;
+ usedOutputSlots |= (1 << vpOutSlot);
+ }
+ else {
+#if 0 /*debug*/
+ printf("VP output %d not used by FP\n", outAttr);
+#endif
}
}
else if (outAttr == VERT_RESULT_PSIZ)
@@ -226,45 +235,49 @@ find_translated_vp(struct st_context *st,
/* must do these last */
if (emitPntSize) {
- xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++;
+ GLuint slot = numVpOuts++;
+ xvp->output_to_slot[VERT_RESULT_PSIZ] = slot;
xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
+ usedOutputSlots |= (1 << slot);
}
if (emitBFC0) {
- xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++;
+ GLuint slot = numVpOuts++;
+ xvp->output_to_slot[VERT_RESULT_BFC0] = slot;
xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
+ usedOutputSlots |= (1 << slot);
}
if (emitBFC1) {
- xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++;
- xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
- xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1;
+ GLuint slot = numVpOuts++;
+ xvp->output_to_slot[VERT_RESULT_BFC1] = slot;
+ xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
+ usedOutputSlots |= (1 << slot);
}
- /* Unneeded vertex program outputs will go to this slot.
- * We could use this info to do dead code elimination in the
- * vertex program.
- */
- dummySlot = numVpOuts;
-
- /* find max GENERIC slot index */
- maxGeneric = -1;
+ /* build usedGenerics mask */
+ usedGenerics = 0x0;
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
- maxGeneric = MAX2(maxGeneric,
- xvp->output_to_semantic_index[outAttr]);
+ usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]);
}
}
- /* Map vert program outputs that aren't used to the dummy slot
- * (and an unused generic attribute slot).
+ /* For each vertex program output that doesn't match up to a fragment
+ * program input, map the vertex program output to a free slot and
+ * free generic attribute.
*/
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
if (outputsWritten & (1 << outAttr)) {
if (xvp->output_to_slot[outAttr] == UNUSED) {
- xvp->output_to_slot[outAttr] = dummySlot;
+ GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1;
+ GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1;
+ usedGenerics |= (1 << freeGeneric);
+ usedOutputSlots |= (1 << freeSlot);
+ xvp->output_to_slot[outAttr] = freeSlot;
xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
- xvp->output_to_semantic_index[outAttr] = maxGeneric + 1;
+ xvp->output_to_semantic_index[outAttr] = freeGeneric;
}
}
diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c
index 3f9a825a15..95181578f6 100644
--- a/src/mesa/state_tracker/st_cb_accum.c
+++ b/src/mesa/state_tracker/st_cb_accum.c
@@ -40,16 +40,14 @@
#include "st_draw.h"
#include "st_public.h"
#include "st_format.h"
+#include "st_texture.h"
+#include "st_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "util/u_tile.h"
-#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
- us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
-
-
/**
* For hardware that supports deep color buffers, we could accelerate
* most/all the accum operations with blending/texturing.
@@ -57,73 +55,20 @@
*/
-/**
- * Wrapper for pipe_get_tile_rgba(). Do format/cpp override to make the
- * tile util function think the surface is 16bit/channel, even if it's not.
- * See also: st_renderbuffer_alloc_storage()
- */
-static void
-acc_get_tile_rgba(struct pipe_context *pipe, struct pipe_transfer *acc_pt,
- uint x, uint y, uint w, uint h, float *p)
-{
- const enum pipe_format f = acc_pt->format;
- const struct pipe_format_block b = acc_pt->block;
-
- acc_pt->format = DEFAULT_ACCUM_PIPE_FORMAT;
- acc_pt->block.size = 8;
- acc_pt->block.width = 1;
- acc_pt->block.height = 1;
-
- pipe_get_tile_rgba(acc_pt, x, y, w, h, p);
-
- acc_pt->format = f;
- acc_pt->block = b;
-}
-
-
-/**
- * Wrapper for pipe_put_tile_rgba(). Do format/cpp override to make the
- * tile util function think the surface is 16bit/channel, even if it's not.
- * See also: st_renderbuffer_alloc_storage()
- */
-static void
-acc_put_tile_rgba(struct pipe_context *pipe, struct pipe_transfer *acc_pt,
- uint x, uint y, uint w, uint h, const float *p)
-{
- enum pipe_format f = acc_pt->format;
- const struct pipe_format_block b = acc_pt->block;
-
- acc_pt->format = DEFAULT_ACCUM_PIPE_FORMAT;
- acc_pt->block.size = 8;
- acc_pt->block.width = 1;
- acc_pt->block.height = 1;
-
- pipe_put_tile_rgba(acc_pt, x, y, w, h, p);
-
- acc_pt->format = f;
- acc_pt->block = b;
-}
-
-
-
void
st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
{
struct st_renderbuffer *acc_strb = st_renderbuffer(rb);
- struct pipe_transfer *acc_pt;
- struct pipe_screen *screen = ctx->st->pipe->screen;
const GLint xpos = ctx->DrawBuffer->_Xmin;
const GLint ypos = ctx->DrawBuffer->_Ymin;
const GLint width = ctx->DrawBuffer->_Xmax - xpos;
const GLint height = ctx->DrawBuffer->_Ymax - ypos;
- GLubyte *map;
+ size_t stride = acc_strb->stride;
+ GLubyte *data = acc_strb->data;
- acc_pt = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_WRITE, xpos, ypos,
- width, height);
- map = screen->transfer_map(screen, acc_pt);
-
- /* note acc_strb->format might not equal acc_pt->format */
+ if(!data)
+ return;
+
switch (acc_strb->format) {
case PIPE_FORMAT_R16G16B16A16_SNORM:
{
@@ -133,7 +78,7 @@ st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]);
int i, j;
for (i = 0; i < height; i++) {
- GLshort *dst = (GLshort *) (map + i * acc_pt->stride + xpos * 8);
+ GLshort *dst = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
for (j = 0; j < width; j++) {
dst[0] = r;
dst[1] = g;
@@ -147,9 +92,6 @@ st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
default:
_mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()");
}
-
- screen->transfer_unmap(screen, acc_pt);
- screen->tex_transfer_destroy(acc_pt);
}
@@ -159,25 +101,18 @@ accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias,
GLint xpos, GLint ypos, GLint width, GLint height,
struct st_renderbuffer *acc_strb)
{
- struct pipe_screen *screen = ctx->st->pipe->screen;
- struct pipe_transfer *acc_pt;
- GLubyte *map;
+ size_t stride = acc_strb->stride;
+ GLubyte *data = acc_strb->data;
- acc_pt = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ_WRITE, xpos, ypos,
- width, height);
- map = screen->transfer_map(screen, acc_pt);
-
- /* note acc_strb->format might not equal acc_pt->format */
switch (acc_strb->format) {
case PIPE_FORMAT_R16G16B16A16_SNORM:
{
int i, j;
for (i = 0; i < height; i++) {
- GLshort *acc = (GLshort *) (map + (ypos + i) * acc_pt->stride + xpos * 8);
+ GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
for (j = 0; j < width * 4; j++) {
- float val = SHORT_TO_FLOAT(acc[j]) * scale + bias;
- acc[j] = FLOAT_TO_SHORT(val);
+ float val = SHORT_TO_FLOAT(*acc) * scale + bias;
+ *acc++ = FLOAT_TO_SHORT(val);
}
}
}
@@ -185,86 +120,95 @@ accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias,
default:
_mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
}
-
- screen->transfer_unmap(screen, acc_pt);
- screen->tex_transfer_destroy(acc_pt);
}
static void
-accum_accum(struct pipe_context *pipe, GLfloat value,
+accum_accum(struct st_context *st, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height,
struct st_renderbuffer *acc_strb,
struct st_renderbuffer *color_strb)
{
+ struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
- struct pipe_transfer *acc_trans, *color_trans;
- GLfloat *colorBuf, *accBuf;
- GLint i;
-
- acc_trans = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ, xpos, ypos,
- width, height);
+ struct pipe_transfer *color_trans;
+ size_t stride = acc_strb->stride;
+ GLubyte *data = acc_strb->data;
+ GLfloat *buf;
- color_trans = screen->get_tex_transfer(screen, color_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ, xpos, ypos,
- width, height);
+ color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, xpos, ypos,
+ width, height);
- colorBuf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
- accBuf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
- pipe_get_tile_rgba(color_trans, 0, 0, width, height, colorBuf);
- acc_get_tile_rgba(pipe, acc_trans, 0, 0, width, height, accBuf);
+ pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf);
- for (i = 0; i < 4 * width * height; i++) {
- accBuf[i] = accBuf[i] + colorBuf[i] * value;
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ const GLfloat *color = buf;
+ int i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
+ for (j = 0; j < width * 4; j++) {
+ float val = *color++ * value;
+ *acc++ += FLOAT_TO_SHORT(val);
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
}
- screen->tex_transfer_destroy(acc_trans);
- acc_trans = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_WRITE, xpos, ypos,
- width, height);
-
- acc_put_tile_rgba(pipe, acc_trans, 0, 0, width, height, accBuf);
-
- _mesa_free(colorBuf);
- _mesa_free(accBuf);
- screen->tex_transfer_destroy(acc_trans);
+ _mesa_free(buf);
screen->tex_transfer_destroy(color_trans);
}
static void
-accum_load(struct pipe_context *pipe, GLfloat value,
+accum_load(struct st_context *st, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height,
struct st_renderbuffer *acc_strb,
struct st_renderbuffer *color_strb)
{
+ struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
- struct pipe_transfer *acc_trans, *color_trans;
+ struct pipe_transfer *color_trans;
+ size_t stride = acc_strb->stride;
+ GLubyte *data = acc_strb->data;
GLfloat *buf;
- GLint i;
- acc_trans = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_WRITE, xpos, ypos,
- width, height);
-
- color_trans = screen->get_tex_transfer(screen, color_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ, xpos, ypos,
- width, height);
+ color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, xpos, ypos,
+ width, height);
buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf);
- for (i = 0; i < 4 * width * height; i++) {
- buf[i] = buf[i] * value;
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ const GLfloat *color = buf;
+ int i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
+ for (j = 0; j < width * 4; j++) {
+ float val = *color++ * value;
+ *acc++ = FLOAT_TO_SHORT(val);
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
}
- acc_put_tile_rgba(pipe, acc_trans, 0, 0, width, height, buf);
-
_mesa_free(buf);
- screen->tex_transfer_destroy(acc_trans);
screen->tex_transfer_destroy(color_trans);
}
@@ -278,45 +222,58 @@ accum_return(GLcontext *ctx, GLfloat value,
struct pipe_context *pipe = ctx->st->pipe;
struct pipe_screen *screen = pipe->screen;
const GLubyte *colormask = ctx->Color.ColorMask;
- struct pipe_transfer *acc_trans, *color_trans;
- GLfloat *abuf, *cbuf = NULL;
- GLint i, ch;
-
- abuf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
-
- acc_trans = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ, xpos, ypos,
- width, height);
+ enum pipe_transfer_usage usage;
+ struct pipe_transfer *color_trans;
+ size_t stride = acc_strb->stride;
+ const GLubyte *data = acc_strb->data;
+ GLfloat *buf;
- color_trans = screen->get_tex_transfer(screen, color_strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ_WRITE, xpos, ypos,
- width, height);
+ buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
- acc_get_tile_rgba(pipe, acc_trans, 0, 0, width, height, abuf);
+ if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3])
+ usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ usage = PIPE_TRANSFER_WRITE;
+
+ color_trans = st_cond_flush_get_tex_transfer(st_context(ctx),
+ color_strb->texture, 0, 0, 0,
+ usage,
+ xpos, ypos,
+ width, height);
- if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) {
- cbuf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
- pipe_get_tile_rgba(color_trans, 0, 0, width, height, cbuf);
- }
+ if (usage != PIPE_TRANSFER_WRITE)
+ pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf);
- for (i = 0; i < width * height; i++) {
- for (ch = 0; ch < 4; ch++) {
- if (colormask[ch]) {
- GLfloat val = abuf[i * 4 + ch] * value;
- abuf[i * 4 + ch] = CLAMP(val, 0.0f, 1.0f);
- }
- else {
- abuf[i * 4 + ch] = cbuf[i * 4 + ch];
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ GLfloat *color = buf;
+ int i, j, ch;
+ for (i = 0; i < height; i++) {
+ const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8);
+ for (j = 0; j < width; j++) {
+ for (ch = 0; ch < 4; ch++) {
+ if (colormask[ch]) {
+ GLfloat val = SHORT_TO_FLOAT(*acc * value);
+ *color = CLAMP(val, 0.0f, 1.0f);
+ }
+ else {
+ /* No change */
+ }
+ ++acc;
+ ++color;
+ }
+ }
}
}
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
}
- pipe_put_tile_rgba(color_trans, 0, 0, width, height, abuf);
+ pipe_put_tile_rgba(color_trans, 0, 0, width, height, buf);
- _mesa_free(abuf);
- if (cbuf)
- _mesa_free(cbuf);
- screen->tex_transfer_destroy(acc_trans);
+ _mesa_free(buf);
screen->tex_transfer_destroy(color_trans);
}
@@ -325,7 +282,6 @@ static void
st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
{
struct st_context *st = ctx->st;
- struct pipe_context *pipe = st->pipe;
struct st_renderbuffer *acc_strb
= st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
struct st_renderbuffer *color_strb
@@ -336,6 +292,9 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
const GLint width = ctx->DrawBuffer->_Xmax - xpos;
const GLint height = ctx->DrawBuffer->_Ymax - ypos;
+ if(!acc_strb->data)
+ return;
+
/* make sure color bufs aren't cached */
st_flush( st, PIPE_FLUSH_RENDER_CACHE, NULL );
@@ -352,11 +311,11 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
break;
case GL_ACCUM:
if (value != 0.0F) {
- accum_accum(pipe, value, xpos, ypos, width, height, acc_strb, color_strb);
+ accum_accum(st, value, xpos, ypos, width, height, acc_strb, color_strb);
}
break;
case GL_LOAD:
- accum_load(pipe, value, xpos, ypos, width, height, acc_strb, color_strb);
+ accum_load(st, value, xpos, ypos, width, height, acc_strb, color_strb);
break;
case GL_RETURN:
accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb);
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 2d547dd072..8709633557 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -47,6 +47,8 @@
#include "st_cb_program.h"
#include "st_mesa_to_tgsi.h"
#include "st_texture.h"
+#include "st_inlines.h"
+
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
@@ -147,7 +149,7 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX;
p->Instructions[ic].SrcReg[0].Index = 0;
- p->Instructions[ic].SrcReg[0].NegateBase = NEGATE_XYZW;
+ p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW;
ic++;
/* END; */
@@ -330,15 +332,16 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
* Create texture to hold bitmap pattern.
*/
pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, ctx->st->bitmap.tex_format,
- 0, width, height, 1, 0,
+ 0, width, height, 1,
PIPE_TEXTURE_USAGE_SAMPLER);
if (!pt) {
_mesa_unmap_bitmap_pbo(ctx, unpack);
return NULL;
}
- transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
- 0, 0, width, height);
+ transfer = st_no_flush_get_tex_transfer(st_context(ctx), pt, 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0, width, height);
dest = screen->transfer_map(screen, transfer);
@@ -425,11 +428,11 @@ setup_bitmap_vertex_data(struct st_context *st,
}
/* put vertex data into vbuf */
- pipe_buffer_write(pipe->screen,
- st->bitmap.vbuf,
- st->bitmap.vbuf_slot * sizeof st->bitmap.vertices,
- sizeof st->bitmap.vertices,
- st->bitmap.vertices);
+ st_no_flush_pipe_buffer_write(st,
+ st->bitmap.vbuf,
+ st->bitmap.vbuf_slot * sizeof st->bitmap.vertices,
+ sizeof st->bitmap.vertices,
+ st->bitmap.vertices);
return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
}
@@ -570,8 +573,10 @@ reset_cache(struct st_context *st)
cache->ymin = 1000000;
cache->ymax = -1000000;
- if (cache->trans)
+ if (cache->trans) {
screen->tex_transfer_destroy(cache->trans);
+ cache->trans = NULL;
+ }
assert(!cache->texture);
@@ -579,16 +584,27 @@ reset_cache(struct st_context *st)
cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
st->bitmap.tex_format, 0,
BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
- 1, 0,
- PIPE_TEXTURE_USAGE_SAMPLER);
+ 1, PIPE_TEXTURE_USAGE_SAMPLER);
+
+}
+
+static void
+create_cache_trans(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ if (cache->trans)
+ return;
/* Map the texture transfer.
* Subsequent glBitmap calls will write into the texture image.
*/
- cache->trans = screen->get_tex_transfer(screen, cache->texture, 0, 0, 0,
- PIPE_TRANSFER_WRITE, 0, 0,
- BITMAP_CACHE_WIDTH,
- BITMAP_CACHE_HEIGHT);
+ cache->trans = st_no_flush_get_tex_transfer(st, cache->texture, 0, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ BITMAP_CACHE_WIDTH,
+ BITMAP_CACHE_HEIGHT);
cache->buffer = screen->transfer_map(screen, cache->trans);
/* init image to all 0xff */
@@ -620,11 +636,13 @@ st_flush_bitmap_cache(struct st_context *st)
/* The texture transfer has been mapped until now.
* So unmap and release the texture transfer before drawing.
*/
- screen->transfer_unmap(screen, cache->trans);
- cache->buffer = NULL;
+ if (cache->trans) {
+ screen->transfer_unmap(screen, cache->trans);
+ cache->buffer = NULL;
- screen->tex_transfer_destroy(cache->trans);
- cache->trans = NULL;
+ screen->tex_transfer_destroy(cache->trans);
+ cache->trans = NULL;
+ }
draw_bitmap_quad(st->ctx,
cache->xpos,
@@ -709,6 +727,9 @@ accum_bitmap(struct st_context *st,
if (y + height > cache->ymax)
cache->ymax = y + height;
+ /* create the transfer if needed */
+ create_cache_trans(st);
+
unpack_bitmap(st, px, py, width, height, unpack, bitmap,
cache->buffer, BITMAP_CACHE_WIDTH);
@@ -821,8 +842,7 @@ st_destroy_bitmap(struct st_context *st)
struct pipe_screen *screen = pipe->screen;
struct bitmap_cache *cache = st->bitmap.cache;
- screen->transfer_unmap(screen, cache->trans);
- screen->tex_transfer_destroy(cache->trans);
+
if (st->bitmap.vs) {
cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
@@ -834,7 +854,11 @@ st_destroy_bitmap(struct st_context *st)
st->bitmap.vbuf = NULL;
}
- if (st->bitmap.cache) {
+ if (cache) {
+ if (cache->trans) {
+ screen->transfer_unmap(screen, cache->trans);
+ screen->tex_transfer_destroy(cache->trans);
+ }
pipe_texture_reference(&st->bitmap.cache->texture, NULL);
_mesa_free(st->bitmap.cache);
st->bitmap.cache = NULL;
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c
index 3651e4ae7d..7021d73208 100644
--- a/src/mesa/state_tracker/st_cb_bufferobjects.c
+++ b/src/mesa/state_tracker/st_cb_bufferobjects.c
@@ -26,10 +26,17 @@
**************************************************************************/
+/**
+ * Functions for pixel buffer objects and vertex/element buffer objects.
+ */
+
+
#include "main/imports.h"
#include "main/mtypes.h"
+#include "main/arrayobj.h"
#include "main/bufferobj.h"
+#include "st_inlines.h"
#include "st_context.h"
#include "st_cb_bufferobjects.h"
@@ -38,14 +45,6 @@
#include "pipe/p_inlines.h"
-
-/* Pixel buffers and Vertex/index buffers are handled through these
- * mesa callbacks. Framebuffer/Renderbuffer objects are
- * created/managed elsewhere.
- */
-
-
-
/**
* There is some duplication between mesa's bufferobjects and our
* bufmgr buffers. Both have an integer handle and a hashtable to
@@ -97,13 +96,13 @@ st_bufferobj_subdata(GLcontext *ctx,
GLsizeiptrARB size,
const GLvoid * data, struct gl_buffer_object *obj)
{
- struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_buffer_object *st_obj = st_buffer_object(obj);
if (offset >= st_obj->size || size > (st_obj->size - offset))
return;
- pipe_buffer_write(pipe->screen, st_obj->buffer, offset, size, data);
+ st_cond_flush_pipe_buffer_write(st_context(ctx), st_obj->buffer,
+ offset, size, data);
}
@@ -117,13 +116,13 @@ st_bufferobj_get_subdata(GLcontext *ctx,
GLsizeiptrARB size,
GLvoid * data, struct gl_buffer_object *obj)
{
- struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_buffer_object *st_obj = st_buffer_object(obj);
if (offset >= st_obj->size || size > (st_obj->size - offset))
return;
- pipe_buffer_read(pipe->screen, st_obj->buffer, offset, size, data);
+ st_cond_flush_pipe_buffer_read(st_context(ctx), st_obj->buffer,
+ offset, size, data);
}
@@ -168,10 +167,16 @@ st_bufferobj_data(GLcontext *ctx,
st_obj->buffer = pipe_buffer_create( pipe->screen, 32, buffer_usage, size );
+ if (!st_obj->buffer) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB");
+ return;
+ }
+
st_obj->size = size;
if (data)
- st_bufferobj_subdata(ctx, target, 0, size, data, obj);
+ st_no_flush_pipe_buffer_write(st_context(ctx), st_obj->buffer, 0,
+ size, data);
}
@@ -182,9 +187,8 @@ static void *
st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access,
struct gl_buffer_object *obj)
{
- struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_buffer_object *st_obj = st_buffer_object(obj);
- GLuint flags;
+ uint flags;
switch (access) {
case GL_WRITE_ONLY:
@@ -200,8 +204,10 @@ st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access,
break;
}
- obj->Pointer = pipe_buffer_map(pipe->screen, st_obj->buffer, flags);
- if(obj->Pointer) {
+ obj->Pointer = st_cond_flush_pipe_buffer_map(st_context(ctx),
+ st_obj->buffer,
+ flags);
+ if (obj->Pointer) {
obj->Offset = 0;
obj->Length = obj->Size;
}
@@ -209,7 +215,6 @@ st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access,
}
-
/**
* Called via glMapBufferRange().
*/
@@ -220,7 +225,7 @@ st_bufferobj_map_range(GLcontext *ctx, GLenum target,
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_buffer_object *st_obj = st_buffer_object(obj);
- GLuint flags = 0;
+ uint flags = 0x0;
char *map;
if (access & GL_MAP_WRITE_BIT)
@@ -242,8 +247,8 @@ st_bufferobj_map_range(GLcontext *ctx, GLenum target,
map = obj->Pointer = pipe_buffer_map_range(pipe->screen, st_obj->buffer, offset, length, flags);
if(obj->Pointer) {
- obj->Offset = 0;
- obj->Length = obj->Size;
+ obj->Offset = offset;
+ obj->Length = length;
map += offset;
}
@@ -262,7 +267,6 @@ st_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target,
/* Subrange is relative to mapped range */
assert(offset >= 0);
assert(length >= 0);
- assert(offset < obj->Length);
assert(offset + length <= obj->Length);
pipe_buffer_flush_mapped_range(pipe->screen, st_obj->buffer,
@@ -287,6 +291,43 @@ st_bufferobj_unmap(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
}
+/**
+ * Called via glCopyBufferSubData().
+ */
+static void
+st_copy_buffer_subdata(GLcontext *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *srcObj = st_buffer_object(src);
+ struct st_buffer_object *dstObj = st_buffer_object(dst);
+ ubyte *srcPtr, *dstPtr;
+
+ /* buffer should not already be mapped */
+ assert(!src->Pointer);
+ assert(!dst->Pointer);
+
+ srcPtr = (ubyte *) pipe_buffer_map_range(pipe->screen,
+ srcObj->buffer,
+ readOffset, size,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ dstPtr = (ubyte *) pipe_buffer_map_range(pipe->screen,
+ dstObj->buffer,
+ writeOffset, size,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ if (srcPtr && dstPtr)
+ _mesa_memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
+
+ pipe_buffer_unmap(pipe->screen, srcObj->buffer);
+ pipe_buffer_unmap(pipe->screen, dstObj->buffer);
+}
+
+
void
st_init_bufferobject_functions(struct dd_function_table *functions)
{
@@ -299,4 +340,9 @@ st_init_bufferobject_functions(struct dd_function_table *functions)
functions->MapBufferRange = st_bufferobj_map_range;
functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range;
functions->UnmapBuffer = st_bufferobj_unmap;
+ functions->CopyBufferSubData = st_copy_buffer_subdata;
+
+ /* For GL_APPLE_vertex_array_object */
+ functions->NewArrayObject = _mesa_new_array_object;
+ functions->DeleteArrayObject = _mesa_delete_array_object;
}
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index 5bdc6a1330..668acbccb8 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -45,6 +45,7 @@
#include "st_program.h"
#include "st_public.h"
#include "st_mesa_to_tgsi.h"
+#include "st_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
@@ -102,20 +103,6 @@ st_destroy_clear(struct st_context *st)
}
-static GLboolean
-is_depth_stencil_format(enum pipe_format pipeFormat)
-{
- switch (pipeFormat) {
- case PIPE_FORMAT_S8Z24_UNORM:
- case PIPE_FORMAT_Z24S8_UNORM:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-
/**
* Draw a screen-aligned quadrilateral.
* Coords are window coords with y=0=bottom. These will be passed
@@ -166,10 +153,10 @@ draw_quad(GLcontext *ctx,
}
/* put vertex data into vbuf */
- pipe_buffer_write(pipe->screen, st->clear.vbuf,
- st->clear.vbuf_slot * sizeof(st->clear.vertices),
- sizeof(st->clear.vertices),
- st->clear.vertices);
+ st_no_flush_pipe_buffer_write(st, st->clear.vbuf,
+ st->clear.vbuf_slot * sizeof(st->clear.vertices),
+ sizeof(st->clear.vertices),
+ st->clear.vertices);
/* draw */
util_draw_vertex_buffer(pipe,
@@ -330,7 +317,7 @@ static INLINE GLboolean
check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
{
const struct st_renderbuffer *strb = st_renderbuffer(rb);
- const GLboolean isDS = is_depth_stencil_format(strb->surface->format);
+ const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
if (ctx->Scissor.Enabled)
return TRUE;
@@ -350,7 +337,7 @@ static INLINE GLboolean
check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
{
const struct st_renderbuffer *strb = st_renderbuffer(rb);
- const GLboolean isDS = is_depth_stencil_format(strb->surface->format);
+ const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
const GLuint stencilMax = (1 << rb->StencilBits) - 1;
const GLboolean maskStencil
= (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index ebb1d1142a..2027b713ce 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -53,6 +53,8 @@
#include "st_format.h"
#include "st_mesa_to_tgsi.h"
#include "st_texture.h"
+#include "st_inlines.h"
+
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
@@ -144,6 +146,8 @@ combined_drawpix_fragment_program(GLcontext *ctx)
st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
st->pixel_xfer.user_prog_sn = st->fp->serialNo;
st->pixel_xfer.combined_prog_sn = stfp->serialNo;
+ /* can't reference new program directly, already have a reference on it */
+ st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
st->pixel_xfer.combined_prog = stfp;
}
@@ -351,8 +355,7 @@ make_texture(struct st_context *st,
if (!pixels)
return NULL;
- pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height,
- 1, 0,
+ pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, 1,
PIPE_TEXTURE_USAGE_SAMPLER);
if (!pt) {
_mesa_unmap_drawpix_pbo(ctx, unpack);
@@ -369,9 +372,9 @@ make_texture(struct st_context *st,
/* we'll do pixel transfer in a fragment shader */
ctx->_ImageTransferState = 0x0;
- transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0,
- PIPE_TRANSFER_WRITE, 0, 0,
- width, height);
+ transfer = st_no_flush_get_tex_transfer(st, pt, 0, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ width, height);
/* map texture transfer */
dest = screen->transfer_map(screen, transfer);
@@ -491,7 +494,7 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
/* allocate/load buffer object with vertex data */
buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
sizeof(verts));
- pipe_buffer_write(pipe->screen, buf, 0, sizeof(verts), verts);
+ st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts);
util_draw_vertex_buffer(pipe, buf, 0,
PIPE_PRIM_QUADS,
@@ -627,13 +630,12 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
struct st_renderbuffer *strb;
+ enum pipe_transfer_usage usage;
struct pipe_transfer *pt;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
GLint skipPixels;
ubyte *stmap;
- pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
-
strb = st_renderbuffer(ctx->DrawBuffer->
Attachment[BUFFER_STENCIL].Renderbuffer);
@@ -641,9 +643,15 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
y = ctx->DrawBuffer->Height - y - height;
}
- pt = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0,
- PIPE_TRANSFER_WRITE, x, y,
- width, height);
+ if(format != GL_DEPTH_STENCIL &&
+ pf_get_component_bits( strb->format, PIPE_FORMAT_COMP_Z ) != 0)
+ usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ usage = PIPE_TRANSFER_WRITE;
+
+ pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0,
+ usage, x, y,
+ width, height);
stmap = screen->transfer_map(screen, pt);
@@ -693,6 +701,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
case PIPE_FORMAT_S8_UNORM:
{
ubyte *dest = stmap + spanY * pt->stride + spanX;
+ assert(usage == PIPE_TRANSFER_WRITE);
memcpy(dest, sValues, spanWidth);
}
break;
@@ -700,6 +709,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
if (format == GL_DEPTH_STENCIL) {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
+ assert(usage == PIPE_TRANSFER_WRITE);
for (k = 0; k < spanWidth; k++) {
dest[k] = zValues[k] | (sValues[k] << 24);
}
@@ -707,6 +717,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
else {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
+ assert(usage == PIPE_TRANSFER_READ_WRITE);
for (k = 0; k < spanWidth; k++) {
dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
}
@@ -716,13 +727,15 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
if (format == GL_DEPTH_STENCIL) {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
+ assert(usage == PIPE_TRANSFER_WRITE);
for (k = 0; k < spanWidth; k++) {
- dest[k] = zValues[k] | (sValues[k] << 24);
+ dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
}
}
else {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
+ assert(usage == PIPE_TRANSFER_READ_WRITE);
for (k = 0; k < spanWidth; k++) {
dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
}
@@ -756,7 +769,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
struct st_vertex_program *stvp;
struct st_context *st = ctx->st;
struct pipe_surface *ps;
- GLuint bufferFormat;
const GLfloat *color;
if (format == GL_STENCIL_INDEX ||
@@ -784,8 +796,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
color = NULL;
}
- bufferFormat = ps->format;
-
/* draw with textured quad */
{
struct pipe_texture *pt
@@ -810,6 +820,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
{
struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
struct pipe_screen *screen = ctx->st->pipe->screen;
+ enum pipe_transfer_usage usage;
struct pipe_transfer *ptDraw;
ubyte *drawMap;
ubyte *buffer;
@@ -826,9 +837,15 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
&ctx->DefaultPacking, buffer);
- ptDraw = screen->get_tex_transfer(screen, rbDraw->texture, 0, 0, 0,
- PIPE_TRANSFER_WRITE, dstx, dsty,
- width, height);
+ if(pf_get_component_bits( rbDraw->format, PIPE_FORMAT_COMP_Z ) != 0)
+ usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ usage = PIPE_TRANSFER_WRITE;
+
+ ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx),
+ rbDraw->texture, 0, 0, 0,
+ usage, dstx, dsty,
+ width, height);
assert(ptDraw->block.width == 1);
assert(ptDraw->block.height == 1);
@@ -857,6 +874,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
{
uint *dst4 = (uint *) dst;
int j;
+ assert(usage == PIPE_TRANSFER_READ_WRITE);
for (j = 0; j < width; j++) {
*dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
dst4++;
@@ -867,6 +885,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
{
uint *dst4 = (uint *) dst;
int j;
+ assert(usage == PIPE_TRANSFER_READ_WRITE);
for (j = 0; j < width; j++) {
*dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff);
dst4++;
@@ -874,6 +893,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
}
break;
case PIPE_FORMAT_S8_UNORM:
+ assert(usage == PIPE_TRANSFER_WRITE);
memcpy(dst, src, width);
break;
default:
@@ -904,11 +924,38 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
GLfloat *color;
enum pipe_format srcFormat, texFormat;
- /* make sure rendering has completed */
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
st_validate_state(st);
+ if (srcx < 0) {
+ width -= -srcx;
+ dstx += -srcx;
+ srcx = 0;
+ }
+
+ if (srcy < 0) {
+ height -= -srcy;
+ dsty += -srcy;
+ srcy = 0;
+ }
+
+ if (dstx < 0) {
+ width -= -dstx;
+ srcx += -dstx;
+ dstx = 0;
+ }
+
+ if (dsty < 0) {
+ height -= -dsty;
+ srcy += -dsty;
+ dsty = 0;
+ }
+
+ if (width < 0 || height < 0)
+ return;
+
+
if (type == GL_STENCIL) {
/* can't use texturing to do stencil */
copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
@@ -950,15 +997,24 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
}
}
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ srcy = ctx->DrawBuffer->Height - srcy - height;
+
+ if (srcy < 0) {
+ height -= -srcy;
+ srcy = 0;
+ }
+
+ if (height < 0)
+ return;
+ }
+
pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0,
- width, height, 1, 0,
+ width, height, 1,
PIPE_TEXTURE_USAGE_SAMPLER);
if (!pt)
return;
- if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
- srcy = ctx->DrawBuffer->Height - srcy - height;
- }
if (srcFormat == texFormat) {
/* copy source framebuffer surface into mipmap/texture */
@@ -978,13 +1034,13 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
else {
/* CPU-based fallback/conversion */
struct pipe_transfer *ptRead =
- screen->get_tex_transfer(screen, rbRead->texture, 0, 0, 0,
- PIPE_TRANSFER_READ, srcx, srcy, width,
- height);
+ st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0,
+ PIPE_TRANSFER_READ, srcx, srcy, width,
+ height);
struct pipe_transfer *ptTex =
- screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
- 0, 0, width, height);
+ st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
+ 0, 0, width, height);
if (type == GL_COLOR) {
/* alternate path using get/put_tile() */
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index f74d0d46d0..ecdb988033 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -88,94 +88,92 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
{
struct pipe_context *pipe = ctx->st->pipe;
struct st_renderbuffer *strb = st_renderbuffer(rb);
- struct pipe_texture template;
- unsigned surface_usage;
-
- /* Free the old surface and texture
- */
- pipe_surface_reference( &strb->surface, NULL );
- pipe_texture_reference( &strb->texture, NULL );
-
-
- memset(&template, 0, sizeof(template));
-
- if (strb->format != PIPE_FORMAT_NONE) {
- template.format = strb->format;
- }
- else {
- template.format = st_choose_renderbuffer_format(pipe, internalFormat);
- }
-
+ enum pipe_format format;
+
+ if (strb->format != PIPE_FORMAT_NONE)
+ format = strb->format;
+ else
+ format = st_choose_renderbuffer_format(pipe, internalFormat);
+
+ /* init renderbuffer fields */
strb->Base.Width = width;
strb->Base.Height = height;
- init_renderbuffer_bits(strb, template.format);
-
- template.target = PIPE_TEXTURE_2D;
- template.compressed = 0;
- pf_get_block(template.format, &template.block);
- template.width[0] = width;
- template.height[0] = height;
- template.depth[0] = 1;
- template.last_level = 0;
- template.nr_samples = rb->NumSamples;
-
- if (pf_is_depth_stencil(template.format)) {
- template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ init_renderbuffer_bits(strb, format);
+
+ strb->defined = GL_FALSE; /* undefined contents now */
+
+ if(strb->software) {
+ struct pipe_format_block block;
+ size_t size;
+
+ _mesa_free(strb->data);
+
+ assert(strb->format != PIPE_FORMAT_NONE);
+ pf_get_block(strb->format, &block);
+
+ strb->stride = pf_get_stride(&block, width);
+ size = pf_get_2d_size(&block, strb->stride, height);
+
+ strb->data = _mesa_malloc(size);
+
+ return strb->data != NULL;
}
else {
- template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
- PIPE_TEXTURE_USAGE_RENDER_TARGET);
- }
-
-
- /* Probably need dedicated flags for surface usage too:
- */
- surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
-#if 0
- PIPE_BUFFER_USAGE_CPU_READ |
- PIPE_BUFFER_USAGE_CPU_WRITE);
-#endif
-
- strb->texture = pipe->screen->texture_create( pipe->screen,
- &template );
+ struct pipe_texture template;
+ unsigned surface_usage;
+
+ /* Free the old surface and texture
+ */
+ pipe_surface_reference( &strb->surface, NULL );
+ pipe_texture_reference( &strb->texture, NULL );
- /* Special path for accum buffers.
- *
- * Try a different surface format. Since accum buffers are s/w
- * only for now, the surface pixel format doesn't really matter,
- * only that the buffer is large enough.
- */
- if (!strb->texture && template.format == DEFAULT_ACCUM_PIPE_FORMAT)
- {
- /* Actually, just setting this usage value should be sufficient
- * to tell the driver to go ahead and allocate the buffer, even
- * if HW doesn't support the format.
+ /* Setup new texture template.
*/
- template.tex_usage = 0;
- surface_usage = (PIPE_BUFFER_USAGE_CPU_READ |
+ memset(&template, 0, sizeof(template));
+ template.target = PIPE_TEXTURE_2D;
+ template.format = format;
+ pf_get_block(format, &template.block);
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ template.last_level = 0;
+ template.nr_samples = rb->NumSamples;
+ if (pf_is_depth_stencil(format)) {
+ template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ }
+ else {
+ template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET);
+ }
+
+ /* Probably need dedicated flags for surface usage too:
+ */
+ surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+#if 0
+ PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE);
+#endif
strb->texture = pipe->screen->texture_create( pipe->screen,
&template );
- }
-
- if (!strb->texture)
- return FALSE;
+ if (!strb->texture)
+ return FALSE;
- strb->surface = pipe->screen->get_tex_surface( pipe->screen,
- strb->texture,
- 0, 0, 0,
- surface_usage );
+ strb->surface = pipe->screen->get_tex_surface( pipe->screen,
+ strb->texture,
+ 0, 0, 0,
+ surface_usage );
- assert(strb->surface->texture);
- assert(strb->surface->format);
- assert(strb->surface->width == width);
- assert(strb->surface->height == height);
+ assert(strb->surface->texture);
+ assert(strb->surface->format);
+ assert(strb->surface->width == width);
+ assert(strb->surface->height == height);
- return strb->surface != NULL;
+ return strb->surface != NULL;
+ }
}
@@ -189,6 +187,7 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb)
ASSERT(strb);
pipe_surface_reference(&strb->surface, NULL);
pipe_texture_reference(&strb->texture, NULL);
+ _mesa_free(strb->data);
_mesa_free(strb);
}
@@ -245,7 +244,7 @@ st_new_renderbuffer(GLcontext *ctx, GLuint name)
* renderbuffer). The window system code determines the format.
*/
struct gl_renderbuffer *
-st_new_renderbuffer_fb(enum pipe_format format, int samples)
+st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
{
struct st_renderbuffer *strb;
@@ -259,7 +258,8 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples)
strb->Base.ClassID = 0x4242; /* just a unique value */
strb->Base.NumSamples = samples;
strb->format = format;
-
+ strb->software = sw;
+
switch (format) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_B8G8R8A8_UNORM:
@@ -290,7 +290,7 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples)
strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
strb->Base._BaseFormat = GL_STENCIL_INDEX;
break;
- case DEFAULT_ACCUM_PIPE_FORMAT: /*PIPE_FORMAT_R16G16B16A16_SNORM*/
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
strb->Base.InternalFormat = GL_RGBA16;
strb->Base._BaseFormat = GL_RGBA;
break;
@@ -346,6 +346,7 @@ st_render_texture(GLcontext *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att)
{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
struct st_renderbuffer *strb;
struct gl_renderbuffer *rb;
struct pipe_texture *pt = st_get_texobj_texture(att->Texture);
@@ -368,6 +369,8 @@ st_render_texture(GLcontext *ctx,
rb->AllocStorage = NULL; /* should not get called */
strb = st_renderbuffer(rb);
+ assert(strb->Base.RefCount > 0);
+
/* get the texture for the texture object */
stObj = st_texture_object(att->Texture);
@@ -387,7 +390,14 @@ st_render_texture(GLcontext *ctx,
pipe_surface_reference(&strb->surface, NULL);
- /* the new surface will be created during framebuffer validation */
+ /* new surface for rendering into the texture */
+ strb->surface = screen->get_tex_surface(screen,
+ strb->texture,
+ strb->rtt_face,
+ strb->rtt_level,
+ strb->rtt_slice,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
init_renderbuffer_bits(strb, pt->format);
@@ -455,6 +465,134 @@ st_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
}
+/**
+ * Copy back color buffer to front color buffer.
+ */
+static void
+copy_back_to_front(struct st_context *st,
+ struct gl_framebuffer *fb,
+ gl_buffer_index frontIndex,
+ gl_buffer_index backIndex)
+
+{
+ struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
+ struct pipe_surface *surf_front, *surf_back;
+
+ (void) st_get_framebuffer_surface(stfb, frontIndex, &surf_front);
+ (void) st_get_framebuffer_surface(stfb, backIndex, &surf_back);
+
+ if (surf_front && surf_back) {
+ st->pipe->surface_copy(st->pipe,
+ surf_front, 0, 0, /* dest */
+ surf_back, 0, 0, /* src */
+ fb->Width, fb->Height);
+ }
+}
+
+
+/**
+ * Check if we're drawing into, or read from, a front color buffer. If the
+ * front buffer is missing, create it now.
+ *
+ * The back color buffer must exist since we'll use its format/samples info
+ * for creating the front buffer.
+ *
+ * \param frontIndex either BUFFER_FRONT_LEFT or BUFFER_FRONT_RIGHT
+ * \param backIndex either BUFFER_BACK_LEFT or BUFFER_BACK_RIGHT
+ */
+static void
+check_create_front_buffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ gl_buffer_index frontIndex,
+ gl_buffer_index backIndex)
+{
+ if (fb->Attachment[frontIndex].Renderbuffer == NULL) {
+ GLboolean create = GL_FALSE;
+
+ /* check if drawing to or reading from front buffer */
+ if (fb->_ColorReadBufferIndex == frontIndex) {
+ create = GL_TRUE;
+ }
+ else {
+ GLuint b;
+ for (b = 0; b < fb->_NumColorDrawBuffers; b++) {
+ if (fb->_ColorDrawBufferIndexes[b] == frontIndex) {
+ create = GL_TRUE;
+ break;
+ }
+ }
+ }
+
+ if (create) {
+ struct st_renderbuffer *back;
+ struct gl_renderbuffer *front;
+ enum pipe_format colorFormat;
+ uint samples;
+
+ if (0)
+ _mesa_debug(ctx, "Allocate new front buffer\n");
+
+ /* get back renderbuffer info */
+ back = st_renderbuffer(fb->Attachment[backIndex].Renderbuffer);
+ colorFormat = back->format;
+ samples = back->Base.NumSamples;
+
+ /* create front renderbuffer */
+ front = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
+ _mesa_add_renderbuffer(fb, frontIndex, front);
+
+ /* alloc texture/surface for new front buffer */
+ front->AllocStorage(ctx, front, front->InternalFormat,
+ fb->Width, fb->Height);
+
+ /* initialize the front color buffer contents by copying
+ * the back buffer.
+ */
+ copy_back_to_front(ctx->st, fb, frontIndex, backIndex);
+ }
+ }
+}
+
+
+/**
+ * If front left/right color buffers are missing, create them now.
+ */
+static void
+check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ /* check if we need to create the front left buffer now */
+ check_create_front_buffer(ctx, fb, BUFFER_FRONT_LEFT, BUFFER_BACK_LEFT);
+
+ if (fb->Visual.stereoMode) {
+ check_create_front_buffer(ctx, fb, BUFFER_FRONT_RIGHT, BUFFER_BACK_RIGHT);
+ }
+
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+/**
+ * Called via glDrawBuffer.
+ */
+static void
+st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
+{
+ (void) count;
+ (void) buffers;
+ check_create_front_buffers(ctx, ctx->DrawBuffer);
+}
+
+
+/**
+ * Called via glReadBuffer.
+ */
+static void
+st_ReadBuffer(GLcontext *ctx, GLenum buffer)
+{
+ (void) buffer;
+ check_create_front_buffers(ctx, ctx->ReadBuffer);
+}
+
+
void st_init_fbo_functions(struct dd_function_table *functions)
{
functions->NewFramebuffer = st_new_framebuffer;
@@ -467,4 +605,7 @@ void st_init_fbo_functions(struct dd_function_table *functions)
/* no longer needed by core Mesa, drivers handle resizes...
functions->ResizeBuffers = st_resize_buffers;
*/
+
+ functions->DrawBuffers = st_DrawBuffers;
+ functions->ReadBuffer = st_ReadBuffer;
}
diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h
index 44fa9fe9a4..bea6eb89c3 100644
--- a/src/mesa/state_tracker/st_cb_fbo.h
+++ b/src/mesa/state_tracker/st_cb_fbo.h
@@ -30,10 +30,6 @@
#define ST_CB_FBO_H
-#define DEFAULT_ACCUM_PIPE_FORMAT PIPE_FORMAT_R16G16B16A16_SNORM
-
-
-
/**
* Derived renderbuffer class. Just need to add a pointer to the
* pipe surface.
@@ -44,7 +40,15 @@ struct st_renderbuffer
struct pipe_texture *texture;
struct pipe_surface *surface; /* temporary view into texture */
enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */
-
+ GLboolean defined; /**< defined contents? */
+
+ /**
+ * Used only when hardware accumulation buffers are not supported.
+ */
+ boolean software;
+ size_t stride;
+ void *data;
+
struct st_texture_object *rtt; /**< GL render to texture's texture */
int rtt_level, rtt_face, rtt_slice;
@@ -62,7 +66,7 @@ st_renderbuffer(struct gl_renderbuffer *rb)
extern struct gl_renderbuffer *
-st_new_renderbuffer_fb(enum pipe_format format, int samples);
+st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw);
extern void
st_init_fbo_functions(struct dd_function_table *functions);
diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c
index 7d7d3823c9..8ceeeabcd3 100644
--- a/src/mesa/state_tracker/st_cb_flush.c
+++ b/src/mesa/state_tracker/st_cb_flush.c
@@ -47,10 +47,19 @@
#include "util/u_blit.h"
+/** Check if we have a front color buffer and if it's been drawn to. */
static INLINE GLboolean
is_front_buffer_dirty(struct st_context *st)
{
- return st->frontbuffer_status == FRONT_STATUS_DIRTY;
+ if (st->frontbuffer_status == FRONT_STATUS_DIRTY) {
+ return GL_TRUE;
+ }
+ else {
+ GLframebuffer *fb = st->ctx->DrawBuffer;
+ struct st_renderbuffer *strb
+ = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ return strb && strb->defined;
+ }
}
@@ -82,7 +91,7 @@ display_front_buffer(struct st_context *st)
void st_flush( struct st_context *st, uint pipeFlushFlags,
struct pipe_fence_handle **fence )
{
- FLUSH_VERTICES(st->ctx, 0);
+ FLUSH_CURRENT(st->ctx, 0);
/* Release any vertex buffers that might potentially be accessed in
* successive frames:
diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c
index 7dd2352739..3bcccd0df4 100644
--- a/src/mesa/state_tracker/st_cb_rasterpos.c
+++ b/src/mesa/state_tracker/st_cb_rasterpos.c
@@ -194,9 +194,10 @@ new_draw_rastpos_stage(GLcontext *ctx, struct draw_context *draw)
rs->stage.destroy = rastpos_destroy;
rs->ctx = ctx;
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ for (i = 0; i < Elements(rs->array); i++) {
rs->array[i].Size = 4;
rs->array[i].Type = GL_FLOAT;
+ rs->array[i].Format = GL_RGBA;
rs->array[i].Stride = 0;
rs->array[i].StrideB = 0;
rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i];
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index 9ce5f3fe84..ccf1a0b563 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -42,13 +42,15 @@
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "util/u_tile.h"
+
#include "st_context.h"
#include "st_cb_bitmap.h"
#include "st_cb_readpixels.h"
#include "st_cb_fbo.h"
#include "st_format.h"
#include "st_public.h"
-
+#include "st_texture.h"
+#include "st_inlines.h"
/**
* Special case for reading stencil buffer.
@@ -73,8 +75,11 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
}
/* Create a read transfer from the renderbuffer's texture */
- pt = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ, x, y, width, height);
+
+ pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, x, y,
+ width, height);
/* map the stencil buffer */
stmap = screen->transfer_map(screen, pt);
@@ -107,7 +112,7 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
case PIPE_FORMAT_S8Z24_UNORM:
if (format == GL_DEPTH_STENCIL) {
const uint *src = (uint *) (stmap + srcY * pt->stride);
- const GLfloat scale = 1.0 / (0xffffff);
+ const GLfloat scale = 1.0f / (0xffffff);
GLint k;
for (k = 0; k < width; k++) {
sValues[k] = src[k] >> 24;
@@ -125,7 +130,7 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
case PIPE_FORMAT_Z24S8_UNORM:
if (format == GL_DEPTH_STENCIL) {
const uint *src = (uint *) (stmap + srcY * pt->stride);
- const GLfloat scale = 1.0 / (0xffffff);
+ const GLfloat scale = 1.0f / (0xffffff);
GLint k;
for (k = 0; k < width; k++) {
sValues[k] = src[k] & 0xff;
@@ -240,8 +245,10 @@ st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb,
y = strb->texture->height[0] - y - height;
}
- trans = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ, x, y, width, height);
+ trans = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, x, y,
+ width, height);
if (!trans) {
return GL_FALSE;
}
@@ -350,7 +357,6 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
if (!dest)
return;
- /* make sure rendering has completed */
st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
if (format == GL_STENCIL_INDEX ||
@@ -395,8 +401,10 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
}
/* Create a read transfer from the renderbuffer's texture */
- trans = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ, x, y, width, height);
+ trans = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, x, y,
+ width, height);
/* determine bottom-to-top vs. top-to-bottom order */
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
@@ -437,11 +445,16 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
}
}
else {
- /* untested, but simple: */
+ /* XXX: unreachable code -- should be before st_read_stencil_pixels */
assert(format == GL_DEPTH_STENCIL_EXT);
for (i = 0; i < height; i++) {
+ GLuint *zshort = (GLuint *)dst;
pipe_get_tile_raw(trans, 0, y, width, 1, dst, 0);
y += yStep;
+ /* Reverse into 24/8 */
+ for (j = 0; j < width; j++) {
+ zshort[j] = (zshort[j] << 8) | (zshort[j] >> 24);
+ }
dst += dstStride;
}
}
@@ -464,7 +477,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
}
}
else {
- /* untested, but simple: */
+ /* XXX: unreachable code -- should be before st_read_stencil_pixels */
assert(format == GL_DEPTH_STENCIL_EXT);
for (i = 0; i < height; i++) {
pipe_get_tile_raw(trans, 0, y, width, 1, dst, 0);
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 8013e69e8e..14b78d1253 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -26,6 +26,7 @@
**************************************************************************/
#include "main/mfeatures.h"
+#include "main/bufferobj.h"
#if FEATURE_convolve
#include "main/convolve.h"
#endif
@@ -49,12 +50,15 @@
#include "state_tracker/st_public.h"
#include "state_tracker/st_texture.h"
#include "state_tracker/st_gen_mipmap.h"
+#include "state_tracker/st_inlines.h"
+#include "state_tracker/st_atom.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "util/u_tile.h"
#include "util/u_blit.h"
+#include "util/u_surface.h"
#define DBG if (0) printf
@@ -88,7 +92,7 @@ gl_target_to_pipe(GLenum target)
* Return nominal bytes per texel for a compressed format, 0 for non-compressed
* format.
*/
-static int
+static GLuint
compressed_num_bytes(GLuint mesaFormat)
{
switch(mesaFormat) {
@@ -110,6 +114,25 @@ compressed_num_bytes(GLuint mesaFormat)
}
+static GLboolean
+is_compressed_mesa_format(const struct gl_texture_format *format)
+{
+ switch (format->MesaFormat) {
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
/** called via ctx->Driver.NewTextureImage() */
static struct gl_texture_image *
st_NewTextureImage(GLcontext * ctx)
@@ -169,7 +192,7 @@ st_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
* than COPY_DWORDS would:
* XXX Put this in src/mesa/main/imports.h ???
*/
-#if defined(i386) || defined(__i386__)
+#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)
static INLINE void *
__memcpy(void *to, const void *from, size_t n)
{
@@ -227,6 +250,21 @@ logbase2(int n)
/**
+ * Return default texture usage bitmask for the given texture format.
+ */
+static GLuint
+default_usage(enum pipe_format fmt)
+{
+ GLuint usage = PIPE_TEXTURE_USAGE_SAMPLER;
+ if (pf_is_depth_stencil(fmt))
+ usage |= PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ else
+ usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ return usage;
+}
+
+
+/**
* Allocate a pipe_texture object for the given st_texture_object using
* the given st_texture_image to guess the mipmap size/levels.
*
@@ -250,7 +288,7 @@ guess_and_alloc_texture(struct st_context *st,
GLuint width = stImage->base.Width2; /* size w/out border */
GLuint height = stImage->base.Height2;
GLuint depth = stImage->base.Depth2;
- GLuint i, comp_byte = 0;
+ GLuint i, usage;
enum pipe_format fmt;
DBG("%s\n", __FUNCTION__);
@@ -308,10 +346,10 @@ guess_and_alloc_texture(struct st_context *st,
lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
}
- if (stImage->base.IsCompressed)
- comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat);
-
fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat);
+
+ usage = default_usage(fmt);
+
stObj->pt = st_texture_create(st,
gl_target_to_pipe(stObj->base.Target),
fmt,
@@ -319,11 +357,7 @@ guess_and_alloc_texture(struct st_context *st,
width,
height,
depth,
- comp_byte,
- ( (pf_is_depth_stencil(fmt) ?
- PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
- PIPE_TEXTURE_USAGE_RENDER_TARGET) |
- PIPE_TEXTURE_USAGE_SAMPLER ));
+ usage);
DBG("%s - success\n", __FUNCTION__);
}
@@ -368,6 +402,109 @@ strip_texture_border(GLint border,
/**
+ * Try to do texture compression via rendering. If the Gallium driver
+ * can render into a compressed surface this will allow us to do texture
+ * compression.
+ * \return GL_TRUE for success, GL_FALSE for failure
+ */
+static GLboolean
+compress_with_blit(GLcontext * ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_image *texImage)
+{
+ const GLuint dstImageOffsets[1] = {0};
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ const struct gl_texture_format *mesa_format;
+ struct pipe_texture templ;
+ struct pipe_texture *src_tex;
+ struct pipe_surface *dst_surface;
+ struct pipe_transfer *tex_xfer;
+ void *map;
+
+
+ if (!stImage->pt) {
+ /* XXX: Can this happen? Should we assert? */
+ return GL_FALSE;
+ }
+
+ /* get destination surface (in the compressed texture) */
+ dst_surface = screen->get_tex_surface(screen, stImage->pt,
+ stImage->face, stImage->level, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ if (!dst_surface) {
+ /* can't render into this format (or other problem) */
+ return GL_FALSE;
+ }
+
+ /* Choose format for the temporary RGBA texture image.
+ */
+ mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type);
+ assert(mesa_format);
+ if (!mesa_format)
+ return GL_FALSE;
+
+ /* Create the temporary source texture
+ */
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = st_mesa_format_to_pipe_format(mesa_format->MesaFormat);
+ pf_get_block(templ.format, &templ.block);
+ templ.width[0] = width;
+ templ.height[0] = height;
+ templ.depth[0] = 1;
+ templ.last_level = 0;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+ src_tex = screen->texture_create(screen, &templ);
+
+ if (!src_tex)
+ return GL_FALSE;
+
+ /* Put user's tex data into the temporary texture
+ */
+ tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx), src_tex,
+ 0, 0, 0, /* face, level are zero */
+ PIPE_TRANSFER_WRITE,
+ 0, 0, width, height); /* x, y, w, h */
+ map = screen->transfer_map(screen, tex_xfer);
+
+ mesa_format->StoreImage(ctx, 2, GL_RGBA, mesa_format,
+ map, /* dest ptr */
+ 0, 0, 0, /* dest x/y/z offset */
+ tex_xfer->stride, /* dest row stride (bytes) */
+ dstImageOffsets, /* image offsets (for 3D only) */
+ width, height, 1, /* size */
+ format, type, /* source format/type */
+ pixels, /* source data */
+ unpack); /* source data packing */
+
+ screen->transfer_unmap(screen, tex_xfer);
+ screen->tex_transfer_destroy(tex_xfer);
+
+ /* copy / compress image */
+ util_blit_pixels_tex(ctx->st->blit,
+ src_tex, /* pipe_texture (src) */
+ 0, 0, /* src x0, y0 */
+ width, height, /* src x1, y1 */
+ dst_surface, /* pipe_surface (dst) */
+ xoffset, yoffset, /* dst x0, y0 */
+ xoffset + width, /* dst x1 */
+ yoffset + height, /* dst y1 */
+ 0.0, /* z */
+ PIPE_TEX_MIPFILTER_NEAREST);
+
+ pipe_surface_reference(&dst_surface, NULL);
+ pipe_texture_reference(&src_tex, NULL);
+
+ return GL_TRUE;
+}
+
+
+/**
* Do glTexImage1/2/3D().
*/
static void
@@ -381,8 +518,9 @@ st_TexImage(GLcontext * ctx,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
- GLsizei imageSize, int compressed)
+ GLsizei imageSize, GLboolean compressed_src)
{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
struct st_texture_object *stObj = st_texture_object(texObj);
struct st_texture_image *stImage = st_texture_image(texImage);
GLint postConvWidth, postConvHeight;
@@ -395,8 +533,7 @@ st_TexImage(GLcontext * ctx,
/* gallium does not support texture borders, strip it off */
if (border) {
- strip_texture_border(border, &width, &height, &depth,
- unpack, &unpackNB);
+ strip_texture_border(border, &width, &height, &depth, unpack, &unpackNB);
unpack = &unpackNB;
texImage->Width = width;
texImage->Height = height;
@@ -512,11 +649,12 @@ st_TexImage(GLcontext * ctx,
* the expectation that the texture will be set up but nothing
* more will be done. This is where those calls return:
*/
- if (compressed) {
+ if (compressed_src) {
pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
unpack,
"glCompressedTexImage");
- } else {
+ }
+ else {
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
format, type,
pixels, unpack, "glTexImage");
@@ -524,12 +662,28 @@ st_TexImage(GLcontext * ctx,
if (!pixels)
return;
+ /* See if we can do texture compression with a blit/render.
+ */
+ if (!compressed_src &&
+ !ctx->Mesa_DXTn &&
+ is_compressed_mesa_format(texImage->TexFormat) &&
+ screen->is_format_supported(screen,
+ stImage->pt->format,
+ stImage->pt->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth,
+ format, type, pixels, unpack, texImage)) {
+ goto done;
+ }
+ }
+
if (stImage->pt) {
texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
PIPE_TRANSFER_WRITE, 0, 0,
stImage->base.Width,
stImage->base.Height);
- dstRowStride = stImage->transfer->stride;
+ if(stImage->transfer)
+ dstRowStride = stImage->transfer->stride;
}
else {
/* Allocate regular memory and store the image there temporarily. */
@@ -559,16 +713,16 @@ st_TexImage(GLcontext * ctx,
* the blitter to copy. Or, use the hardware to do the format
* conversion and copy:
*/
- if (compressed) {
+ if (compressed_src) {
memcpy(texImage->Data, pixels, imageSize);
}
else {
- GLuint srcImageStride = _mesa_image_image_stride(unpack, width, height,
- format, type);
- int i;
+ const GLuint srcImageStride =
+ _mesa_image_image_stride(unpack, width, height, format, type);
+ GLint i;
const GLubyte *src = (const GLubyte *) pixels;
- for (i = 0; i++ < depth;) {
+ for (i = 0; i < depth; i++) {
if (!texImage->TexFormat->StoreImage(ctx, dims,
texImage->_BaseFormat,
texImage->TexFormat,
@@ -581,9 +735,11 @@ st_TexImage(GLcontext * ctx,
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
}
- if (stImage->pt && i < depth) {
+ if (stImage->pt && i + 1 < depth) {
+ /* unmap this slice */
st_texture_image_unmap(ctx->st, stImage);
- texImage->Data = st_texture_image_map(ctx->st, stImage, i,
+ /* map next slice of 3D texture */
+ texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1,
PIPE_TRANSFER_WRITE, 0, 0,
stImage->base.Width,
stImage->base.Height);
@@ -594,7 +750,8 @@ st_TexImage(GLcontext * ctx,
_mesa_unmap_teximage_pbo(ctx, unpack);
- if (stImage->pt) {
+done:
+ if (stImage->pt && texImage->Data) {
st_texture_image_unmap(ctx->st, stImage);
texImage->Data = NULL;
}
@@ -616,9 +773,9 @@ st_TexImage3D(GLcontext * ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- st_TexImage(ctx, 3, target, level,
- internalFormat, width, height, depth, border,
- format, type, pixels, unpack, texObj, texImage, 0, 0);
+ st_TexImage(ctx, 3, target, level, internalFormat, width, height, depth,
+ border, format, type, pixels, unpack, texObj, texImage,
+ 0, GL_FALSE);
}
@@ -632,9 +789,8 @@ st_TexImage2D(GLcontext * ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- st_TexImage(ctx, 2, target, level,
- internalFormat, width, height, 1, border,
- format, type, pixels, unpack, texObj, texImage, 0, 0);
+ st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border,
+ format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
}
@@ -648,9 +804,8 @@ st_TexImage1D(GLcontext * ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- st_TexImage(ctx, 1, target, level,
- internalFormat, width, 1, 1, border,
- format, type, pixels, unpack, texObj, texImage, 0, 0);
+ st_TexImage(ctx, 1, target, level, internalFormat, width, 1, 1, border,
+ format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
}
@@ -662,12 +817,96 @@ st_CompressedTexImage2D(GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- st_TexImage(ctx, 2, target, level,
- internalFormat, width, height, 1, border,
- 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1);
+ st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border,
+ 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, GL_TRUE);
}
+
+/**
+ * glGetTexImage() helper: decompress a compressed texture by rendering
+ * a textured quad. Store the results in the user's buffer.
+ */
+static void
+decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ const GLuint width = texImage->Width;
+ const GLuint height = texImage->Height;
+ struct pipe_surface *dst_surface;
+ struct pipe_texture *dst_texture;
+ struct pipe_transfer *tex_xfer;
+
+ /* create temp / dest surface */
+ if (!util_create_rgba_surface(screen, width, height,
+ &dst_texture, &dst_surface)) {
+ _mesa_problem(ctx, "util_create_rgba_surface() failed "
+ "in decompress_with_blit()");
+ return;
+ }
+
+ /* blit/render/decompress */
+ util_blit_pixels_tex(ctx->st->blit,
+ stImage->pt, /* pipe_texture (src) */
+ 0, 0, /* src x0, y0 */
+ width, height, /* src x1, y1 */
+ dst_surface, /* pipe_surface (dst) */
+ 0, 0, /* dst x0, y0 */
+ width, height, /* dst x1, y1 */
+ 0.0, /* z */
+ PIPE_TEX_MIPFILTER_NEAREST);
+
+ /* map the dst_surface so we can read from it */
+ tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx),
+ dst_texture, 0, 0, 0,
+ PIPE_TRANSFER_READ,
+ 0, 0, width, height);
+
+ pixels = _mesa_map_readpix_pbo(ctx, &ctx->Pack, pixels);
+
+ /* copy/pack data into user buffer */
+ if (st_equal_formats(stImage->pt->format, format, type)) {
+ /* memcpy */
+ const uint bytesPerRow = width * pf_get_size(stImage->pt->format);
+ ubyte *map = screen->transfer_map(screen, tex_xfer);
+ GLuint row;
+ for (row = 0; row < height; row++) {
+ GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
+ height, format, type, row, 0);
+ memcpy(dest, map, bytesPerRow);
+ map += tex_xfer->stride;
+ }
+ screen->transfer_unmap(screen, tex_xfer);
+ }
+ else {
+ /* format translation via floats */
+ GLuint row;
+ for (row = 0; row < height; row++) {
+ const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
+ GLfloat rgba[4 * MAX_WIDTH];
+ GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
+ height, format, type, row, 0);
+
+ /* get float[4] rgba row from surface */
+ pipe_get_tile_rgba(tex_xfer, 0, row, width, 1, rgba);
+
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
+ type, dest, &ctx->Pack, transferOps);
+ }
+ }
+
+ _mesa_unmap_readpix_pbo(ctx, &ctx->Pack);
+
+ /* destroy the temp / dest surface */
+ util_destroy_rgba_surface(dst_texture, dst_surface);
+}
+
+
+
/**
* Need to map texture image into memory before copying image data,
* then unmap it.
@@ -676,22 +915,36 @@ static void
st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid * pixels,
struct gl_texture_object *texObj,
- struct gl_texture_image *texImage, int compressed)
+ struct gl_texture_image *texImage, GLboolean compressed_dst)
{
struct st_texture_image *stImage = st_texture_image(texImage);
- GLuint dstImageStride = _mesa_image_image_stride(&ctx->Pack,
- texImage->Width,
- texImage->Height,
- format, type);
- GLuint depth;
- GLuint i;
+ const GLuint dstImageStride =
+ _mesa_image_image_stride(&ctx->Pack, texImage->Width, texImage->Height,
+ format, type);
+ GLuint depth, i;
GLubyte *dest;
+ if (stImage->pt &&
+ pf_is_compressed(stImage->pt->format) &&
+ !compressed_dst) {
+ /* Need to decompress the texture.
+ * We'll do this by rendering a textured quad.
+ * Note that we only expect RGBA formats (no Z/depth formats).
+ */
+ decompress_with_blit(ctx, target, level, format, type, pixels,
+ texObj, texImage);
+ return;
+ }
+
/* Map */
if (stImage->pt) {
/* Image is stored in hardware format in a buffer managed by the
* kernel. Need to explicitly map and unmap it.
*/
+
+ st_teximage_flush_before_map(ctx->st, stImage->pt, 0, level,
+ PIPE_TRANSFER_READ);
+
texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
PIPE_TRANSFER_READ, 0, 0,
stImage->base.Width,
@@ -715,18 +968,21 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
dest = (GLubyte *) pixels;
- for (i = 0; i++ < depth;) {
- if (compressed) {
+ for (i = 0; i < depth; i++) {
+ if (compressed_dst) {
_mesa_get_compressed_teximage(ctx, target, level, dest,
texObj, texImage);
- } else {
+ }
+ else {
_mesa_get_teximage(ctx, target, level, format, type, dest,
texObj, texImage);
}
- if (stImage->pt && i < depth) {
+ if (stImage->pt && i + 1 < depth) {
+ /* unmap this slice */
st_texture_image_unmap(ctx->st, stImage);
- texImage->Data = st_texture_image_map(ctx->st, stImage, i,
+ /* map next slice of 3D texture */
+ texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1,
PIPE_TRANSFER_READ, 0, 0,
stImage->base.Width,
stImage->base.Height);
@@ -750,8 +1006,8 @@ st_GetTexImage(GLcontext * ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- st_get_tex_image(ctx, target, level, format, type, pixels,
- texObj, texImage, 0);
+ st_get_tex_image(ctx, target, level, format, type, pixels, texObj, texImage,
+ GL_FALSE);
}
@@ -761,17 +1017,14 @@ st_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- st_get_tex_image(ctx, target, level, 0, 0, pixels,
- (struct gl_texture_object *) texObj,
- (struct gl_texture_image *) texImage, 1);
+ st_get_tex_image(ctx, target, level, 0, 0, pixels, texObj, texImage,
+ GL_TRUE);
}
static void
-st_TexSubimage(GLcontext * ctx,
- GLint dims,
- GLenum target, GLint level,
+st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type, const void *pixels,
@@ -779,11 +1032,12 @@ st_TexSubimage(GLcontext * ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
struct st_texture_image *stImage = st_texture_image(texImage);
GLuint dstRowStride;
- GLuint srcImageStride = _mesa_image_image_stride(packing, width, height,
- format, type);
- int i;
+ const GLuint srcImageStride =
+ _mesa_image_image_stride(packing, width, height, format, type);
+ GLint i;
const GLubyte *src;
DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
@@ -796,10 +1050,28 @@ st_TexSubimage(GLcontext * ctx,
if (!pixels)
return;
+ /* See if we can do texture compression with a blit/render.
+ */
+ if (!ctx->Mesa_DXTn &&
+ is_compressed_mesa_format(texImage->TexFormat) &&
+ screen->is_format_supported(screen,
+ stImage->pt->format,
+ stImage->pt->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ if (compress_with_blit(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, pixels, packing, texImage)) {
+ goto done;
+ }
+ }
+
/* Map buffer if necessary. Need to lock to prevent other contexts
* from uploading the buffer under us.
*/
if (stImage->pt) {
+ st_teximage_flush_before_map(ctx->st, stImage->pt, 0, level,
+ PIPE_TRANSFER_WRITE);
texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset,
PIPE_TRANSFER_WRITE,
xoffset, yoffset,
@@ -814,7 +1086,7 @@ st_TexSubimage(GLcontext * ctx,
src = (const GLubyte *) pixels;
dstRowStride = stImage->transfer->stride;
- for (i = 0; i++ < depth;) {
+ for (i = 0; i < depth; i++) {
if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data,
@@ -826,10 +1098,12 @@ st_TexSubimage(GLcontext * ctx,
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
}
- if (stImage->pt && i < depth) {
- /* map next slice of 3D texture */
+ if (stImage->pt && i + 1 < depth) {
+ /* unmap this slice */
st_texture_image_unmap(ctx->st, stImage);
- texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i,
+ /* map next slice of 3D texture */
+ texImage->Data = st_texture_image_map(ctx->st, stImage,
+ zoffset + i + 1,
PIPE_TRANSFER_WRITE,
xoffset, yoffset,
width, height);
@@ -837,88 +1111,74 @@ st_TexSubimage(GLcontext * ctx,
}
}
- if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
- ctx->Driver.GenerateMipmap(ctx, target, texObj);
- }
-
_mesa_unmap_teximage_pbo(ctx, packing);
+done:
if (stImage->pt) {
st_texture_image_unmap(ctx->st, stImage);
texImage->Data = NULL;
}
+
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
}
static void
-st_TexSubImage3D(GLcontext * ctx,
- GLenum target,
- GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
+st_TexSubImage3D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
{
- st_TexSubimage(ctx, 3, target, level,
- xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, pixels, packing, texObj, texImage);
+ st_TexSubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type,
+ pixels, packing, texObj, texImage);
}
static void
-st_TexSubImage2D(GLcontext * ctx,
- GLenum target,
- GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
+st_TexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
{
- st_TexSubimage(ctx, 2, target, level,
- xoffset, yoffset, 0,
- width, height, 1,
- format, type, pixels, packing, texObj, texImage);
+ st_TexSubimage(ctx, 2, target, level, xoffset, yoffset, 0,
+ width, height, 1, format, type,
+ pixels, packing, texObj, texImage);
}
static void
-st_TexSubImage1D(GLcontext * ctx,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLsizei width,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
+st_TexSubImage1D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width, GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
{
- st_TexSubimage(ctx, 1, target, level,
- xoffset, 0, 0,
- width, 1, 1,
+ st_TexSubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1,
format, type, pixels, packing, texObj, texImage);
}
/**
- * Do a CopyTexSubImage operation using a read transfer from the source, a write
- * transfer to the destination and get_tile()/put_tile() to access the pixels/texels.
+ * Do a CopyTexSubImage operation using a read transfer from the source,
+ * a write transfer to the destination and get_tile()/put_tile() to access
+ * the pixels/texels.
*
* Note: srcY=0=TOP of renderbuffer
*/
static void
-fallback_copy_texsubimage(GLcontext *ctx,
- GLenum target,
- GLint level,
+fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
struct st_renderbuffer *strb,
struct st_texture_image *stImage,
GLenum baseFormat,
@@ -937,12 +1197,15 @@ fallback_copy_texsubimage(GLcontext *ctx,
srcY = strb->Base.Height - srcY - height;
}
- src_trans = screen->get_tex_transfer( screen,
- strb->texture,
- 0, 0, 0,
- PIPE_TRANSFER_READ,
- srcX, srcY,
- width, height);
+ src_trans = st_cond_flush_get_tex_transfer( st_context(ctx),
+ strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ,
+ srcX, srcY,
+ width, height);
+
+ st_teximage_flush_before_map(ctx->st, stImage->pt, 0, 0,
+ PIPE_TRANSFER_WRITE);
texDest = st_texture_image_map(ctx->st, stImage, 0, PIPE_TRANSFER_WRITE,
destX, destY, width, height);
@@ -980,8 +1243,8 @@ fallback_copy_texsubimage(GLcontext *ctx,
if (tempSrc && texDest) {
const GLint dims = 2;
+ const GLint dstRowStride = stImage->transfer->stride;
struct gl_texture_image *texImage = &stImage->base;
- GLint dstRowStride = stImage->transfer->stride;
struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
@@ -1054,8 +1317,12 @@ st_copy_texsubimage(GLcontext *ctx,
GLboolean use_fallback = GL_TRUE;
GLboolean matching_base_formats;
- /* any rendering in progress must complete before we grab the fb image */
- st_finish(ctx->st);
+ /* any rendering in progress must flushed before we grab the fb image */
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* make sure finalize_textures has been called?
+ */
+ if (0) st_validate_state(ctx->st);
/* determine if copying depth or color data */
if (texBaseFormat == GL_DEPTH_COMPONENT ||
@@ -1070,6 +1337,39 @@ st_copy_texsubimage(GLcontext *ctx,
strb = st_renderbuffer(fb->_ColorReadBuffer);
}
+ if (!strb || !strb->surface || !stImage->pt) {
+ debug_printf("%s: null strb or stImage\n", __FUNCTION__);
+ return;
+ }
+
+ if (srcX < 0) {
+ width -= -srcX;
+ destX += -srcX;
+ srcX = 0;
+ }
+
+ if (srcY < 0) {
+ height -= -srcY;
+ destY += -srcY;
+ srcY = 0;
+ }
+
+ if (destX < 0) {
+ width -= -destX;
+ srcX += -destX;
+ destX = 0;
+ }
+
+ if (destY < 0) {
+ height -= -destY;
+ srcY += -destY;
+ destY = 0;
+ }
+
+ if (width < 0 || height < 0)
+ return;
+
+
assert(strb);
assert(strb->surface);
assert(stImage->pt);
@@ -1095,7 +1395,6 @@ st_copy_texsubimage(GLcontext *ctx,
if (src_format == dest_format && !do_flip) {
/* use surface_copy() / blit */
-
dest_surface = screen->get_tex_surface(screen, stImage->pt,
stImage->face, stImage->level,
destZ,
@@ -1122,7 +1421,7 @@ st_copy_texsubimage(GLcontext *ctx,
PIPE_TEXTURE_USAGE_RENDER_TARGET,
0)) {
/* draw textured quad to do the copy */
- int srcY0, srcY1;
+ GLint srcY0, srcY1;
dest_surface = screen->get_tex_surface(screen, stImage->pt,
stImage->face, stImage->level,
@@ -1179,11 +1478,6 @@ st_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
struct gl_texture_image *texImage =
_mesa_select_tex_image(ctx, texObj, target, level);
-#if 0
- if (border)
- goto fail;
-#endif
-
/* Setup or redefine the texture object, texture and texture
* image. Don't populate yet.
*/
@@ -1274,8 +1568,8 @@ calculate_first_last_level(struct st_texture_object *stObj)
* and having firstLevel and lastLevel as signed prevents the need for
* extra sign checks.
*/
- int firstLevel;
- int lastLevel;
+ GLint firstLevel;
+ GLint lastLevel;
/* Yes, this looks overly complicated, but it's all needed.
*/
@@ -1329,16 +1623,21 @@ copy_image_data_to_texture(struct st_context *st,
/* More straightforward upload.
*/
- st_texture_image_data(st->pipe,
- stObj->pt,
- stImage->face,
- dstLevel,
- stImage->base.Data,
- stImage->base.RowStride *
- stObj->pt->block.size,
- stImage->base.RowStride *
- stImage->base.Height *
- stObj->pt->block.size);
+
+ st_teximage_flush_before_map(st, stObj->pt, stImage->face, dstLevel,
+ PIPE_TRANSFER_WRITE);
+
+
+ st_texture_image_data(st,
+ stObj->pt,
+ stImage->face,
+ dstLevel,
+ stImage->base.Data,
+ stImage->base.RowStride *
+ stObj->pt->block.size,
+ stImage->base.RowStride *
+ stImage->base.Height *
+ stObj->pt->block.size);
_mesa_align_free(stImage->base.Data);
stImage->base.Data = NULL;
}
@@ -1360,9 +1659,7 @@ st_finalize_texture(GLcontext *ctx,
{
struct st_texture_object *stObj = st_texture_object(tObj);
const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
- int comp_byte = 0;
- int cpp;
- GLuint face;
+ GLuint cpp, face;
struct st_texture_image *firstImage;
*needFlush = GL_FALSE;
@@ -1384,14 +1681,12 @@ st_finalize_texture(GLcontext *ctx,
if (firstImage->pt &&
firstImage->pt != stObj->pt &&
firstImage->pt->last_level >= stObj->lastLevel) {
-
pipe_texture_reference(&stObj->pt, firstImage->pt);
}
/* FIXME: determine format block instead of cpp */
if (firstImage->base.IsCompressed) {
- comp_byte = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
- cpp = comp_byte;
+ cpp = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
}
else {
cpp = firstImage->base.TexFormat->TexelBytes;
@@ -1409,8 +1704,9 @@ st_finalize_texture(GLcontext *ctx,
stObj->pt->width[0] != firstImage->base.Width2 ||
stObj->pt->height[0] != firstImage->base.Height2 ||
stObj->pt->depth[0] != firstImage->base.Depth2 ||
- stObj->pt->block.size/stObj->pt->block.width != cpp || /* Nominal bytes per pixel */
- stObj->pt->compressed != firstImage->base.IsCompressed) {
+ /* Nominal bytes per pixel: */
+ stObj->pt->block.size / stObj->pt->block.width != cpp)
+ {
pipe_texture_reference(&stObj->pt, NULL);
ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
}
@@ -1421,6 +1717,8 @@ st_finalize_texture(GLcontext *ctx,
if (!stObj->pt) {
const enum pipe_format fmt =
st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
+ GLuint usage = default_usage(fmt);
+
stObj->pt = st_texture_create(ctx->st,
gl_target_to_pipe(stObj->base.Target),
fmt,
@@ -1428,11 +1726,7 @@ st_finalize_texture(GLcontext *ctx,
firstImage->base.Width2,
firstImage->base.Height2,
firstImage->base.Depth2,
- comp_byte,
- ( (pf_is_depth_stencil(fmt) ?
- PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
- PIPE_TEXTURE_USAGE_RENDER_TARGET) |
- PIPE_TEXTURE_USAGE_SAMPLER ));
+ usage);
if (!stObj->pt) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index b27274725f..92ddffc014 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -177,6 +177,12 @@ struct st_context *st_create_context(struct pipe_context *pipe,
ctx = _mesa_create_context(visual, shareCtx, &funcs, NULL);
+ /* XXX: need a capability bit in gallium to query if the pipe
+ * driver prefers DP4 or MUL/MAD for vertex transformation.
+ */
+ if (debug_get_bool_option("MESA_MVP_DP4", FALSE))
+ _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
+
return st_create_context_priv(ctx, pipe);
}
@@ -227,6 +233,7 @@ void st_destroy_context( struct st_context *st )
struct pipe_context *pipe = st->pipe;
struct cso_context *cso = st->cso_context;
GLcontext *ctx = st->ctx;
+ GLuint i;
/* need to unbind and destroy CSO objects before anything else */
cso_release_all(st->cso_context);
@@ -234,6 +241,12 @@ void st_destroy_context( struct st_context *st )
st_reference_fragprog(st, &st->fp, NULL);
st_reference_vertprog(st, &st->vp, NULL);
+ /* release framebuffer surfaces */
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL);
+ }
+ pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL);
+
_mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
_vbo_DestroyContext(st->ctx);
@@ -250,9 +263,10 @@ void st_destroy_context( struct st_context *st )
}
-void st_make_current(struct st_context *st,
- struct st_framebuffer *draw,
- struct st_framebuffer *read)
+GLboolean
+st_make_current(struct st_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read)
{
/* Call this periodically to detect when the user has begun using
* GL rendering from multiple threads.
@@ -261,7 +275,8 @@ void st_make_current(struct st_context *st,
if (st) {
GLboolean firstTime = st->ctx->FirstTimeCurrent;
- _mesa_make_current(st->ctx, &draw->Base, &read->Base);
+ if(!_mesa_make_current(st->ctx, &draw->Base, &read->Base))
+ return GL_FALSE;
/* Need to initialize viewport here since draw->Base->Width/Height
* will still be zero at this point.
* This could be improved, but would require rather extensive work
@@ -273,12 +288,19 @@ void st_make_current(struct st_context *st,
_mesa_set_scissor(st->ctx, 0, 0, w, h);
}
+ return GL_TRUE;
}
else {
- _mesa_make_current(NULL, NULL, NULL);
+ return _mesa_make_current(NULL, NULL, NULL);
}
}
+struct st_context *st_get_current(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ return (ctx == NULL) ? NULL : ctx->st;
+}
void st_copy_context_state(struct st_context *dst,
struct st_context *src,
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index ae8c2978bf..18adb35e87 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -45,6 +45,7 @@ struct blit_state;
struct bitmap_cache;
+/** XXX we'd like to get rid of these */
#define FRONT_STATUS_UNDEFINED 0
#define FRONT_STATUS_DIRTY 1
#define FRONT_STATUS_COPY_OF_BACK 2
@@ -111,22 +112,15 @@ struct st_context
struct gl_fragment_program *fragment_program;
} cb;
- GLuint frontbuffer_status; /**< one of FRONT_STATUS_ */
+ GLuint frontbuffer_status; /**< one of FRONT_STATUS_ (XXX to be removed) */
char vendor[100];
char renderer[100];
- /* State to be validated:
- */
- struct st_tracked_state **atoms;
- GLuint nr_atoms;
-
struct st_state_flags dirty;
GLboolean missing_textures;
- GLfloat polygon_offset_scale; /* ?? */
-
/** Mapping from VERT_RESULT_x to post-transformed vertex slot */
const GLuint *vertex_result_to_slot;
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index 225541a30b..8e036223c6 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -159,12 +159,21 @@ static GLuint fixed_types[4] = {
* Return a PIPE_FORMAT_x for the given GL datatype and size.
*/
GLuint
-st_pipe_vertex_format(GLenum type, GLuint size, GLboolean normalized)
+st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
+ GLboolean normalized)
{
assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
type == GL_FIXED);
assert(size >= 1);
assert(size <= 4);
+ assert(format == GL_RGBA || format == GL_BGRA);
+
+ if (format == GL_BGRA) {
+ /* this is an odd-ball case */
+ assert(type == GL_UNSIGNED_BYTE);
+ assert(normalized);
+ return PIPE_FORMAT_B8G8R8A8_UNORM;
+ }
if (normalized) {
switch (type) {
@@ -392,6 +401,7 @@ setup_interleaved_attribs(GLcontext *ctx,
velements[attr].src_format =
st_pipe_vertex_format(arrays[mesaAttr]->Type,
arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Format,
arrays[mesaAttr]->Normalized);
assert(velements[attr].src_format);
}
@@ -479,6 +489,7 @@ setup_non_interleaved_attribs(GLcontext *ctx,
velements[attr].src_format
= st_pipe_vertex_format(arrays[mesaAttr]->Type,
arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Format,
arrays[mesaAttr]->Normalized);
assert(velements[attr].src_format);
}
diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h
index da04fce8e2..dcfe7e1536 100644
--- a/src/mesa/state_tracker/st_draw.h
+++ b/src/mesa/state_tracker/st_draw.h
@@ -62,7 +62,8 @@ st_feedback_draw_vbo(GLcontext *ctx,
/* Internal function:
*/
extern GLuint
-st_pipe_vertex_format(GLenum type, GLuint size, GLboolean normalized);
+st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
+ GLboolean normalized);
/**
diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
index e533afd051..2712c131c0 100644
--- a/src/mesa/state_tracker/st_draw_feedback.c
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -178,6 +178,7 @@ st_feedback_draw_vbo(GLcontext *ctx,
velements[attr].src_format =
st_pipe_vertex_format(arrays[mesaAttr]->Type,
arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Format,
arrays[mesaAttr]->Normalized);
assert(velements[attr].src_format);
@@ -196,13 +197,10 @@ st_feedback_draw_vbo(GLcontext *ctx,
draw_set_vertex_elements(draw, vp->num_inputs, velements);
if (ib) {
- unsigned indexSize;
struct gl_buffer_object *bufobj = ib->obj;
- struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ unsigned indexSize;
void *map;
- index_buffer_handle = stobj->buffer;
-
switch (ib->type) {
case GL_UNSIGNED_INT:
indexSize = 4;
@@ -215,9 +213,19 @@ st_feedback_draw_vbo(GLcontext *ctx,
return;
}
- map = pipe_buffer_map(pipe->screen, index_buffer_handle,
- PIPE_BUFFER_USAGE_CPU_READ);
- draw_set_mapped_element_buffer(draw, indexSize, map);
+ if (bufobj && bufobj->Name) {
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+
+ index_buffer_handle = stobj->buffer;
+
+ map = pipe_buffer_map(pipe->screen, index_buffer_handle,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ draw_set_mapped_element_buffer(draw, indexSize, map);
+ }
+ else {
+ draw_set_mapped_element_buffer(draw, indexSize, (void *) ib->ptr);
+ }
}
else {
/* no index/element buffer */
@@ -252,7 +260,7 @@ st_feedback_draw_vbo(GLcontext *ctx,
draw_set_mapped_vertex_buffer(draw, i, NULL);
}
}
- if (ib) {
+ if (index_buffer_handle) {
pipe_buffer_unmap(pipe->screen, index_buffer_handle);
draw_set_mapped_element_buffer(draw, 0, NULL);
}
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 8f6be50774..8ed1211db6 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -138,6 +138,7 @@ void st_init_extensions(struct st_context *st)
/*
* Extensions that are supported by all Gallium drivers:
*/
+ ctx->Extensions.ARB_copy_buffer = GL_TRUE;
ctx->Extensions.ARB_multisample = GL_TRUE;
ctx->Extensions.ARB_fragment_program = GL_TRUE;
ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */
@@ -167,6 +168,9 @@ void st_init_extensions(struct st_context *st)
ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
+ ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
+
+ ctx->Extensions.APPLE_vertex_array_object = GL_TRUE;
ctx->Extensions.NV_blend_square = GL_TRUE;
ctx->Extensions.NV_texgen_reflection = GL_TRUE;
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index 9e2d60c926..b243c249e3 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -392,7 +392,7 @@ default_depth_format(struct pipe_screen *screen,
* or PIPE_TEXTURE_USAGE_SAMPLER
*/
enum pipe_format
-st_choose_format(struct pipe_context *pipe, GLint internalFormat,
+st_choose_format(struct pipe_context *pipe, GLenum internalFormat,
enum pipe_texture_target target, unsigned tex_usage)
{
struct pipe_screen *screen = pipe->screen;
@@ -594,9 +594,13 @@ st_choose_format(struct pipe_context *pipe, GLint internalFormat,
static GLboolean
-is_stencil_format(GLenum format)
+is_depth_or_stencil_format(GLenum internalFormat)
{
- switch (format) {
+ switch (internalFormat) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
case GL_STENCIL_INDEX:
case GL_STENCIL_INDEX1_EXT:
case GL_STENCIL_INDEX4_EXT:
@@ -614,10 +618,10 @@ is_stencil_format(GLenum format)
* Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces.
*/
enum pipe_format
-st_choose_renderbuffer_format(struct pipe_context *pipe, GLint internalFormat)
+st_choose_renderbuffer_format(struct pipe_context *pipe, GLenum internalFormat)
{
uint usage;
- if (is_stencil_format(internalFormat))
+ if (is_depth_or_stencil_format(internalFormat))
usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
else
usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
@@ -716,3 +720,23 @@ st_ChooseTextureFormat(GLcontext *ctx, GLint internalFormat,
return translate_gallium_format_to_mesa_format(pFormat);
}
+
+
+/**
+ * Test if a gallium format is equivalent to a GL format/type.
+ */
+GLboolean
+st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type)
+{
+ switch (pFormat) {
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ return format == GL_RGBA && type == GL_UNSIGNED_BYTE;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ return format == GL_BGRA && type == GL_UNSIGNED_BYTE;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5;
+ /* XXX more combos... */
+ default:
+ return GL_FALSE;
+ }
+}
diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h
index 3f5ac3201b..9d9e02fe9b 100644
--- a/src/mesa/state_tracker/st_format.h
+++ b/src/mesa/state_tracker/st_format.h
@@ -64,11 +64,11 @@ st_mesa_format_to_pipe_format(GLuint mesaFormat);
extern enum pipe_format
-st_choose_format(struct pipe_context *pipe, GLint internalFormat,
+st_choose_format(struct pipe_context *pipe, GLenum internalFormat,
enum pipe_texture_target target, unsigned tex_usage);
extern enum pipe_format
-st_choose_renderbuffer_format(struct pipe_context *pipe, GLint internalFormat);
+st_choose_renderbuffer_format(struct pipe_context *pipe, GLenum internalFormat);
extern const struct gl_texture_format *
@@ -76,4 +76,8 @@ st_ChooseTextureFormat(GLcontext * ctx, GLint internalFormat,
GLenum format, GLenum type);
+extern GLboolean
+st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type);
+
+
#endif /* ST_CB_TEXIMAGE_H */
diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c
index daaad65cca..7072cbe62c 100644
--- a/src/mesa/state_tracker/st_framebuffer.c
+++ b/src/mesa/state_tracker/st_framebuffer.c
@@ -58,25 +58,25 @@ st_create_framebuffer( const __GLcontextModes *visual,
_mesa_initialize_framebuffer(&stfb->Base, visual);
- {
- /* fake frontbuffer */
- /* XXX allocation should only happen in the unusual case
- it's actually needed */
- struct gl_renderbuffer *rb
- = st_new_renderbuffer_fb(colorFormat, samples);
- _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb);
- }
-
if (visual->doubleBufferMode) {
struct gl_renderbuffer *rb
- = st_new_renderbuffer_fb(colorFormat, samples);
+ = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
_mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb);
}
+ else {
+ /* Only allocate front buffer right now if we're single buffered.
+ * If double-buffered, allocate front buffer on demand later.
+ * See check_create_front_buffers().
+ */
+ struct gl_renderbuffer *rb
+ = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb);
+ }
if (depthFormat == stencilFormat && depthFormat != PIPE_FORMAT_NONE) {
/* combined depth/stencil buffer */
struct gl_renderbuffer *depthStencilRb
- = st_new_renderbuffer_fb(depthFormat, samples);
+ = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
/* note: bind RB to two attachment points */
_mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthStencilRb);
_mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, depthStencilRb);
@@ -87,34 +87,35 @@ st_create_framebuffer( const __GLcontextModes *visual,
if (visual->depthBits == 32) {
/* 32-bit depth buffer */
struct gl_renderbuffer *depthRb
- = st_new_renderbuffer_fb(depthFormat, samples);
+ = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
_mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
}
else if (visual->depthBits == 24) {
/* 24-bit depth buffer, ignore stencil bits */
struct gl_renderbuffer *depthRb
- = st_new_renderbuffer_fb(depthFormat, samples);
+ = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
_mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
}
else if (visual->depthBits > 0) {
/* 16-bit depth buffer */
struct gl_renderbuffer *depthRb
- = st_new_renderbuffer_fb(depthFormat, samples);
+ = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
_mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
}
if (visual->stencilBits > 0) {
/* 8-bit stencil */
struct gl_renderbuffer *stencilRb
- = st_new_renderbuffer_fb(stencilFormat, samples);
+ = st_new_renderbuffer_fb(stencilFormat, samples, FALSE);
_mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, stencilRb);
}
}
if (visual->accumRedBits > 0) {
/* 16-bit/channel accum */
+ /* TODO: query the pipe screen for accumulation buffer format support */
struct gl_renderbuffer *accumRb
- = st_new_renderbuffer_fb(DEFAULT_ACCUM_PIPE_FORMAT, 0); /* XXX accum isn't multisampled right? */
+ = st_new_renderbuffer_fb(PIPE_FORMAT_R16G16B16A16_SNORM, 0, TRUE);
_mesa_add_renderbuffer(&stfb->Base, BUFFER_ACCUM, accumRb);
}
@@ -293,6 +294,115 @@ st_notify_swapbuffers(struct st_framebuffer *stfb)
}
+/**
+ * Swap the front/back color buffers. Exchange the front/back pointers
+ * and update some derived state.
+ * No need to call st_notify_swapbuffers() first.
+ *
+ * For a single-buffered framebuffer, no swap occurs, but we still return
+ * the pointer(s) to the front color buffer(s).
+ *
+ * \param front_left returns pointer to front-left renderbuffer after swap
+ * \param front_right returns pointer to front-right renderbuffer after swap
+ */
+void
+st_swapbuffers(struct st_framebuffer *stfb,
+ struct pipe_surface **front_left,
+ struct pipe_surface **front_right)
+{
+ struct gl_framebuffer *fb = &stfb->Base;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx && ctx->DrawBuffer == &stfb->Base) {
+ st_flush( ctx->st,
+ PIPE_FLUSH_RENDER_CACHE |
+ PIPE_FLUSH_SWAPBUFFERS |
+ PIPE_FLUSH_FRAME,
+ NULL );
+ }
+
+ if (!fb->Visual.doubleBufferMode) {
+ /* single buffer mode - return pointers to front surfaces */
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer);
+ *front_right = strb ? strb->surface : NULL;
+ }
+ return;
+ }
+
+ /* swap left buffers */
+ if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) {
+ struct gl_renderbuffer *rbTemp;
+ rbTemp = fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer =
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer = rbTemp;
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ /* mark back buffer contents as undefined */
+ {
+ struct st_renderbuffer *back =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ back->defined = GL_FALSE;
+ }
+ }
+ else {
+ /* no front buffer, display the back buffer */
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ }
+
+ /* swap right buffers (for stereo) */
+ if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) {
+ struct gl_renderbuffer *rbTemp;
+ rbTemp = fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer;
+ fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer =
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer;
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer = rbTemp;
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer);
+ *front_right = strb->surface;
+ }
+ /* mark back buffer contents as undefined */
+ {
+ struct st_renderbuffer *back =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
+ back->defined = GL_FALSE;
+ }
+ }
+ else {
+ /* no front right buffer, display back right buffer (if exists) */
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
+ *front_right = strb ? strb->surface : NULL;
+ }
+ }
+
+ /* Update the _ColorDrawBuffers[] array and _ColorReadBuffer pointer */
+ _mesa_update_framebuffer(ctx);
+
+ /* Make sure we draw into the new back surface */
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
void *st_framebuffer_private( struct st_framebuffer *stfb )
{
return stfb->Private;
diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
index 9cc2176d5e..dc6d77825f 100644
--- a/src/mesa/state_tracker/st_gen_mipmap.c
+++ b/src/mesa/state_tracker/st_gen_mipmap.c
@@ -47,6 +47,7 @@
#include "st_program.h"
#include "st_texture.h"
#include "st_cb_texture.h"
+#include "st_inlines.h"
/**
@@ -86,7 +87,7 @@ st_render_mipmap(struct st_context *st,
assert(target != GL_TEXTURE_3D); /* not done yet */
/* check if we can render in the texture's format */
- if (!screen->is_format_supported(screen, pt->format, target,
+ if (!screen->is_format_supported(screen, pt->format, pt->target,
PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
return FALSE;
}
@@ -122,27 +123,34 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target,
struct pipe_transfer *srcTrans, *dstTrans;
const ubyte *srcData;
ubyte *dstData;
+ int srcStride, dstStride;
- srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
- PIPE_TRANSFER_READ, 0, 0,
- pt->width[srcLevel],
- pt->height[srcLevel]);
- dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
- PIPE_TRANSFER_WRITE, 0, 0,
- pt->width[dstLevel],
- pt->height[dstLevel]);
+ srcTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face,
+ srcLevel, zslice,
+ PIPE_TRANSFER_READ, 0, 0,
+ pt->width[srcLevel],
+ pt->height[srcLevel]);
+
+ dstTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face,
+ dstLevel, zslice,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ pt->width[dstLevel],
+ pt->height[dstLevel]);
srcData = (ubyte *) screen->transfer_map(screen, srcTrans);
dstData = (ubyte *) screen->transfer_map(screen, dstTrans);
+ srcStride = srcTrans->stride / srcTrans->block.size;
+ dstStride = dstTrans->stride / dstTrans->block.size;
+
_mesa_generate_mipmap_level(target, datatype, comps,
0 /*border*/,
pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
srcData,
- srcTrans->stride, /* stride in bytes */
+ srcStride, /* stride in texels */
pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
dstData,
- dstTrans->stride); /* stride in bytes */
+ dstStride); /* stride in texels */
screen->transfer_unmap(screen, srcTrans);
screen->transfer_unmap(screen, dstTrans);
diff --git a/src/mesa/state_tracker/st_inlines.h b/src/mesa/state_tracker/st_inlines.h
new file mode 100644
index 0000000000..a41cfeb96f
--- /dev/null
+++ b/src/mesa/state_tracker/st_inlines.h
@@ -0,0 +1,154 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * 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 VMWARE 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.
+ *
+ **************************************************************************/
+
+/**
+ * Functions for checking if buffers/textures are referenced when we need
+ * to read/write from/to them. Flush when needed.
+ */
+
+#ifndef ST_INLINES_H
+#define ST_INLINES_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_state.h"
+
+#include "st_context.h"
+#include "st_texture.h"
+#include "st_public.h"
+
+static INLINE struct pipe_transfer *
+st_cond_flush_get_tex_transfer(struct st_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ unsigned int zslice,
+ enum pipe_transfer_usage usage,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+
+ st_teximage_flush_before_map(st, pt, face, level, usage);
+ return screen->get_tex_transfer(screen, pt, face, level, zslice, usage,
+ x, y, w, h);
+}
+
+static INLINE struct pipe_transfer *
+st_no_flush_get_tex_transfer(struct st_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ unsigned int zslice,
+ enum pipe_transfer_usage usage,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+
+ return screen->get_tex_transfer(screen, pt, face, level,
+ zslice, usage, x, y, w, h);
+}
+
+static INLINE void *
+st_cond_flush_pipe_buffer_map(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int map_flags)
+{
+ struct pipe_context *pipe = st->pipe;
+ unsigned int referenced = pipe->is_buffer_referenced(pipe, buf);
+
+ if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
+ (map_flags & PIPE_BUFFER_USAGE_CPU_WRITE)))
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ return pipe_buffer_map(pipe->screen, buf, map_flags);
+}
+
+static INLINE void *
+st_no_flush_pipe_buffer_map(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int map_flags)
+{
+ return pipe_buffer_map(st->pipe->screen, buf, map_flags);
+}
+
+
+static INLINE void
+st_cond_flush_pipe_buffer_write(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ const void * data)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ if (pipe->is_buffer_referenced(pipe, buf))
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ pipe_buffer_write(pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_no_flush_pipe_buffer_write(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ const void * data)
+{
+ pipe_buffer_write(st->pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_cond_flush_pipe_buffer_read(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ void * data)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ if (pipe->is_buffer_referenced(pipe, buf) & PIPE_REFERENCED_FOR_WRITE)
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ pipe_buffer_read(pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_no_flush_pipe_buffer_read(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ void * data)
+{
+ pipe_buffer_read(st->pipe->screen, buf, offset, size, data);
+}
+
+#endif
+
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index ffa607dd87..43c9afccc3 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -275,8 +275,8 @@ compile_instruction(
/* swizzle (ext swizzle also depends on negation) */
{
GLuint swz[4];
- GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE &&
- inst->SrcReg[i].NegateBase != NEGATE_XYZW);
+ GLboolean extended = (inst->SrcReg[i].Negate != NEGATE_NONE &&
+ inst->SrcReg[i].Negate != NEGATE_XYZW);
for( j = 0; j < 4; j++ ) {
swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j );
if (swz[j] > SWIZZLE_W)
@@ -296,20 +296,20 @@ compile_instruction(
}
}
- if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {
+ if( inst->SrcReg[i].Negate == NEGATE_XYZW ) {
fullsrc->SrcRegister.Negate = 1;
}
- else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {
- if( inst->SrcReg[i].NegateBase & NEGATE_X ) {
+ else if( inst->SrcReg[i].Negate != NEGATE_NONE ) {
+ if( inst->SrcReg[i].Negate & NEGATE_X ) {
fullsrc->SrcRegisterExtSwz.NegateX = 1;
}
- if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {
+ if( inst->SrcReg[i].Negate & NEGATE_Y ) {
fullsrc->SrcRegisterExtSwz.NegateY = 1;
}
- if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {
+ if( inst->SrcReg[i].Negate & NEGATE_Z ) {
fullsrc->SrcRegisterExtSwz.NegateZ = 1;
}
- if( inst->SrcReg[i].NegateBase & NEGATE_W ) {
+ if( inst->SrcReg[i].Negate & NEGATE_W ) {
fullsrc->SrcRegisterExtSwz.NegateW = 1;
}
}
@@ -318,10 +318,6 @@ compile_instruction(
fullsrc->SrcRegisterExtMod.Absolute = 1;
}
- if( inst->SrcReg[i].NegateAbs ) {
- fullsrc->SrcRegisterExtMod.Negate = 1;
- }
-
if( inst->SrcReg[i].RelAddr ) {
fullsrc->SrcRegister.Indirect = 1;
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 6348e83d8a..72ca852458 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -49,26 +49,12 @@
#include "cso_cache/cso_context.h"
-#define ST_MAX_SHADER_TOKENS 4096
+#define ST_MAX_SHADER_TOKENS (8 * 1024)
#define TGSI_DEBUG 0
-/** XXX we should use the version of this from u_memory.h but including
- * that header causes symbol collisions.
- */
-static INLINE void *
-mem_dup(const void *src, uint size)
-{
- void *dup = _mesa_malloc(size);
- if (dup)
- _mesa_memcpy(dup, src, size);
- return dup;
-}
-
-
-
/**
* Translate a Mesa vertex shader into a TGSI shader.
* \param outputMapping to map vertex program output registers (VERT_RESULT_x)
@@ -84,7 +70,7 @@ st_translate_vertex_program(struct st_context *st,
const ubyte *outputSemanticIndex)
{
struct pipe_context *pipe = st->pipe;
- struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
+ struct tgsi_token *tokens;
GLuint defaultOutputMapping[VERT_RESULT_MAX];
struct pipe_shader_state vs;
GLuint attr, i;
@@ -102,6 +88,13 @@ st_translate_vertex_program(struct st_context *st,
GLbitfield input_flags[MAX_PROGRAM_INPUTS];
GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
+ tokens = (struct tgsi_token *)MALLOC(ST_MAX_SHADER_TOKENS * sizeof *tokens);
+ if(!tokens) {
+ /* FIXME: propagate error to the caller */
+ assert(0);
+ return;
+ }
+
memset(&vs, 0, sizeof(vs));
memset(input_flags, 0, sizeof(input_flags));
memset(output_flags, 0, sizeof(output_flags));
@@ -169,6 +162,14 @@ st_translate_vertex_program(struct st_context *st,
case VERT_ATTRIB_GENERIC5:
case VERT_ATTRIB_GENERIC6:
case VERT_ATTRIB_GENERIC7:
+ case VERT_ATTRIB_GENERIC8:
+ case VERT_ATTRIB_GENERIC9:
+ case VERT_ATTRIB_GENERIC10:
+ case VERT_ATTRIB_GENERIC11:
+ case VERT_ATTRIB_GENERIC12:
+ case VERT_ATTRIB_GENERIC13:
+ case VERT_ATTRIB_GENERIC14:
+ case VERT_ATTRIB_GENERIC15:
assert(attr < VERT_ATTRIB_MAX);
vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
vs_input_semantic_index[slot] = num_generic++;
@@ -289,9 +290,6 @@ st_translate_vertex_program(struct st_context *st,
}
}
- assert(vs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
-
-
if (outputMapping) {
/* find max output slot referenced to compute vs_num_outputs */
GLuint maxSlot = 0;
@@ -339,7 +337,9 @@ st_translate_vertex_program(struct st_context *st,
assert(num_tokens < ST_MAX_SHADER_TOKENS);
vs.tokens = (struct tgsi_token *)
- mem_dup(tokens, num_tokens * sizeof(tokens[0]));
+ _mesa_realloc(tokens,
+ ST_MAX_SHADER_TOKENS * sizeof *tokens,
+ num_tokens * sizeof *tokens);
stvp->num_inputs = vs_num_inputs;
stvp->state = vs; /* struct copy */
@@ -367,7 +367,7 @@ st_translate_fragment_program(struct st_context *st,
const GLuint inputMapping[])
{
struct pipe_context *pipe = st->pipe;
- struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
+ struct tgsi_token *tokens;
GLuint outputMapping[FRAG_RESULT_MAX];
GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
struct pipe_shader_state fs;
@@ -387,6 +387,13 @@ st_translate_fragment_program(struct st_context *st,
GLbitfield input_flags[MAX_PROGRAM_INPUTS];
GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
+ tokens = (struct tgsi_token *)MALLOC(ST_MAX_SHADER_TOKENS * sizeof *tokens);
+ if(!tokens) {
+ /* FIXME: propagate error to the caller */
+ assert(0);
+ return;
+ }
+
memset(&fs, 0, sizeof(fs));
memset(input_flags, 0, sizeof(input_flags));
memset(output_flags, 0, sizeof(output_flags));
@@ -484,14 +491,14 @@ st_translate_fragment_program(struct st_context *st,
/* handled above */
assert(0);
break;
- case FRAG_RESULT_COLOR:
+ default:
+ assert(attr == FRAG_RESULT_COLOR ||
+ (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
fs_output_semantic_index[fs_num_outputs] = numColors;
outputMapping[attr] = fs_num_outputs;
numColors++;
break;
- default:
- assert(0);
}
output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr];
@@ -528,7 +535,9 @@ st_translate_fragment_program(struct st_context *st,
assert(num_tokens < ST_MAX_SHADER_TOKENS);
fs.tokens = (struct tgsi_token *)
- mem_dup(tokens, num_tokens * sizeof(tokens[0]));
+ _mesa_realloc(tokens,
+ ST_MAX_SHADER_TOKENS * sizeof *tokens,
+ num_tokens * sizeof *tokens);
stfp->state = fs; /* struct copy */
stfp->driver_shader = pipe->create_fs_state(pipe, &fs);
diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h
index 030314372f..04d3a3d7c2 100644
--- a/src/mesa/state_tracker/st_public.h
+++ b/src/mesa/state_tracker/st_public.h
@@ -91,9 +91,11 @@ void *st_framebuffer_private( struct st_framebuffer *stfb );
void st_unreference_framebuffer( struct st_framebuffer *stfb );
-void st_make_current(struct st_context *st,
- struct st_framebuffer *draw,
- struct st_framebuffer *read);
+GLboolean st_make_current(struct st_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read);
+
+struct st_context *st_get_current(void);
void st_flush( struct st_context *st, uint pipeFlushFlags,
struct pipe_fence_handle **fence );
@@ -101,6 +103,10 @@ void st_finish( struct st_context *st );
void st_notify_swapbuffers(struct st_framebuffer *stfb);
+void st_swapbuffers(struct st_framebuffer *stfb,
+ struct pipe_surface **front_left,
+ struct pipe_surface **front_right);
+
int st_set_teximage(struct pipe_texture *pt, int target);
/** Redirect rendering into stfb's surface to a texture image */
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index 3f90ad502c..10faa633ea 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -30,6 +30,7 @@
#include "st_public.h"
#include "st_texture.h"
#include "st_cb_fbo.h"
+#include "st_inlines.h"
#include "main/enums.h"
#include "main/teximage.h"
#include "main/texstore.h"
@@ -78,7 +79,6 @@ st_texture_create(struct st_context *st,
GLuint width0,
GLuint height0,
GLuint depth0,
- GLuint compress_byte,
GLuint usage )
{
struct pipe_texture pt, *newtex;
@@ -101,7 +101,6 @@ st_texture_create(struct st_context *st,
pt.width[0] = width0;
pt.height[0] = height0;
pt.depth[0] = depth0;
- pt.compressed = compress_byte ? 1 : 0;
pf_get_block(format, &pt.block);
pt.tex_usage = usage;
@@ -128,8 +127,7 @@ st_texture_match_image(const struct pipe_texture *pt,
/* Check if this image's format matches the established texture's format.
*/
- if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format ||
- image->IsCompressed != pt->compressed)
+ if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format)
return GL_FALSE;
/* Test if this image's size matches what's expected in the
@@ -191,13 +189,15 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
GLuint zoffset, enum pipe_transfer_usage usage,
GLuint x, GLuint y, GLuint w, GLuint h)
{
- struct pipe_screen *screen = st->pipe->screen;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
struct pipe_texture *pt = stImage->pt;
+
DBG("%s \n", __FUNCTION__);
- stImage->transfer = screen->get_tex_transfer(screen, pt, stImage->face,
- stImage->level, zoffset,
- usage, x, y, w, h);
+ stImage->transfer = st_no_flush_get_tex_transfer(st, pt, stImage->face,
+ stImage->level, zoffset,
+ usage, x, y, w, h);
if (stImage->transfer)
return screen->transfer_map(screen, stImage->transfer);
@@ -254,13 +254,14 @@ st_surface_data(struct pipe_context *pipe,
/* Upload data for a particular image.
*/
void
-st_texture_image_data(struct pipe_context *pipe,
+st_texture_image_data(struct st_context *st,
struct pipe_texture *dst,
GLuint face,
GLuint level,
void *src,
GLuint src_row_stride, GLuint src_image_stride)
{
+ struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
GLuint depth = dst->depth[level];
GLuint i;
@@ -268,11 +269,12 @@ st_texture_image_data(struct pipe_context *pipe,
struct pipe_transfer *dst_transfer;
DBG("%s\n", __FUNCTION__);
+
for (i = 0; i < depth; i++) {
- dst_transfer = screen->get_tex_transfer(screen, dst, face, level, i,
- PIPE_TRANSFER_WRITE, 0, 0,
- dst->width[level],
- dst->height[level]);
+ dst_transfer = st_no_flush_get_tex_transfer(st, dst, face, level, i,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ dst->width[level],
+ dst->height[level]);
st_surface_data(pipe, dst_transfer,
0, 0, /* dstx, dsty */
@@ -484,3 +486,20 @@ st_release_teximage(struct st_framebuffer *stfb, uint surfIndex,
return 1;
}
+
+void
+st_teximage_flush_before_map(struct st_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ enum pipe_transfer_usage usage)
+{
+ struct pipe_context *pipe = st->pipe;
+ unsigned referenced =
+ pipe->is_texture_referenced(pipe, pt, face, level);
+
+ if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
+ usage == PIPE_TRANSFER_WRITE ||
+ usage == PIPE_TRANSFER_READ_WRITE))
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+}
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index 28c2f580f6..b9d447cb56 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -108,7 +108,6 @@ st_texture_create(struct st_context *st,
GLuint width0,
GLuint height0,
GLuint depth0,
- GLuint compress_byte,
GLuint tex_usage );
@@ -157,7 +156,7 @@ st_texture_texel_offset(const struct pipe_texture * pt,
/* Upload an image into a texture
*/
extern void
-st_texture_image_data(struct pipe_context *pipe,
+st_texture_image_data(struct st_context *st,
struct pipe_texture *dst,
GLuint face, GLuint level, void *src,
GLuint src_row_pitch, GLuint src_image_pitch);
@@ -171,5 +170,10 @@ st_texture_image_copy(struct pipe_context *pipe,
struct pipe_texture *src,
GLuint face);
-
+extern void
+st_teximage_flush_before_map(struct st_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ enum pipe_transfer_usage usage);
#endif