diff options
author | Ben Skeggs <[email protected]> | 2008-03-21 12:54:34 +1100 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2008-03-21 12:54:34 +1100 |
commit | 85108e5f8f3fd1ace813cb6eac6e82af4a2e2c7a (patch) | |
tree | 05d8ff1139fbf3d51a3123280a3a8fc0d2c18349 | |
parent | 1d9049c4df24d47446218f4032b891b817af0d00 (diff) | |
parent | cab68957c72d6f198546a250b6fe0a74732cb3ec (diff) |
Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
40 files changed, 1250 insertions, 647 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 01fe2164478..4a1a6cb79c2 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -496,7 +496,8 @@ void cso_restore_vertex_shader(struct cso_context *ctx) void cso_set_framebuffer(struct cso_context *ctx, const struct pipe_framebuffer_state *fb) { - if (memcmp(&ctx->fb, fb, sizeof(*fb))) { + /* XXX this memcmp() fails to detect buffer size changes */ + if (1/*memcmp(&ctx->fb, fb, sizeof(*fb))*/) { ctx->fb = *fb; ctx->pipe->set_framebuffer_state(ctx->pipe, fb); } diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c index bd3a0221eaa..c51e9e6a692 100644 --- a/src/gallium/auxiliary/util/p_debug.c +++ b/src/gallium/auxiliary/util/p_debug.c @@ -85,6 +85,22 @@ void debug_printf(const char *format, ...) } +void debug_print_blob( const char *name, + const void *blob, + unsigned size ) +{ + const unsigned *ublob = (const unsigned *)blob; + unsigned i; + + debug_printf("%s (%d dwords%s)\n", name, size/4, + size%4 ? "... plus a few bytes" : ""); + + for (i = 0; i < size/4; i++) { + debug_printf("%d:\t%08x\n", i, ublob[i]); + } +} + + /* TODO: implement a debug_abort that calls EngBugCheckEx on WIN32 */ @@ -240,3 +256,5 @@ debug_dump_flags(const struct debug_named_value *names, return output; } + + diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index d05dae3af8f..28a404fd01f 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -61,6 +61,9 @@ struct blit_state /*struct pipe_viewport_state viewport;*/ struct pipe_sampler_state *vs; struct pipe_sampler_state *fs; + + struct pipe_buffer *vbuf; /**< quad vertices */ + float vertices[4][2][4]; /**< vertex/texcoords for quad */ }; @@ -72,6 +75,7 @@ struct blit_state * util_create_blit(struct pipe_context *pipe, struct cso_context *cso) { struct blit_state *ctx; + uint i; ctx = CALLOC_STRUCT(blit_state); if (!ctx) @@ -132,6 +136,24 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) /* fragment shader */ ctx->fs = util_make_fragment_tex_shader(pipe); + ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys, + 32, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(ctx->vertices)); + if (!ctx->vbuf) { + FREE(ctx); + ctx->pipe->delete_fs_state(ctx->pipe, ctx->fs); + ctx->pipe->delete_vs_state(ctx->pipe, ctx->vs); + return NULL; + } + + /* init vertex data that doesn't change */ + for (i = 0; i < 4; i++) { + ctx->vertices[i][0][3] = 1.0f; /* w */ + ctx->vertices[i][1][2] = 0.0f; /* r */ + ctx->vertices[i][1][3] = 1.0f; /* q */ + } + return ctx; } @@ -147,11 +169,56 @@ util_destroy_blit(struct blit_state *ctx) pipe->delete_vs_state(pipe, ctx->vs); pipe->delete_fs_state(pipe, ctx->fs); + pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf); + FREE(ctx); } /** + * Setup vertex data for the textured quad we'll draw. + * Note: y=0=top + */ +static void +setup_vertex_data(struct blit_state *ctx, + float x0, float y0, float x1, float y1, float z) +{ + void *buf; + + ctx->vertices[0][0][0] = x0; + ctx->vertices[0][0][1] = y0; + ctx->vertices[0][0][2] = z; + ctx->vertices[0][1][0] = 0.0f; /*s*/ + ctx->vertices[0][1][1] = 0.0f; /*t*/ + + ctx->vertices[1][0][0] = x1; + ctx->vertices[1][0][1] = y0; + ctx->vertices[1][0][2] = z; + ctx->vertices[1][1][0] = 1.0f; /*s*/ + ctx->vertices[1][1][1] = 0.0f; /*t*/ + + ctx->vertices[2][0][0] = x1; + ctx->vertices[2][0][1] = y1; + ctx->vertices[2][0][2] = z; + ctx->vertices[2][1][0] = 1.0f; + ctx->vertices[2][1][1] = 1.0f; + + ctx->vertices[3][0][0] = x0; + ctx->vertices[3][0][1] = y1; + ctx->vertices[3][0][2] = z; + ctx->vertices[3][1][0] = 0.0f; + ctx->vertices[3][1][1] = 1.0f; + + buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); + + memcpy(buf, ctx->vertices, sizeof(ctx->vertices)); + + ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf); +} + + +/** * Copy pixel block from src surface to dst surface. * Overlapping regions are acceptable. * XXX need some control over blitting Z and/or stencil. @@ -249,16 +316,21 @@ util_blit_pixels(struct blit_state *ctx, /* drawing dest */ memset(&fb, 0, sizeof(fb)); + fb.width = dst->width; + fb.height = dst->height; fb.num_cbufs = 1; fb.cbufs[0] = dst; cso_set_framebuffer(ctx->cso, &fb); /* draw quad */ - util_draw_texquad(pipe, - (float)dstX0, - (float)dstY0, - (float)dstX1, - (float)dstY1, z); + setup_vertex_data(ctx, + (float) dstX0, (float) dstY0, + (float) dstX1, (float) dstY1, z); + + util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ /* restore state we changed */ cso_restore_blend(ctx->cso); diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c index 79a69de633d..37e85336091 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.c +++ b/src/gallium/auxiliary/util/u_draw_quad.c @@ -34,15 +34,51 @@ /** + * Draw a simple vertex buffer / primitive. + * Limited to float[4] vertex attribs, tightly packed. + */ +void +util_draw_vertex_buffer(struct pipe_context *pipe, + struct pipe_buffer *vbuf, + uint prim_type, + uint num_verts, + uint num_attribs) +{ + struct pipe_vertex_buffer vbuffer; + struct pipe_vertex_element velement; + uint i; + + /* tell pipe about the vertex buffer */ + vbuffer.buffer = vbuf; + vbuffer.pitch = num_attribs * 4 * sizeof(float); /* vertex size */ + vbuffer.buffer_offset = 0; + pipe->set_vertex_buffer(pipe, 0, &vbuffer); + + /* tell pipe about the vertex attributes */ + for (i = 0; i < num_attribs; i++) { + velement.src_offset = i * 4 * sizeof(float); + velement.vertex_buffer_index = 0; + velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + velement.nr_components = 4; + pipe->set_vertex_element(pipe, i, &velement); + } + + /* draw */ + pipe->draw_arrays(pipe, prim_type, 0, num_verts); +} + + + +/** * Draw screen-aligned textured quad. + * Note: this function allocs/destroys a vertex buffer and isn't especially + * efficient. */ void util_draw_texquad(struct pipe_context *pipe, float x0, float y0, float x1, float y1, float z) { struct pipe_buffer *vbuf; - struct pipe_vertex_buffer vbuffer; - struct pipe_vertex_element velement; uint numAttribs = 2, vertexBytes, i, j; float *v; @@ -89,24 +125,7 @@ util_draw_texquad(struct pipe_context *pipe, pipe->winsys->buffer_unmap(pipe->winsys, vbuf); - /* tell pipe about the vertex buffer */ - vbuffer.buffer = vbuf; - vbuffer.pitch = numAttribs * 4 * sizeof(float); /* vertex size */ - vbuffer.buffer_offset = 0; - pipe->set_vertex_buffer(pipe, 0, &vbuffer); - - /* tell pipe about the vertex attributes */ - for (i = 0; i < numAttribs; i++) { - velement.src_offset = i * 4 * sizeof(float); - velement.vertex_buffer_index = 0; - velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - velement.nr_components = 4; - pipe->set_vertex_element(pipe, i, &velement); - } - - /* draw */ - pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4); + util_draw_vertex_buffer(pipe, vbuf, PIPE_PRIM_TRIANGLE_FAN, 4, 2); - /* XXX: do one-time */ pipe_buffer_reference(pipe->winsys, &vbuf, NULL); } diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h index a97f55d2efd..5b6539a99ca 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.h +++ b/src/gallium/auxiliary/util/u_draw_quad.h @@ -29,9 +29,25 @@ #define U_DRAWQUAD_H +#ifdef __cplusplus +extern "C" { +#endif + + +extern void +util_draw_vertex_buffer(struct pipe_context *pipe, + struct pipe_buffer *vbuf, + uint num_attribs, uint num_verts, uint prim_type); + + extern void util_draw_texquad(struct pipe_context *pipe, float x0, float y0, float x1, float y1, float z); +#ifdef __cplusplus +} +#endif + + #endif diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index 028b180a777..cf02f00b1b7 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -64,6 +64,9 @@ struct gen_mipmap_state /*struct pipe_viewport_state viewport;*/ struct pipe_sampler_state *vs; struct pipe_sampler_state *fs; + + struct pipe_buffer *vbuf; /**< quad vertices */ + float vertices[4][2][4]; /**< vertex/texcoords for quad */ }; @@ -683,6 +686,7 @@ util_create_gen_mipmap(struct pipe_context *pipe, struct cso_context *cso) { struct gen_mipmap_state *ctx; + uint i; ctx = CALLOC_STRUCT(gen_mipmap_state); if (!ctx) @@ -744,10 +748,62 @@ util_create_gen_mipmap(struct pipe_context *pipe, /* fragment shader */ ctx->fs = util_make_fragment_tex_shader(pipe); + ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys, + 32, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(ctx->vertices)); + if (!ctx->vbuf) { + FREE(ctx); + return NULL; + } + + /* vertex data that doesn't change */ + for (i = 0; i < 4; i++) { + ctx->vertices[i][0][2] = 0.0f; /* z */ + ctx->vertices[i][0][3] = 1.0f; /* w */ + ctx->vertices[i][1][2] = 0.0f; /* r */ + ctx->vertices[i][1][3] = 1.0f; /* q */ + } + return ctx; } +static void +set_vertex_data(struct gen_mipmap_state *ctx, float width, float height) +{ + void *buf; + + ctx->vertices[0][0][0] = 0.0f; /*x*/ + ctx->vertices[0][0][1] = 0.0f; /*y*/ + ctx->vertices[0][1][0] = 0.0f; /*s*/ + ctx->vertices[0][1][1] = 0.0f; /*t*/ + + ctx->vertices[1][0][0] = width; /*x*/ + ctx->vertices[1][0][1] = 0.0f; /*y*/ + ctx->vertices[1][1][0] = 1.0f; /*s*/ + ctx->vertices[1][1][1] = 0.0f; /*t*/ + + ctx->vertices[2][0][0] = width; + ctx->vertices[2][0][1] = height; + ctx->vertices[2][1][0] = 1.0f; + ctx->vertices[2][1][1] = 1.0f; + + ctx->vertices[3][0][0] = 0.0f; + ctx->vertices[3][0][1] = height; + ctx->vertices[3][1][0] = 0.0f; + ctx->vertices[3][1][1] = 1.0f; + + buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); + + memcpy(buf, ctx->vertices, sizeof(ctx->vertices)); + + ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf); +} + + + /** * Destroy a mipmap generation context */ @@ -759,6 +815,8 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx) pipe->delete_vs_state(pipe, ctx->vs); pipe->delete_fs_state(pipe, ctx->fs); + pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf); + FREE(ctx); } @@ -843,6 +901,8 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, * Setup framebuffer / dest surface */ fb.cbufs[0] = screen->get_tex_surface(screen, pt, face, dstLevel, zslice); + fb.width = pt->width[dstLevel]; + fb.height = pt->height[dstLevel]; cso_set_framebuffer(ctx->cso, &fb); /* @@ -863,12 +923,13 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, pipe->set_sampler_textures(pipe, 1, &pt); /* quad coords in window coords (bypassing clipping, viewport mapping) */ - util_draw_texquad(pipe, - 0.0F, 0.0F, /* x0, y0 */ - (float) pt->width[dstLevel], /* x1 */ - (float) pt->height[dstLevel], /* y1 */ - 0.0F); /* z */ - + set_vertex_data(ctx, + (float) pt->width[dstLevel], + (float) pt->height[dstLevel]); + util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ pipe->flush(pipe, PIPE_FLUSH_WAIT); diff --git a/src/gallium/auxiliary/util/u_handle_table.c b/src/gallium/auxiliary/util/u_handle_table.c index 8b0f7fca4b1..5a731a6b963 100644 --- a/src/gallium/auxiliary/util/u_handle_table.c +++ b/src/gallium/auxiliary/util/u_handle_table.c @@ -171,8 +171,7 @@ handle_table_set(struct handle_table *ht, assert(ht); assert(handle > 0); - assert(handle <= ht->size); - if(!handle || handle > ht->size) + if(!handle) return 0; assert(object); diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index 88e2ab05bd0..d230ddfbebc 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -68,7 +68,7 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, uint ti, i; struct pipe_shader_state shader; - tokens = (struct tgsi_token *) malloc(maxTokens * sizeof(tokens[0])); + tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0])); /* shader header */ @@ -84,16 +84,15 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, /* declare inputs */ for (i = 0; i < num_attribs; i++) { - decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; - /* + decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION; - decl.Semantic.SemanticIndex = 0; - */ + decl.Semantic.SemanticName = semantic_names[i]; + decl.Semantic.SemanticIndex = semantic_indexes[i]; + decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = 0; + decl.u.DeclarationRange.Last = i; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, @@ -102,19 +101,17 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, /* declare outputs */ for (i = 0; i < num_attribs; i++) { - decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_OUTPUT; decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = semantic_names[i]; decl.Semantic.SemanticIndex = semantic_indexes[i]; decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = 0; + decl.u.DeclarationRange.Last = i; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, maxTokens - ti); - } /* emit MOV instructions */ @@ -173,7 +170,7 @@ util_make_fragment_tex_shader(struct pipe_context *pipe) uint ti; struct pipe_shader_state shader; - tokens = (struct tgsi_token *) malloc(maxTokens * sizeof(tokens[0])); + tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0])); /* shader header */ @@ -261,3 +258,98 @@ util_make_fragment_tex_shader(struct pipe_context *pipe) return pipe->create_fs_state(pipe, &shader); } + + + + +/** + * Make simple fragment color pass-through shader. + */ +void * +util_make_fragment_passthrough_shader(struct pipe_context *pipe) +{ + uint maxTokens = 40; + struct tgsi_token *tokens; + struct tgsi_header *header; + struct tgsi_processor *processor; + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + const uint procType = TGSI_PROCESSOR_FRAGMENT; + uint ti; + struct pipe_shader_state shader; + + tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0])); + + /* shader header + */ + *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); + + header = (struct tgsi_header *) &tokens[1]; + *header = tgsi_build_header(); + + processor = (struct tgsi_processor *) &tokens[2]; + *processor = tgsi_build_processor( procType, header ); + + ti = 3; + + /* declare input */ + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_INPUT; + decl.Declaration.Semantic = 1; + decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; + decl.Semantic.SemanticIndex = 0; + decl.u.DeclarationRange.First = + decl.u.DeclarationRange.Last = 0; + ti += tgsi_build_full_declaration(&decl, + &tokens[ti], + header, + maxTokens - ti); + + /* declare output */ + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_OUTPUT; + decl.Declaration.Semantic = 1; + decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; + decl.Semantic.SemanticIndex = 0; + decl.u.DeclarationRange.First = + decl.u.DeclarationRange.Last = 0; + ti += tgsi_build_full_declaration(&decl, + &tokens[ti], + header, + maxTokens - ti); + + + /* MOVE out[0], in[0]; */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_MOV; + inst.Instruction.NumDstRegs = 1; + inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; + inst.FullDstRegisters[0].DstRegister.Index = 0; + inst.Instruction.NumSrcRegs = 1; + inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; + inst.FullSrcRegisters[0].SrcRegister.Index = 0; + ti += tgsi_build_full_instruction(&inst, + &tokens[ti], + header, + maxTokens - ti ); + + /* END instruction */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_END; + inst.Instruction.NumDstRegs = 0; + inst.Instruction.NumSrcRegs = 0; + ti += tgsi_build_full_instruction(&inst, + &tokens[ti], + header, + maxTokens - ti ); + + assert(ti < maxTokens); + +#if 0 /*debug*/ + tgsi_dump(tokens, 0); +#endif + + shader.tokens = tokens; + return pipe->create_fs_state(pipe, &shader); +} + diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h index 3ef4f288018..ca219a092c7 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.h +++ b/src/gallium/auxiliary/util/u_simple_shaders.h @@ -36,6 +36,11 @@ struct pipe_context; +#ifdef __cplusplus +extern "C" { +#endif + + extern void * util_make_vertex_passthrough_shader(struct pipe_context *pipe, uint num_attribs, @@ -47,6 +52,13 @@ extern void * util_make_fragment_tex_shader(struct pipe_context *pipe); +extern void * +util_make_fragment_passthrough_shader(struct pipe_context *pipe); + + +#ifdef __cplusplus +} #endif +#endif diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h index fe93fd8e1a2..d59e4f7036e 100644 --- a/src/gallium/drivers/cell/common.h +++ b/src/gallium/drivers/cell/common.h @@ -115,6 +115,16 @@ struct cell_command_depth_stencil_alpha_test { /** + * Upload code to perform framebuffer blend operation + */ +struct cell_command_blend { + uint64_t base; /**< Effective address of code start. */ + unsigned size; /**< Size in bytes of test code. */ + unsigned read_fb; /**< Flag: should framebuffer be read? */ +}; + + +/** * Tell SPUs about the framebuffer size, location */ struct cell_command_framebuffer diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index c880760e4bd..86fcdcff1f6 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -54,14 +54,19 @@ cell_create_blend_state(struct pipe_context *pipe, static void -cell_bind_blend_state(struct pipe_context *pipe, void *blend) +cell_bind_blend_state(struct pipe_context *pipe, void *state) { struct cell_context *cell = cell_context(pipe); + struct cell_blend_state *blend = (struct cell_blend_state *) state; + draw_flush(cell->draw); - cell->blend = (const struct cell_blend_state *)blend; + if ((blend != NULL) && (blend->code.store == NULL)) { + cell_generate_alpha_blend(blend, &cell->blend_color); + } + cell->blend = blend; cell->dirty |= CELL_NEW_BLEND; } @@ -70,7 +75,7 @@ static void cell_delete_blend_state(struct pipe_context *pipe, void *blend) { struct cell_blend_state *cb = (struct cell_blend_state *) blend; - + spe_release_func(& cb->code); FREE(cb); } diff --git a/src/gallium/drivers/cell/ppu/cell_state_derived.c b/src/gallium/drivers/cell/ppu/cell_state_derived.c index 5c240a55c0b..5480534ad90 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_derived.c +++ b/src/gallium/drivers/cell/ppu/cell_state_derived.c @@ -141,17 +141,8 @@ calculate_vertex_layout( struct cell_context *cell ) static void compute_cliprect(struct cell_context *sp) { - unsigned surfWidth, surfHeight; - - if (sp->framebuffer.num_cbufs > 0) { - surfWidth = sp->framebuffer.cbufs[0]->width; - surfHeight = sp->framebuffer.cbufs[0]->height; - } - else { - /* no surface? */ - surfWidth = sp->scissor.maxx; - surfHeight = sp->scissor.maxy; - } + uint surfWidth = sp->framebuffer.width; + uint surfHeight = sp->framebuffer.height; if (sp->rasterizer->scissor) { /* clip to scissor rect */ diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index 4d589bcdbf9..5709b48f129 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -60,14 +60,25 @@ cell_emit_state(struct cell_context *cell) fb->color_format = cbuf->format; fb->depth_start = cell->zsbuf_map; fb->depth_format = zbuf ? zbuf->format : PIPE_FORMAT_NONE; - fb->width = cell->framebuffer.cbufs[0]->width; - fb->height = cell->framebuffer.cbufs[0]->height; + fb->width = cell->framebuffer.width; + fb->height = cell->framebuffer.height; } if (cell->dirty & CELL_NEW_BLEND) { - emit_state_cmd(cell, CELL_CMD_STATE_BLEND, - cell->blend, - sizeof(struct pipe_blend_state)); + struct cell_command_blend blend; + + if (cell->blend != NULL) { + blend.base = (intptr_t) cell->blend->code.store; + blend.size = (char *) cell->blend->code.csr + - (char *) cell->blend->code.store; + blend.read_fb = TRUE; + } else { + blend.base = 0; + blend.size = 0; + blend.read_fb = FALSE; + } + + emit_state_cmd(cell, CELL_CMD_STATE_BLEND, &blend, sizeof(blend)); } if (cell->dirty & CELL_NEW_DEPTH_STENCIL) { diff --git a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c index 9c479684596..988c251e205 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c @@ -669,7 +669,7 @@ emit_alpha_factor_calculation(struct spe_function *f, /** - * \note Emits a maximum of 5 instructions + * \note Emits a maximum of 6 instructions */ static void emit_color_factor_calculation(struct spe_function *f, @@ -864,7 +864,11 @@ emit_blend_calculation(struct spe_function *f, spe_il(f, src, 0); } else if (dF == PIPE_BLENDFACTOR_ONE) { spe_or(f, src, dst, dst); + } else { + spe_fm(f, src, dst, dst_factor); } + } else if (dF == PIPE_BLENDFACTOR_ZERO) { + spe_fm(f, src, src, src_factor); } else { spe_fm(f, tmp, dst, dst_factor); spe_fma(f, src, src, src_factor, tmp); @@ -884,7 +888,11 @@ emit_blend_calculation(struct spe_function *f, } else if (dF == PIPE_BLENDFACTOR_ONE) { spe_il(f, tmp, 0); spe_fs(f, src, tmp, dst); + } else { + spe_fm(f, src, dst, dst_factor); } + } else if (dF == PIPE_BLENDFACTOR_ZERO) { + spe_fm(f, src, src, src_factor); } else { spe_fm(f, tmp, dst, dst_factor); spe_fms(f, src, src, src_factor, tmp); @@ -904,7 +912,11 @@ emit_blend_calculation(struct spe_function *f, spe_il(f, src, 0); } else if (dF == PIPE_BLENDFACTOR_ONE) { spe_or(f, src, dst, dst); + } else { + spe_fm(f, src, dst, dst_factor); } + } else if (dF == PIPE_BLENDFACTOR_ZERO) { + spe_fm(f, src, src, src_factor); } else { spe_fm(f, tmp, src, src_factor); spe_fms(f, src, src, dst_factor, tmp); @@ -913,12 +925,12 @@ emit_blend_calculation(struct spe_function *f, case PIPE_BLEND_MIN: spe_cgt(f, tmp, src, dst); - spe_selb(f, src, dst, src, tmp); + spe_selb(f, src, src, dst, tmp); break; case PIPE_BLEND_MAX: spe_cgt(f, tmp, src, dst); - spe_selb(f, src, src, dst, tmp); + spe_selb(f, src, dst, src, tmp); break; default: @@ -940,9 +952,9 @@ cell_generate_alpha_blend(struct cell_blend_state *cb, struct spe_function *const f = &cb->code; /* This code generates a maximum of 3 (source alpha factor) - * + 3 (destination alpha factor) + (3 * 5) (source color factor) - * + (3 * 5) (destination color factor) + (4 * 2) (blend equation) - * + 4 (fragment mask) + 1 (return) = 49 instlructions. Round up to 64 to + * + 3 (destination alpha factor) + (3 * 6) (source color factor) + * + (3 * 6) (destination color factor) + (4 * 2) (blend equation) + * + 4 (fragment mask) + 1 (return) = 55 instlructions. Round up to 64 to * make it a happy power-of-two. */ spe_init_func(f, 4 * 64); @@ -984,16 +996,57 @@ cell_generate_alpha_blend(struct cell_blend_state *cb, && (b->alpha_func != PIPE_BLEND_MAX); - sF[0] = b->rgb_src_factor; - sF[1] = sF[0]; - sF[2] = sF[0]; - sF[3] = (b->alpha_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) - ? PIPE_BLENDFACTOR_ONE : b->alpha_src_factor; + if (b->blend_enable) { + sF[0] = b->rgb_src_factor; + sF[1] = sF[0]; + sF[2] = sF[0]; + switch (b->alpha_src_factor & 0x0f) { + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: + sF[3] = PIPE_BLENDFACTOR_ONE; + break; + case PIPE_BLENDFACTOR_SRC_COLOR: + case PIPE_BLENDFACTOR_DST_COLOR: + case PIPE_BLENDFACTOR_CONST_COLOR: + case PIPE_BLENDFACTOR_SRC1_COLOR: + sF[3] = b->alpha_src_factor + 1; + break; + default: + sF[3] = b->alpha_src_factor; + } - dF[0] = b->rgb_dst_factor; - dF[1] = dF[0]; - dF[2] = dF[0]; - dF[3] = b->rgb_dst_factor; + dF[0] = b->rgb_dst_factor; + dF[1] = dF[0]; + dF[2] = dF[0]; + switch (b->alpha_dst_factor & 0x0f) { + case PIPE_BLENDFACTOR_SRC_COLOR: + case PIPE_BLENDFACTOR_DST_COLOR: + case PIPE_BLENDFACTOR_CONST_COLOR: + case PIPE_BLENDFACTOR_SRC1_COLOR: + dF[3] = b->alpha_dst_factor + 1; + break; + default: + dF[3] = b->alpha_dst_factor; + } + + func[0] = b->rgb_func; + func[1] = func[0]; + func[2] = func[0]; + func[3] = b->alpha_func; + } else { + sF[0] = PIPE_BLENDFACTOR_ONE; + sF[1] = PIPE_BLENDFACTOR_ONE; + sF[2] = PIPE_BLENDFACTOR_ONE; + sF[3] = PIPE_BLENDFACTOR_ONE; + dF[0] = PIPE_BLENDFACTOR_ZERO; + dF[1] = PIPE_BLENDFACTOR_ZERO; + dF[2] = PIPE_BLENDFACTOR_ZERO; + dF[3] = PIPE_BLENDFACTOR_ZERO; + + func[0] = PIPE_BLEND_ADD; + func[1] = PIPE_BLEND_ADD; + func[2] = PIPE_BLEND_ADD; + func[3] = PIPE_BLEND_ADD; + } /* If alpha writing is enabled and the alpha blend mode requires use of @@ -1054,11 +1107,6 @@ cell_generate_alpha_blend(struct cell_blend_state *cb, - func[0] = b->rgb_func; - func[1] = func[0]; - func[2] = func[0]; - func[3] = b->alpha_func; - for (i = 0; i < 4; ++i) { if ((b->colormask & (1U << i)) != 0) { emit_blend_calculation(f, @@ -1072,4 +1120,28 @@ cell_generate_alpha_blend(struct cell_blend_state *cb, } spe_bi(f, 0, 0, 0); + +#if 0 + { + const uint32_t *p = f->store; + + printf("# %u instructions\n", f->csr - f->store); + printf("# blend (%sabled)\n", + (cb->base.blend_enable) ? "en" : "dis"); + printf("# RGB func / sf / df: %u %u %u\n", + cb->base.rgb_func, + cb->base.rgb_src_factor, + cb->base.rgb_dst_factor); + printf("# ALP func / sf / df: %u %u %u\n", + cb->base.alpha_func, + cb->base.alpha_src_factor, + cb->base.alpha_dst_factor); + + printf("\t.text\n"); + for (/* empty */; p < f->csr; p++) { + printf("\t.long\t0x%04x\n", *p); + } + fflush(stdout); + } +#endif } diff --git a/src/gallium/drivers/cell/spu/Makefile b/src/gallium/drivers/cell/spu/Makefile index 115ca8cd901..8e83610790e 100644 --- a/src/gallium/drivers/cell/spu/Makefile +++ b/src/gallium/drivers/cell/spu/Makefile @@ -17,7 +17,6 @@ PROG_SPU_EMBED_O = $(PROG)_spu-embed.o SOURCES = \ spu_main.c \ - spu_blend.c \ spu_dcache.c \ spu_per_fragment_op.c \ spu_render.c \ diff --git a/src/gallium/drivers/cell/spu/spu_blend.c b/src/gallium/drivers/cell/spu/spu_blend.c deleted file mode 100644 index 23ec0eeb451..00000000000 --- a/src/gallium/drivers/cell/spu/spu_blend.c +++ /dev/null @@ -1,62 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -#include "spu_main.h" -#include "spu_blend.h" -#include "spu_colorpack.h" - - -void -blend_quad(uint itx, uint ity, vector float colors[4]) -{ - /* simple SRC_ALPHA, ONE_MINUS_SRC_ALPHA blending */ - vector float fbc00 = spu_unpack_color(spu.ctile.ui[ity][itx]); - vector float fbc01 = spu_unpack_color(spu.ctile.ui[ity][itx+1]); - vector float fbc10 = spu_unpack_color(spu.ctile.ui[ity+1][itx]); - vector float fbc11 = spu_unpack_color(spu.ctile.ui[ity+1][itx+1]); - - vector float alpha00 = spu_splats(spu_extract(colors[0], 3)); - vector float alpha01 = spu_splats(spu_extract(colors[1], 3)); - vector float alpha10 = spu_splats(spu_extract(colors[2], 3)); - vector float alpha11 = spu_splats(spu_extract(colors[3], 3)); - - vector float one_minus_alpha00 = spu_sub(spu_splats(1.0f), alpha00); - vector float one_minus_alpha01 = spu_sub(spu_splats(1.0f), alpha01); - vector float one_minus_alpha10 = spu_sub(spu_splats(1.0f), alpha10); - vector float one_minus_alpha11 = spu_sub(spu_splats(1.0f), alpha11); - - colors[0] = spu_add(spu_mul(colors[0], alpha00), - spu_mul(fbc00, one_minus_alpha00)); - colors[1] = spu_add(spu_mul(colors[1], alpha01), - spu_mul(fbc01, one_minus_alpha01)); - colors[2] = spu_add(spu_mul(colors[2], alpha10), - spu_mul(fbc10, one_minus_alpha10)); - colors[3] = spu_add(spu_mul(colors[3], alpha11), - spu_mul(fbc11, one_minus_alpha11)); -} - diff --git a/src/gallium/drivers/cell/spu/spu_main.c b/src/gallium/drivers/cell/spu/spu_main.c index 937962285d0..41bebf5362b 100644 --- a/src/gallium/drivers/cell/spu/spu_main.c +++ b/src/gallium/drivers/cell/spu/spu_main.c @@ -61,6 +61,25 @@ static unsigned char attribute_fetch_code_buffer[136 * PIPE_ATTRIB_MAX] static unsigned char depth_stencil_code_buffer[4 * 64] ALIGN16_ATTRIB; +static unsigned char fb_blend_code_buffer[4 * 64] + ALIGN16_ATTRIB; + +static struct spu_blend_results +default_blend(qword frag_r, qword frag_g, qword frag_b, qword frag_a, + qword pixel_r, qword pixel_g, qword pixel_b, qword pixel_a, + qword frag_mask) +{ + struct spu_blend_results result; + + result.r = si_selb(pixel_r, frag_r, frag_mask); + result.g = si_selb(pixel_g, frag_g, frag_mask); + result.b = si_selb(pixel_b, frag_b, frag_mask); + result.a = si_selb(pixel_a, frag_a, frag_mask); + + return result; +} + + /** * Tell the PPU that this SPU has finished copying a buffer to * local store and that it may be reused by the PPU. @@ -246,14 +265,31 @@ cmd_state_framebuffer(const struct cell_command_framebuffer *cmd) static void -cmd_state_blend(const struct pipe_blend_state *state) +cmd_state_blend(const struct cell_command_blend *state) { if (Debug) printf("SPU %u: BLEND: enabled %d\n", spu.init.id, - state->blend_enable); + (state->size != 0)); + + ASSERT_ALIGN16(state->base); - memcpy(&spu.blend, state, sizeof(*state)); + if (state->size != 0) { + mfc_get(fb_blend_code_buffer, + (unsigned int) state->base, /* src */ + ROUNDUP16(state->size), + TAG_BATCH_BUFFER, + 0, /* tid */ + 0 /* rid */); + wait_on_mask(1 << TAG_BATCH_BUFFER); + spu.blend = (blend_func) fb_blend_code_buffer; + spu.read_fb = state->read_fb; + } else { + /* If there is no code, use the default; + */ + spu.blend = default_blend; + spu.read_fb = FALSE; + } } @@ -441,9 +477,8 @@ cmd_batch(uint opcode) pos += 1; break; case CELL_CMD_STATE_BLEND: - cmd_state_blend((struct pipe_blend_state *) - &buffer[pos+1]); - pos += (1 + ROUNDUP8(sizeof(struct pipe_blend_state)) / 8); + cmd_state_blend((struct cell_command_blend *) &buffer[pos+1]); + pos += (1 + ROUNDUP8(sizeof(struct cell_command_blend)) / 8); break; case CELL_CMD_STATE_DEPTH_STENCIL: cmd_state_depth_stencil((struct cell_command_depth_stencil_alpha_test *) @@ -587,6 +622,9 @@ one_time_init(void) memset(spu.ctile_status, TILE_STATUS_DEFINED, sizeof(spu.ctile_status)); memset(spu.ztile_status, TILE_STATUS_DEFINED, sizeof(spu.ztile_status)); invalidate_tex_cache(); + + spu.blend = default_blend; + spu.read_fb = FALSE; } diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h index 444e2186452..56d0968676b 100644 --- a/src/gallium/drivers/cell/spu/spu_main.h +++ b/src/gallium/drivers/cell/spu/spu_main.h @@ -67,6 +67,18 @@ typedef struct spu_frag_test_results (*frag_test_func)(qword frag_mask, qword frag_alpha, qword facing); +struct spu_blend_results { + qword r; + qword g; + qword b; + qword a; +}; + +typedef struct spu_blend_results (*blend_func)( + qword frag_r, qword frag_g, qword frag_b, qword frag_a, + qword pixel_r, qword pixel_g, qword pixel_b, qword pixel_a, + qword frag_mask); + struct spu_framebuffer { void *color_start; /**< addr of color surface in main memory */ void *depth_start; /**< addr of depth surface in main memory */ @@ -93,7 +105,10 @@ struct spu_global boolean read_depth; boolean read_stencil; frag_test_func frag_test; - struct pipe_blend_state blend; + + boolean read_fb; + blend_func blend; + struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS]; struct cell_command_texture texture; diff --git a/src/gallium/drivers/cell/spu/spu_tri.c b/src/gallium/drivers/cell/spu/spu_tri.c index 81823f24633..c4272d6e93c 100644 --- a/src/gallium/drivers/cell/spu/spu_tri.c +++ b/src/gallium/drivers/cell/spu/spu_tri.c @@ -29,10 +29,10 @@ * Triangle rendering within a tile. */ +#include <transpose_matrix4x4.h> #include "pipe/p_compiler.h" #include "pipe/p_format.h" #include "pipe/p_util.h" -#include "spu_blend.h" #include "spu_colorpack.h" #include "spu_main.h" #include "spu_texture.h" @@ -261,6 +261,9 @@ do_depth_test(int x, int y, mask_t quadmask) float4 zvals; mask_t mask; + if (spu.fb.depth_format == PIPE_FORMAT_NONE) + return quadmask; + zvals.v = eval_z((float) x, (float) y); mask = (mask_t) spu_do_depth_stencil(x - setup.cliprect_minx, @@ -326,27 +329,45 @@ emit_quad( int x, int y, mask_t mask ) eval_coeff(1, (float) x, (float) y, colors); } -#if 1 - if (spu.blend.blend_enable) - blend_quad(ix % TILE_SIZE, iy % TILE_SIZE, colors); -#endif - if (spu_extract(mask, 0)) - spu.ctile.ui[iy][ix] = spu_pack_color_shuffle(colors[0], shuffle); - if (spu_extract(mask, 1)) - spu.ctile.ui[iy][ix+1] = spu_pack_color_shuffle(colors[1], shuffle); - if (spu_extract(mask, 2)) - spu.ctile.ui[iy+1][ix] = spu_pack_color_shuffle(colors[2], shuffle); - if (spu_extract(mask, 3)) - spu.ctile.ui[iy+1][ix+1] = spu_pack_color_shuffle(colors[3], shuffle); + /* Read the current framebuffer values. + * + * Ignore read_fb for now. In the future we can use this to avoid + * reading the framebuffer if read_fb is false and the fragment mask is + * all 0xffffffff. This is the common case, so it is probably worth + * the effort. We'll have to profile to determine whether or not the + * extra conditional branches hurt overall performance. + */ + vec_float4 aos_pix[4] = { + spu_unpack_A8R8G8B8(spu.ctile.ui[iy+0][ix+0]), + spu_unpack_A8R8G8B8(spu.ctile.ui[iy+0][ix+1]), + spu_unpack_A8R8G8B8(spu.ctile.ui[iy+1][ix+0]), + spu_unpack_A8R8G8B8(spu.ctile.ui[iy+1][ix+1]), + }; -#if 0 - /* SIMD_Z with swizzled color buffer (someday) */ - vector unsigned int uicolors = *((vector unsigned int *) &colors); - spu.ctile.ui4[iy/2][ix/2] = spu_sel(spu.ctile.ui4[iy/2][ix/2], uicolors, mask); -#endif - } + qword soa_pix[4]; + qword soa_frag[4]; + /* Convert pixel and fragment data from AoS to SoA format. + */ + _transpose_matrix4x4((vec_float4 *) soa_pix, aos_pix); + _transpose_matrix4x4((vec_float4 *) soa_frag, colors); + + const struct spu_blend_results result = + (*spu.blend)(soa_frag[0], soa_frag[1], soa_frag[2], soa_frag[3], + soa_pix[0], soa_pix[1], soa_pix[2], soa_pix[3], + (qword) mask); + + + /* Convert final pixel data from SoA to AoS format. + */ + _transpose_matrix4x4(aos_pix, (const vec_float4 *) &result); + + spu.ctile.ui[iy+0][ix+0] = spu_pack_color_shuffle(aos_pix[0], shuffle); + spu.ctile.ui[iy+0][ix+1] = spu_pack_color_shuffle(aos_pix[1], shuffle); + spu.ctile.ui[iy+1][ix+0] = spu_pack_color_shuffle(aos_pix[2], shuffle); + spu.ctile.ui[iy+1][ix+1] = spu_pack_color_shuffle(aos_pix[3], shuffle); + } #endif } diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 31d7062dcc0..19e6cfaf02e 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -84,8 +84,6 @@ struct softpipe_context { unsigned num_samplers; unsigned num_textures; - uint fb_width, fb_height; - /* Counter for occlusion queries. Note this supports overlapping * queries. */ diff --git a/src/gallium/drivers/softpipe/sp_prim_setup.c b/src/gallium/drivers/softpipe/sp_prim_setup.c index f2d6043e2ed..6a81e4d8cc2 100644 --- a/src/gallium/drivers/softpipe/sp_prim_setup.c +++ b/src/gallium/drivers/softpipe/sp_prim_setup.c @@ -485,7 +485,7 @@ setup_fragcoord_coeff(struct setup_stage *setup, uint slot) /*Y*/ if (setup->softpipe->rasterizer->origin_lower_left) { /* y=0=bottom */ - const int winHeight = setup->softpipe->fb_height; + const int winHeight = setup->softpipe->framebuffer.height; setup->coef[slot].a0[1] = (float) (winHeight - 1); setup->coef[slot].dady[1] = -1.0; } diff --git a/src/gallium/drivers/softpipe/sp_quad_stipple.c b/src/gallium/drivers/softpipe/sp_quad_stipple.c index 9a39249576b..f1e9b80e09a 100644 --- a/src/gallium/drivers/softpipe/sp_quad_stipple.c +++ b/src/gallium/drivers/softpipe/sp_quad_stipple.c @@ -25,7 +25,7 @@ stipple_quad(struct quad_stage *qs, struct quad_header *quad) int y0, y1; uint stipple0, stipple1; if (softpipe->rasterizer->origin_lower_left) { - y0 = softpipe->fb_height - 1 - quad->y0; + y0 = softpipe->framebuffer.height - 1 - quad->y0; y1 = y0 - 1; } else { diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c index 53b2056b8a6..14abb20eeb2 100644 --- a/src/gallium/drivers/softpipe/sp_state_derived.c +++ b/src/gallium/drivers/softpipe/sp_state_derived.c @@ -171,8 +171,8 @@ softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe) static void compute_cliprect(struct softpipe_context *sp) { - uint surfWidth = sp->fb_width; - uint surfHeight = sp->fb_height; + uint surfWidth = sp->framebuffer.width; + uint surfHeight = sp->framebuffer.height; if (sp->rasterizer->scissor) { /* clip to scissor rect */ diff --git a/src/gallium/drivers/softpipe/sp_state_surface.c b/src/gallium/drivers/softpipe/sp_state_surface.c index 2f556844644..ba8c9eece72 100644 --- a/src/gallium/drivers/softpipe/sp_state_surface.c +++ b/src/gallium/drivers/softpipe/sp_state_surface.c @@ -48,9 +48,6 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe, struct softpipe_context *sp = softpipe_context(pipe); uint i; - /* updated below */ - sp->fb_width = sp->fb_height = 0; - for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { /* check if changing cbuf */ if (sp->framebuffer.cbufs[i] != fb->cbufs[i]) { @@ -63,10 +60,6 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe, /* update cache */ sp_tile_cache_set_surface(sp->cbuf_cache[i], fb->cbufs[i]); } - if (fb->cbufs[i]) { - sp->fb_width = fb->cbufs[i]->width; - sp->fb_height = fb->cbufs[i]->height; - } } sp->framebuffer.num_cbufs = fb->num_cbufs; @@ -81,11 +74,6 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe, /* update cache */ sp_tile_cache_set_surface(sp->zsbuf_cache, fb->zsbuf); - - if (!sp->fb_width && fb->zsbuf) { - sp->fb_width = fb->zsbuf->width; - sp->fb_height = fb->zsbuf->height; - } } #if 0 @@ -113,9 +101,8 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe, } #endif + sp->framebuffer.width = fb->width; + sp->framebuffer.height = fb->height; + sp->dirty |= SP_NEW_FRAMEBUFFER; } - - - - diff --git a/src/gallium/include/pipe/p_debug.h b/src/gallium/include/pipe/p_debug.h index e924c1ef606..14f8056924d 100644 --- a/src/gallium/include/pipe/p_debug.h +++ b/src/gallium/include/pipe/p_debug.h @@ -73,6 +73,14 @@ extern "C" { */ void debug_printf(const char *format, ...); + +/* Dump a blob in hex to the same place that debug_printf sends its + * messages: + */ +void debug_print_blob( const char *name, + const void *blob, + unsigned size ); + /** * @sa debug_printf */ diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 5791a10119c..3e531c4da48 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -220,6 +220,8 @@ struct pipe_blend_color struct pipe_framebuffer_state { + unsigned width, height; + /** multiple colorbuffers for multiple render targets */ unsigned num_cbufs; struct pipe_surface *cbufs[PIPE_MAX_COLOR_BUFS]; diff --git a/src/mesa/sources b/src/mesa/sources index 287af7121aa..d109dce5bcc 100644 --- a/src/mesa/sources +++ b/src/mesa/sources @@ -172,6 +172,7 @@ STATETRACKER_SOURCES = \ state_tracker/st_atom_texture.c \ state_tracker/st_atom_viewport.c \ state_tracker/st_cb_accum.c \ + state_tracker/st_cb_bitmap.c \ state_tracker/st_cb_blit.c \ state_tracker/st_cb_bufferobjects.c \ state_tracker/st_cb_clear.c \ diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index 43259c3ecb1..02573af8f0a 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -52,6 +52,9 @@ update_framebuffer_state( struct st_context *st ) memset(framebuffer, 0, sizeof(*framebuffer)); + framebuffer->width = fb->Width; + framebuffer->height = fb->Height; + /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state * to determine which surfaces to draw to */ diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 2a711e513df..9aef30f4566 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -64,7 +64,10 @@ update_textures(struct st_context *st) GLboolean flush, retval; retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush); - /* XXX retval indicates whether there's a texture border */ + if (!retval) { + /* out of mem */ + continue; + } st->state.num_textures = unit + 1; } diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c new file mode 100644 index 00000000000..33256196bb5 --- /dev/null +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -0,0 +1,524 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Brian Paul + */ + +#include "main/imports.h" +#include "main/image.h" +#include "main/macros.h" +#include "main/texformat.h" +#include "shader/program.h" +#include "shader/prog_parameter.h" +#include "shader/prog_print.h" + +#include "st_context.h" +#include "st_atom.h" +#include "st_atom_constbuf.h" +#include "st_program.h" +#include "st_cb_bitmap.h" +#include "st_mesa_to_tgsi.h" +#include "st_texture.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_inlines.h" +#include "pipe/p_winsys.h" +#include "util/p_tile.h" +#include "util/u_draw_quad.h" +#include "util/u_simple_shaders.h" +#include "shader/prog_instruction.h" +#include "cso_cache/cso_context.h" + + + +/** + * Make fragment program for glBitmap: + * Sample the texture and kill the fragment if the bit is 0. + * This program will be combined with the user's fragment program. + */ +static struct st_fragment_program * +make_bitmap_fragment_program(GLcontext *ctx) +{ + struct st_fragment_program *stfp; + struct gl_program *p; + GLuint ic = 0; + + p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); + if (!p) + return NULL; + + p->NumInstructions = 5; + + p->Instructions = _mesa_alloc_instructions(p->NumInstructions); + if (!p->Instructions) { + ctx->Driver.DeleteProgram(ctx, p); + return NULL; + } + _mesa_init_instructions(p->Instructions, p->NumInstructions); + + /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */ + p->Instructions[ic].Opcode = OPCODE_TEX; + p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; + p->Instructions[ic].DstReg.Index = 0; + p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; + p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; + p->Instructions[ic].TexSrcUnit = 0; + p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; + ic++; + + /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */ + p->Instructions[ic].Opcode = OPCODE_SWZ; + p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; + p->Instructions[ic].DstReg.Index = 0; + p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X; + p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; + p->Instructions[ic].SrcReg[0].Index = 0; + p->Instructions[ic].SrcReg[0].Swizzle + = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE ); + ic++; + + /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */ + p->Instructions[ic].Opcode = OPCODE_SUB; + p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; + p->Instructions[ic].DstReg.Index = 0; + p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; + p->Instructions[ic].SrcReg[0].Index = 0; + p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW; + p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY; + p->Instructions[ic].SrcReg[1].Index = 0; + p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */ + ic++; + + /* KIL if tmp0 < 0 */ + p->Instructions[ic].Opcode = OPCODE_KIL; + p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; + p->Instructions[ic].SrcReg[0].Index = 0; + ic++; + + /* END; */ + p->Instructions[ic++].Opcode = OPCODE_END; + + assert(ic == p->NumInstructions); + + p->InputsRead = FRAG_BIT_TEX0; + p->OutputsWritten = 0x0; + + stfp = (struct st_fragment_program *) p; + stfp->Base.UsesKill = GL_TRUE; + st_translate_fragment_program(ctx->st, stfp, NULL); + + return stfp; +} + + +/** + * Combine basic bitmap fragment program with the user-defined program. + */ +static struct st_fragment_program * +combined_bitmap_fragment_program(GLcontext *ctx) +{ + struct st_context *st = ctx->st; + struct st_fragment_program *stfp; + + if (!st->bitmap.program) { + /* create the basic bitmap fragment program */ + st->bitmap.program = make_bitmap_fragment_program(ctx); + } + + if (st->bitmap.user_prog_sn == st->fp->serialNo) { + /* re-use */ + stfp = st->bitmap.combined_prog; + } + else { + /* Concatenate the bitmap program with the current user-defined program. + */ + stfp = (struct st_fragment_program *) + _mesa_combine_programs(ctx, + &st->bitmap.program->Base.Base, + &st->fp->Base.Base); + +#if 0 + { + struct gl_program *p = &stfp->Base.Base; + printf("Combined bitmap program:\n"); + _mesa_print_program(p); + printf("InputsRead: 0x%x\n", p->InputsRead); + printf("OutputsWritten: 0x%x\n", p->OutputsWritten); + _mesa_print_parameter_list(p->Parameters); + } +#endif + + /* translate to TGSI tokens */ + st_translate_fragment_program(st, stfp, NULL); + + /* save new program, update serial numbers */ + st->bitmap.user_prog_sn = st->fp->serialNo; + st->bitmap.combined_prog = stfp; + } + + /* Ideally we'd have updated the pipe constants during the normal + * st/atom mechanism. But we can't since this is specific to glBitmap. + */ + st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); + + return stfp; +} + + + +/** + * Create a texture which represents a bitmap image. + */ +static struct pipe_texture * +make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ + struct pipe_context *pipe = ctx->st->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_surface *surface; + uint format = 0, cpp, comp; + ubyte *dest; + struct pipe_texture *pt; + int row, col; + + /* find a texture format we know */ + if (screen->is_format_supported( screen, PIPE_FORMAT_U_I8, PIPE_TEXTURE )) { + format = PIPE_FORMAT_U_I8; + cpp = 1; + comp = 0; + } + else if (screen->is_format_supported( screen, PIPE_FORMAT_A8R8G8B8_UNORM, PIPE_TEXTURE )) { + format = PIPE_FORMAT_A8R8G8B8_UNORM; + cpp = 4; + comp = 3; /* alpha channel */ /*XXX little-endian dependency */ + } + else { + /* XXX support more formats */ + assert( 0 ); + } + + /** + * Create a texture. + */ + pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, width, height, + 1, 0); + if (!pt) + return NULL; + + if (unpack->BufferObj && unpack->BufferObj->Name) { + /* + pt->region = buffer_object_region(unpack->BufferObj); + */ + printf("st_Bitmap (sourcing from PBO not implemented yet)\n"); + } + + surface = screen->get_tex_surface(screen, pt, 0, 0, 0); + + /* map texture surface */ + dest = pipe_surface_map(surface); + + /* Put image into texture surface. + * Note that the image is actually going to be upside down in + * the texture. We deal with that with texcoords. + */ + + for (row = 0; row < height; row++) { + const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack, + bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0); + ubyte *destRow = dest + row * surface->pitch * cpp; + + if (unpack->LsbFirst) { + /* Lsb first */ + GLubyte mask = 1U << (unpack->SkipPixels & 0x7); + for (col = 0; col < width; col++) { + + /* set texel to 255 if bit is set */ + destRow[comp] = (*src & mask) ? 255 : 0; + destRow += cpp; + + if (mask == 128U) { + src++; + mask = 1U; + } + else { + mask = mask << 1; + } + } + + /* get ready for next row */ + if (mask != 1) + src++; + } + else { + /* Msb first */ + GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); + for (col = 0; col < width; col++) { + + /* set texel to 255 if bit is set */ + destRow[comp] =(*src & mask) ? 255 : 0; + destRow += cpp; + + if (mask == 1U) { + src++; + mask = 128U; + } + else { + mask = mask >> 1; + } + } + + /* get ready for next row */ + if (mask != 128) + src++; + } + + } /* row */ + + /* Release surface */ + pipe_surface_unmap(surface); + pipe_surface_reference(&surface, NULL); + pipe->texture_update(pipe, pt, 0, 0x1); + + pt->format = format; + + return pt; +} + + +static void +setup_bitmap_vertex_data(struct st_context *st, + int x, int y, int width, int height, + float z, const float color[4]) +{ + struct pipe_context *pipe = st->pipe; + const struct gl_framebuffer *fb = st->ctx->DrawBuffer; + const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP); + const GLfloat x0 = x; + const GLfloat x1 = x + width; + const GLfloat y0 = invert ? (fb->Height - y - height) : y; + const GLfloat y1 = invert ? (y0 + height) : y + height; + const GLfloat bias = st->bitmap_texcoord_bias; + const GLfloat xBias = bias / (x1-x0); + const GLfloat yBias = bias / (y1-y0); + const GLfloat sLeft = 0.0 + xBias, sRight = 1.0 + xBias; + const GLfloat tTop = 1.0 - yBias, tBot = 1.0 - tTop - yBias; + GLuint i; + void *buf; + + if (!st->bitmap.vbuf) { + st->bitmap.vbuf = pipe->winsys->buffer_create(pipe->winsys, 32, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(st->bitmap.vertices)); + } + + /* positions, texcoords */ + st->bitmap.vertices[0][0][0] = x0; + st->bitmap.vertices[0][0][1] = y0; + st->bitmap.vertices[0][2][0] = sLeft; + st->bitmap.vertices[0][2][1] = tTop; + + st->bitmap.vertices[1][0][0] = x1; + st->bitmap.vertices[1][0][1] = y0; + st->bitmap.vertices[1][2][0] = sRight; + st->bitmap.vertices[1][2][1] = tTop; + + st->bitmap.vertices[2][0][0] = x1; + st->bitmap.vertices[2][0][1] = y1; + st->bitmap.vertices[2][2][0] = sRight; + st->bitmap.vertices[2][2][1] = tBot; + + st->bitmap.vertices[3][0][0] = x0; + st->bitmap.vertices[3][0][1] = y1; + st->bitmap.vertices[3][2][0] = sLeft; + st->bitmap.vertices[3][2][1] = tBot; + + /* same for all verts: */ + for (i = 0; i < 4; i++) { + st->bitmap.vertices[i][0][2] = z; + st->bitmap.vertices[i][0][3] = 1.0; + st->bitmap.vertices[i][1][0] = color[0]; + st->bitmap.vertices[i][1][1] = color[1]; + st->bitmap.vertices[i][1][2] = color[2]; + st->bitmap.vertices[i][1][3] = color[3]; + st->bitmap.vertices[i][2][2] = 0.0; /*R*/ + st->bitmap.vertices[i][2][3] = 1.0; /*Q*/ + } + + /* put vertex data into vbuf */ + buf = pipe->winsys->buffer_map(pipe->winsys, st->bitmap.vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); + memcpy(buf, st->bitmap.vertices, sizeof(st->bitmap.vertices)); + pipe->winsys->buffer_unmap(pipe->winsys, st->bitmap.vbuf); +} + + + +/** + * Render a glBitmap by drawing a textured quad + */ +static void +draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, + GLsizei width, GLsizei height, + struct pipe_texture *pt, + struct st_fragment_program *stfp) +{ + struct st_context *st = ctx->st; + struct pipe_context *pipe = ctx->st->pipe; + struct cso_context *cso = ctx->st->cso_context; + GLuint maxSize; + + /* limit checks */ + /* XXX if DrawPixels image is larger than max texture size, break + * it up into chunks. + */ + maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + assert(width <= maxSize); + assert(height <= maxSize); + + cso_save_rasterizer(cso); + //cso_save_viewport(cso); + + /* rasterizer state: just scissor */ + { + struct pipe_rasterizer_state rasterizer; + memset(&rasterizer, 0, sizeof(rasterizer)); + if (ctx->Scissor.Enabled) + rasterizer.scissor = 1; + rasterizer.bypass_clipping = 1; + + cso_set_rasterizer(cso, &rasterizer); + } + + /* fragment shader state: TEX lookup program */ + pipe->bind_fs_state(pipe, stfp->driver_shader); + + /* vertex shader state: position + texcoord pass-through */ + pipe->bind_vs_state(pipe, st->bitmap.vs); + + /* sampler / texture state */ + { + struct pipe_sampler_state sampler; + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; + sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.normalized_coords = 1; + + cso_single_sampler(cso, 0, &sampler); + cso_single_sampler_done(cso); + + pipe->set_sampler_textures(pipe, 1, &pt); + } + + /* draw textured quad */ + setup_bitmap_vertex_data(st, x, y, width, height, + ctx->Current.RasterPos[2], + ctx->Current.RasterColor); + + util_draw_vertex_buffer(pipe, st->bitmap.vbuf, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 3); /* attribs/vert */ + + + /* restore state */ + cso_restore_rasterizer(cso); + cso_restore_samplers(cso); + //cso_restore_viewport(cso); + /* shaders don't go through cso yet */ + pipe->bind_fs_state(pipe, st->fp->driver_shader); + pipe->bind_vs_state(pipe, st->vp->driver_shader); + + pipe->set_sampler_textures(pipe, ctx->st->state.num_textures, + ctx->st->state.sampler_texture); +} + + + +static void +st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) +{ + struct st_fragment_program *stfp; + struct st_context *st = ctx->st; + struct pipe_texture *pt; + + stfp = combined_bitmap_fragment_program(ctx); + + if (!st->bitmap.vs) { + /* create pass-through vertex shader now */ + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_COLOR, + TGSI_SEMANTIC_GENERIC }; + const uint semantic_indexes[] = { 0, 0, 0 }; + st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3, + semantic_names, + semantic_indexes); + } + + st_validate_state(st); + + pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); + if (pt) { + draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], + width, height, + pt, stfp); + pipe_texture_reference(&pt, NULL); + } +} + + + +void st_init_bitmap_functions(struct dd_function_table *functions) +{ + functions->Bitmap = st_Bitmap; +} + + +void +st_destroy_bitmap(struct st_context *st) +{ + struct pipe_context *pipe = st->pipe; + + /* XXX free frag shader state */ + + if (st->bitmap.vs) { + pipe->delete_vs_state(pipe, st->bitmap.vs); + st->bitmap.vs = NULL; + } + if (st->bitmap.vbuf) { + pipe->winsys->buffer_destroy(pipe->winsys, st->bitmap.vbuf); + st->bitmap.vbuf = NULL; + } +} + diff --git a/src/gallium/drivers/cell/spu/spu_blend.h b/src/mesa/state_tracker/st_cb_bitmap.h index 2b594b578b4..ac19e0ebb12 100644 --- a/src/gallium/drivers/cell/spu/spu_blend.h +++ b/src/mesa/state_tracker/st_cb_bitmap.h @@ -1,8 +1,8 @@ /************************************************************************** * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -26,12 +26,16 @@ **************************************************************************/ -#ifndef SPU_BLEND_H -#define SPU_BLEND_H +#ifndef ST_CB_BITMAP_H +#define ST_CB_BITMAP_H + + +extern void +st_init_bitmap_functions(struct dd_function_table *functions); extern void -blend_quad(uint itx, uint ity, vector float colors[4]); +st_destroy_bitmap(struct st_context *st); -#endif /* SPU_BLEND_H */ +#endif /* ST_CB_BITMAP_H */ diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index 64314a5078f..63211d8b66e 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -85,11 +85,14 @@ st_BlitFramebuffer(GLcontext *ctx, struct pipe_surface *srcSurf = srcRb->surface; struct pipe_surface *dstSurf = dstRb->surface; - srcY0 = srcRb->Base.Height - srcY0; - srcY1 = srcRb->Base.Height - srcY1; - - dstY0 = dstRb->Base.Height - dstY0; - dstY1 = dstRb->Base.Height - dstY1; + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { + /* invert Y */ + srcY0 = srcRb->Base.Height - srcY0; + srcY1 = srcRb->Base.Height - srcY1; + + dstY0 = dstRb->Base.Height - dstY0; + dstY1 = dstRb->Base.Height - dstY1; + } util_blit_pixels(st->blit, srcSurf, srcX0, srcY0, srcX1, srcY1, diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index c23938dc681..5ca15df602a 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -49,14 +49,37 @@ #include "pipe/p_defines.h" #include "pipe/p_winsys.h" #include "util/u_pack_color.h" +#include "util/u_simple_shaders.h" +#include "util/u_draw_quad.h" #include "cso_cache/cso_context.h" /* XXX for testing draw module vertex passthrough: */ +/* XXX this hack is broken now */ #define TEST_DRAW_PASSTHROUGH 0 +void +st_destroy_clear(struct st_context *st) +{ + struct pipe_context *pipe = st->pipe; + + if (st->clear.fs) { + pipe->delete_fs_state(pipe, st->clear.fs); + st->clear.fs = NULL; + } + if (st->clear.vs) { + pipe->delete_vs_state(pipe, st->clear.vs); + st->clear.vs = NULL; + } + if (st->clear.vbuf) { + pipe->winsys->buffer_destroy(pipe->winsys, st->clear.vbuf); + st->clear.vbuf = NULL; + } +} + + static GLboolean is_depth_stencil_format(enum pipe_format pipeFormat) { @@ -72,104 +95,6 @@ is_depth_stencil_format(enum pipe_format pipeFormat) /** - * Create a simple fragment shader that just passes through the fragment color. - */ -static struct st_fragment_program * -make_frag_shader(struct st_context *st) -{ - GLcontext *ctx = st->ctx; - struct st_fragment_program *stfp; - struct gl_program *p; - GLuint interpMode[16]; - GLuint i; - - /* XXX temporary */ - for (i = 0; i < 16; i++) - interpMode[i] = TGSI_INTERPOLATE_LINEAR; - - p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); - if (!p) - return NULL; - - p->NumInstructions = 2; - p->Instructions = _mesa_alloc_instructions(2); - if (!p->Instructions) { - ctx->Driver.DeleteProgram(ctx, p); - return NULL; - } - _mesa_init_instructions(p->Instructions, 2); - /* MOV result.color, fragment.color; */ - p->Instructions[0].Opcode = OPCODE_MOV; - p->Instructions[0].DstReg.File = PROGRAM_OUTPUT; - p->Instructions[0].DstReg.Index = FRAG_RESULT_COLR; - p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT; - p->Instructions[0].SrcReg[0].Index = FRAG_ATTRIB_COL0; - /* END; */ - p->Instructions[1].Opcode = OPCODE_END; - - p->InputsRead = FRAG_BIT_COL0; - p->OutputsWritten = (1 << FRAG_RESULT_COLR); - - stfp = (struct st_fragment_program *) p; - st_translate_fragment_program(st, stfp, NULL); - - return stfp; -} - - -/** - * Create a simple vertex shader that just passes through the - * vertex position and color. - */ -static struct st_vertex_program * -make_vertex_shader(struct st_context *st) -{ - GLcontext *ctx = st->ctx; - struct st_vertex_program *stvp; - struct gl_program *p; - - p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); - if (!p) - return NULL; - - p->NumInstructions = 3; - p->Instructions = _mesa_alloc_instructions(3); - if (!p->Instructions) { - ctx->Driver.DeleteProgram(ctx, p); - return NULL; - } - _mesa_init_instructions(p->Instructions, 3); - /* MOV result.pos, vertex.pos; */ - p->Instructions[0].Opcode = OPCODE_MOV; - p->Instructions[0].DstReg.File = PROGRAM_OUTPUT; - p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS; - p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT; - p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS; - /* MOV result.color, vertex.color; */ - p->Instructions[1].Opcode = OPCODE_MOV; - p->Instructions[1].DstReg.File = PROGRAM_OUTPUT; - p->Instructions[1].DstReg.Index = VERT_RESULT_COL0; - p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT; - p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_COLOR0; - /* END; */ - p->Instructions[2].Opcode = OPCODE_END; - - p->InputsRead = VERT_BIT_POS | VERT_BIT_COLOR0; - p->OutputsWritten = ((1 << VERT_RESULT_COL0) | - (1 << VERT_RESULT_HPOS)); - - stvp = (struct st_vertex_program *) p; - st_translate_vertex_program(st, stvp, NULL); -#if 0 - assert(stvp->cso); -#endif - - return stvp; -} - - - -/** * Draw a screen-aligned quadrilateral. * Coords are window coords with y=0=bottom. These coords will be transformed * by the vertex shader and viewport transform (which will flip Y if needed). @@ -179,45 +104,51 @@ draw_quad(GLcontext *ctx, float x0, float y0, float x1, float y1, GLfloat z, const GLfloat color[4]) { - GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */ + struct st_context *st = ctx->st; + struct pipe_context *pipe = st->pipe; GLuint i; + void *buf; -#if TEST_DRAW_PASSTHROUGH - /* invert Y coords (may be off by one pixel) */ - y0 = ctx->DrawBuffer->Height - y0; - y1 = ctx->DrawBuffer->Height - y1; -#endif + if (!st->clear.vbuf) { + st->clear.vbuf = pipe->winsys->buffer_create(pipe->winsys, 32, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(st->clear.vertices)); + } /* positions */ - verts[0][0][0] = x0; - verts[0][0][1] = y0; + st->clear.vertices[0][0][0] = x0; + st->clear.vertices[0][0][1] = y0; - verts[1][0][0] = x1; - verts[1][0][1] = y0; + st->clear.vertices[1][0][0] = x1; + st->clear.vertices[1][0][1] = y0; - verts[2][0][0] = x1; - verts[2][0][1] = y1; + st->clear.vertices[2][0][0] = x1; + st->clear.vertices[2][0][1] = y1; - verts[3][0][0] = x0; - verts[3][0][1] = y1; + st->clear.vertices[3][0][0] = x0; + st->clear.vertices[3][0][1] = y1; /* same for all verts: */ for (i = 0; i < 4; i++) { - verts[i][0][2] = z; - verts[i][0][3] = 1.0; - verts[i][1][0] = color[0]; - verts[i][1][1] = color[1]; - verts[i][1][2] = color[2]; - verts[i][1][3] = color[3]; + st->clear.vertices[i][0][2] = z; + st->clear.vertices[i][0][3] = 1.0; + st->clear.vertices[i][1][0] = color[0]; + st->clear.vertices[i][1][1] = color[1]; + st->clear.vertices[i][1][2] = color[2]; + st->clear.vertices[i][1][3] = color[3]; } - st_draw_vertices(ctx, PIPE_PRIM_POLYGON, 4, (float *) verts, 2, -#if TEST_DRAW_PASSTHROUGH - GL_TRUE -#else - GL_FALSE -#endif - ); + /* put vertex data into vbuf */ + buf = pipe->winsys->buffer_map(pipe->winsys, st->clear.vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); + memcpy(buf, st->clear.vertices, sizeof(st->clear.vertices)); + pipe->winsys->buffer_unmap(pipe->winsys, st->clear.vbuf); + + /* draw */ + util_draw_vertex_buffer(pipe, st->clear.vbuf, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ } @@ -234,9 +165,17 @@ clear_with_quad(GLcontext *ctx, struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; const GLfloat x0 = ctx->DrawBuffer->_Xmin; - const GLfloat y0 = ctx->DrawBuffer->_Ymin; const GLfloat x1 = ctx->DrawBuffer->_Xmax; - const GLfloat y1 = ctx->DrawBuffer->_Ymax; + GLfloat y0, y1; + + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { + y0 = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax; + y1 = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin; + } + else { + y0 = ctx->DrawBuffer->_Ymin; + y1 = ctx->DrawBuffer->_Ymax; + } /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, @@ -299,35 +238,35 @@ clear_with_quad(GLcontext *ctx, cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil); } - /* rasterizer state: nothing */ + /* rasterizer state: bypass clipping */ { struct pipe_rasterizer_state raster; memset(&raster, 0, sizeof(raster)); -#if TEST_DRAW_PASSTHROUGH raster.bypass_clipping = 1; +#if TEST_DRAW_PASSTHROUGH raster.bypass_vs = 1; #endif cso_set_rasterizer(st->cso_context, &raster); } /* fragment shader state: color pass-through program */ - { - static struct st_fragment_program *stfp = NULL; - if (!stfp) { - stfp = make_frag_shader(st); - } - pipe->bind_fs_state(pipe, stfp->driver_shader); + if (!st->clear.fs) { + st->clear.fs = util_make_fragment_passthrough_shader(pipe); } + pipe->bind_fs_state(pipe, st->clear.fs); + #if !TEST_DRAW_PASSTHROUGH /* vertex shader state: color/position pass-through */ - { - static struct st_vertex_program *stvp = NULL; - if (!stvp) { - stvp = make_vertex_shader(st); - } - pipe->bind_vs_state(pipe, stvp->driver_shader); + if (!st->clear.vs) { + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_COLOR }; + const uint semantic_indexes[] = { 0, 0 }; + st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2, + semantic_names, + semantic_indexes); } + pipe->bind_vs_state(pipe, st->clear.vs); #endif #if !TEST_DRAW_PASSTHROUGH diff --git a/src/mesa/state_tracker/st_cb_clear.h b/src/mesa/state_tracker/st_cb_clear.h index c715e56bd56..dfa4033faa6 100644 --- a/src/mesa/state_tracker/st_cb_clear.h +++ b/src/mesa/state_tracker/st_cb_clear.h @@ -31,6 +31,10 @@ extern void +st_destroy_clear(struct st_context *st); + + +extern void st_init_clear_functions(struct dd_function_table *functions); diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 99d5e3e848f..b4cd93cd548 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -56,6 +56,7 @@ #include "pipe/p_inlines.h" #include "pipe/p_winsys.h" #include "util/p_tile.h" +#include "util/u_draw_quad.h" #include "shader/prog_instruction.h" #include "cso_cache/cso_context.h" @@ -85,140 +86,6 @@ is_passthrough_program(const struct gl_fragment_program *prog) } -/** - * Make fragment program for glBitmap: - * Sample the texture and kill the fragment if the bit is 0. - * This program will be combined with the user's fragment program. - */ -static struct st_fragment_program * -make_bitmap_fragment_program(GLcontext *ctx) -{ - struct st_fragment_program *stfp; - struct gl_program *p; - GLuint ic = 0; - - p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); - if (!p) - return NULL; - - p->NumInstructions = 5; - - p->Instructions = _mesa_alloc_instructions(p->NumInstructions); - if (!p->Instructions) { - ctx->Driver.DeleteProgram(ctx, p); - return NULL; - } - _mesa_init_instructions(p->Instructions, p->NumInstructions); - - /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */ - p->Instructions[ic].Opcode = OPCODE_TEX; - p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; - p->Instructions[ic].DstReg.Index = 0; - p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; - p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; - p->Instructions[ic].TexSrcUnit = 0; - p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; - ic++; - - /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */ - p->Instructions[ic].Opcode = OPCODE_SWZ; - p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; - p->Instructions[ic].DstReg.Index = 0; - p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X; - p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; - p->Instructions[ic].SrcReg[0].Index = 0; - p->Instructions[ic].SrcReg[0].Swizzle - = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE ); - ic++; - - /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */ - p->Instructions[ic].Opcode = OPCODE_SUB; - p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; - p->Instructions[ic].DstReg.Index = 0; - p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; - p->Instructions[ic].SrcReg[0].Index = 0; - p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW; - p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY; - p->Instructions[ic].SrcReg[1].Index = 0; - p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */ - ic++; - - /* KIL if tmp0 < 0 */ - p->Instructions[ic].Opcode = OPCODE_KIL; - p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; - p->Instructions[ic].SrcReg[0].Index = 0; - ic++; - - /* END; */ - p->Instructions[ic++].Opcode = OPCODE_END; - - assert(ic == p->NumInstructions); - - p->InputsRead = FRAG_BIT_TEX0; - p->OutputsWritten = 0x0; - - stfp = (struct st_fragment_program *) p; - stfp->Base.UsesKill = GL_TRUE; - st_translate_fragment_program(ctx->st, stfp, NULL); - - return stfp; -} - - -/** - * Combine basic bitmap fragment program with the user-defined program. - */ -static struct st_fragment_program * -combined_bitmap_fragment_program(GLcontext *ctx) -{ - struct st_context *st = ctx->st; - struct st_fragment_program *stfp; - - if (!st->bitmap.program) { - /* create the basic bitmap fragment program */ - st->bitmap.program = make_bitmap_fragment_program(ctx); - } - - if (st->bitmap.user_prog_sn == st->fp->serialNo) { - /* re-use */ - stfp = st->bitmap.combined_prog; - } - else { - /* Concatenate the bitmap program with the current user-defined program. - */ - stfp = (struct st_fragment_program *) - _mesa_combine_programs(ctx, - &st->bitmap.program->Base.Base, - &st->fp->Base.Base); - -#if 0 - { - struct gl_program *p = &stfp->Base.Base; - printf("Combined bitmap program:\n"); - _mesa_print_program(p); - printf("InputsRead: 0x%x\n", p->InputsRead); - printf("OutputsWritten: 0x%x\n", p->OutputsWritten); - _mesa_print_parameter_list(p->Parameters); - } -#endif - - /* translate to TGSI tokens */ - st_translate_fragment_program(st, stfp, NULL); - - /* save new program, update serial numbers */ - st->bitmap.user_prog_sn = st->fp->serialNo; - st->bitmap.combined_prog = stfp; - } - - /* Ideally we'd have updated the pipe constants during the normal - * st/atom mechanism. But we can't since this is specific to glBitmap. - */ - st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); - - return stfp; -} - - /** * Make fragment shader for glDraw/CopyPixels. This shader is made @@ -351,7 +218,7 @@ make_fragment_shader_z(struct st_context *st) * Create a simple vertex shader that just passes through the * vertex position and texcoord (and optionally, color). */ -struct st_vertex_program * +static struct st_vertex_program * st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) { /* only make programs once and re-use */ @@ -655,14 +522,14 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_save_rasterizer(cso); cso_save_viewport(cso); - /* setup state: just scissor */ + /* rasterizer state: just scissor */ { - struct pipe_rasterizer_state setup; - memset(&setup, 0, sizeof(setup)); + struct pipe_rasterizer_state rasterizer; + memset(&rasterizer, 0, sizeof(rasterizer)); if (ctx->Scissor.Enabled) - setup.scissor = 1; + rasterizer.scissor = 1; - cso_set_rasterizer(cso, &setup); + cso_set_rasterizer(cso, &rasterizer); } /* fragment shader state: TEX lookup program */ @@ -990,153 +857,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, -/** - * Create a texture which represents a bitmap image. - */ -static struct pipe_texture * -make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height, - const struct gl_pixelstore_attrib *unpack, - const GLubyte *bitmap) -{ - struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen = pipe->screen; - struct pipe_surface *surface; - uint format = 0, cpp, comp; - ubyte *dest; - struct pipe_texture *pt; - int row, col; - - /* find a texture format we know */ - if (screen->is_format_supported( screen, PIPE_FORMAT_U_I8, PIPE_TEXTURE )) { - format = PIPE_FORMAT_U_I8; - cpp = 1; - comp = 0; - } - else if (screen->is_format_supported( screen, PIPE_FORMAT_A8R8G8B8_UNORM, PIPE_TEXTURE )) { - format = PIPE_FORMAT_A8R8G8B8_UNORM; - cpp = 4; - comp = 3; /* alpha channel */ /*XXX little-endian dependency */ - } - else { - /* XXX support more formats */ - assert( 0 ); - } - - /** - * Create a texture. - */ - pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, width, height, - 1, 0); - if (!pt) - return NULL; - - if (unpack->BufferObj && unpack->BufferObj->Name) { - /* - pt->region = buffer_object_region(unpack->BufferObj); - */ - printf("st_Bitmap (sourcing from PBO not implemented yet)\n"); - } - - surface = screen->get_tex_surface(screen, pt, 0, 0, 0); - - /* map texture surface */ - dest = pipe_surface_map(surface); - - /* Put image into texture surface. - * Note that the image is actually going to be upside down in - * the texture. We deal with that with texcoords. - */ - - for (row = 0; row < height; row++) { - const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack, - bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0); - ubyte *destRow = dest + row * surface->pitch * cpp; - - if (unpack->LsbFirst) { - /* Lsb first */ - GLubyte mask = 1U << (unpack->SkipPixels & 0x7); - for (col = 0; col < width; col++) { - - /* set texel to 255 if bit is set */ - destRow[comp] = (*src & mask) ? 255 : 0; - destRow += cpp; - - if (mask == 128U) { - src++; - mask = 1U; - } - else { - mask = mask << 1; - } - } - - /* get ready for next row */ - if (mask != 1) - src++; - } - else { - /* Msb first */ - GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); - for (col = 0; col < width; col++) { - - /* set texel to 255 if bit is set */ - destRow[comp] =(*src & mask) ? 255 : 0; - destRow += cpp; - - if (mask == 1U) { - src++; - mask = 128U; - } - else { - mask = mask >> 1; - } - } - - /* get ready for next row */ - if (mask != 128) - src++; - } - - } /* row */ - - /* Release surface */ - pipe_surface_unmap(surface); - pipe_surface_reference(&surface, NULL); - pipe->texture_update(pipe, pt, 0, 0x1); - - pt->format = format; - - return pt; -} - - - -static void -st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, - const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) -{ - struct st_fragment_program *stfp; - struct st_vertex_program *stvp; - struct st_context *st = ctx->st; - struct pipe_texture *pt; - - stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); - stfp = combined_bitmap_fragment_program(ctx); - - st_validate_state(st); - - pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); - if (pt) { - draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], - width, height, 1.0, 1.0, - pt, stvp, stfp, - ctx->Current.RasterColor, GL_FALSE); - - pipe_texture_reference(&pt, NULL); - } -} - - static void copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, @@ -1337,5 +1057,4 @@ void st_init_drawpixels_functions(struct dd_function_table *functions) { functions->DrawPixels = st_DrawPixels; functions->CopyPixels = st_CopyPixels; - functions->Bitmap = st_Bitmap; } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h index b8b906f06bc..71ba4870200 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.h +++ b/src/mesa/state_tracker/st_cb_drawpixels.h @@ -30,10 +30,6 @@ #define ST_CB_DRAWPIXELS_H -extern struct st_vertex_program * -st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor); - - extern void st_init_drawpixels_functions(struct dd_function_table *functions); diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 306b27c4235..a6c1a353552 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -564,7 +564,8 @@ st_TexImage(GLcontext * ctx, if (!stObj->pt) { guess_and_alloc_texture(ctx->st, stObj, stImage); if (!stObj->pt) { - DBG("guess_and_alloc_texture: failed\n"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); + return; } } @@ -1379,7 +1380,7 @@ copy_image_data_to_texture(struct st_context *st, /** * Called during state validation. When this function is finished, * the texture object should be ready for rendering. - * \return GL_FALSE if a texture border is present, GL_TRUE otherwise + * \return GL_TRUE for success, GL_FALSE for failure (out of mem) */ GLboolean st_finalize_texture(GLcontext *ctx, @@ -1405,6 +1406,7 @@ st_finalize_texture(GLcontext *ctx, calculate_first_last_level(stObj); firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); +#if 0 /* Fallback case: */ if (firstImage->base.Border) { @@ -1413,7 +1415,7 @@ st_finalize_texture(GLcontext *ctx, } return GL_FALSE; } - +#endif /* If both firstImage and stObj point to a texture which can contain * all active images, favour firstImage. Note that because of the @@ -1466,6 +1468,10 @@ st_finalize_texture(GLcontext *ctx, firstImage->base.Height, firstImage->base.Depth, comp_byte); + if (!stObj->pt) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); + return GL_FALSE; + } } /* Pull in any images not in the object's texture: @@ -1486,7 +1492,6 @@ st_finalize_texture(GLcontext *ctx, } } - return GL_TRUE; } diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index e1fc885e0e7..d9e87229764 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -35,8 +35,9 @@ #include "st_public.h" #include "st_context.h" #include "st_cb_accum.h" -#include "st_cb_bufferobjects.h" +#include "st_cb_bitmap.h" #include "st_cb_blit.h" +#include "st_cb_bufferobjects.h" #include "st_cb_clear.h" #include "st_cb_drawpixels.h" #include "st_cb_fbo.h" @@ -154,7 +155,9 @@ static void st_destroy_context_priv( struct st_context *st ) st_destroy_atoms( st ); st_destroy_draw( st ); st_destroy_generate_mipmap(st); + st_destroy_bitmap(st); st_destroy_blit(st); + st_destroy_clear(st); _vbo_DestroyContext(st->ctx); @@ -220,8 +223,9 @@ void st_init_driver_functions(struct dd_function_table *functions) _mesa_init_glsl_driver_functions(functions); st_init_accum_functions(functions); - st_init_bufferobject_functions(functions); + st_init_bitmap_functions(functions); st_init_blit_functions(functions); + st_init_bufferobject_functions(functions); st_init_clear_functions(functions); st_init_drawpixels_functions(functions); st_init_fbo_functions(functions); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index ca8307c4ba0..2d37086799d 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -142,12 +142,24 @@ struct st_context GLuint combined_prog_sn; } pixel_xfer; + /** for glBitmap */ struct { struct st_fragment_program *program; /**< bitmap tex/kil program */ GLuint user_prog_sn; /**< user fragment program serial no. */ struct st_fragment_program *combined_prog; + void *vs; + float vertices[4][3][4]; /**< vertex pos + color + texcoord */ + struct pipe_buffer *vbuf; } bitmap; + /** for glClear */ + struct { + void *vs; + void *fs; + float vertices[4][2][4]; /**< vertex pos + color */ + struct pipe_buffer *vbuf; + } clear; + struct gen_mipmap_state *gen_mipmap; struct blit_state *blit; diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c index 8b9b91aa348..23ecfff0aa4 100644 --- a/src/mesa/state_tracker/st_debug.c +++ b/src/mesa/state_tracker/st_debug.c @@ -50,9 +50,10 @@ st_print_current(void) { GET_CURRENT_CONTEXT(ctx); struct st_context *st = ctx->st; - int i; #if 0 + int i; + printf("Vertex Transform Inputs:\n"); for (i = 0; i < st->vp->state.num_inputs; i++) { printf(" Slot %d: VERT_ATTRIB_%d\n", i, st->vp->index_to_input[i]); |