diff options
Diffstat (limited to 'src/mesa/drivers/dri')
26 files changed, 472 insertions, 210 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_disasm.c b/src/mesa/drivers/dri/i965/brw_disasm.c index a8f6b993ac3..54699cf8d34 100644 --- a/src/mesa/drivers/dri/i965/brw_disasm.c +++ b/src/mesa/drivers/dri/i965/brw_disasm.c @@ -74,9 +74,9 @@ struct { [BRW_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 1, .ndst = 0 }, [BRW_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 }, [BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 1, .ndst = 01 }, - [BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 2, .ndst = 0 }, [BRW_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 }, - [BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 2, .ndst = 0 }, [BRW_OPCODE_CONTINUE] = { .name = "cont", .nsrc = 1, .ndst = 0 }, [BRW_OPCODE_HALT] = { .name = "halt", .nsrc = 1, .ndst = 0 }, [BRW_OPCODE_MSAVE] = { .name = "msave", .nsrc = 1, .ndst = 1 }, diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c index c78f7b38aee..1fd957b3ad6 100644 --- a/src/mesa/drivers/dri/i965/brw_program.c +++ b/src/mesa/drivers/dri/i965/brw_program.c @@ -95,9 +95,17 @@ static void brwDeleteProgram( GLcontext *ctx, struct gl_program *prog ) { if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) { - struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; - struct brw_fragment_program *brw_fprog = brw_fragment_program(fprog); - dri_bo_unreference(brw_fprog->const_buffer); + struct gl_fragment_program *fp = (struct gl_fragment_program *) prog; + struct brw_fragment_program *brw_fp = brw_fragment_program(fp); + + dri_bo_unreference(brw_fp->const_buffer); + } + + if (prog->Target == GL_VERTEX_PROGRAM_ARB) { + struct gl_vertex_program *vp = (struct gl_vertex_program *) prog; + struct brw_vertex_program *brw_vp = brw_vertex_program(vp); + + dri_bo_unreference(brw_vp->const_buffer); } _mesa_delete_program( ctx, prog ); diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c index a7c4b589727..a48804a660f 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c @@ -1717,11 +1717,13 @@ void brw_vs_emit(struct brw_vs_compile *c ) /* patch all the BREAK/CONT instructions from last BEGINLOOP */ while (inst0 > loop_inst[loop_depth]) { inst0--; - if (inst0->header.opcode == BRW_OPCODE_BREAK) { + if (inst0->header.opcode == BRW_OPCODE_BREAK && + inst0->bits3.if_else.jump_count == 0) { inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1); inst0->bits3.if_else.pop_count = 0; } - else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) { + else if (inst0->header.opcode == BRW_OPCODE_CONTINUE && + inst0->bits3.if_else.jump_count == 0) { inst0->bits3.if_else.jump_count = br * (inst1 - inst0); inst0->bits3.if_else.pop_count = 0; } diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c index 562608e2ecd..ea3c2405af9 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c +++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c @@ -614,112 +614,6 @@ static void invoke_subroutine( struct brw_wm_compile *c, } } -/* Workaround for using brw_wm_emit.c's emit functions, which expect - * destination regs to be uniquely written. Moves arguments out to - * temporaries as necessary for instructions which use their destination as - * a temporary. - */ -static void -unalias3(struct brw_wm_compile *c, - void (*func)(struct brw_compile *c, - const struct brw_reg *dst, - GLuint mask, - const struct brw_reg *arg0, - const struct brw_reg *arg1, - const struct brw_reg *arg2), - const struct brw_reg *dst, - GLuint mask, - const struct brw_reg *arg0, - const struct brw_reg *arg1, - const struct brw_reg *arg2) -{ - struct brw_compile *p = &c->func; - struct brw_reg tmp_arg0[4], tmp_arg1[4], tmp_arg2[4]; - int i, j; - int mark = mark_tmps(c); - - for (j = 0; j < 4; j++) { - tmp_arg0[j] = arg0[j]; - tmp_arg1[j] = arg1[j]; - tmp_arg2[j] = arg2[j]; - } - - for (i = 0; i < 4; i++) { - if (mask & (1<<i)) { - for (j = 0; j < 4; j++) { - if (arg0[j].file == dst[i].file && - dst[i].nr == arg0[j].nr) { - tmp_arg0[j] = alloc_tmp(c); - brw_MOV(p, tmp_arg0[j], arg0[j]); - } - if (arg1[j].file == dst[i].file && - dst[i].nr == arg1[j].nr) { - tmp_arg1[j] = alloc_tmp(c); - brw_MOV(p, tmp_arg1[j], arg1[j]); - } - if (arg2[j].file == dst[i].file && - dst[i].nr == arg2[j].nr) { - tmp_arg2[j] = alloc_tmp(c); - brw_MOV(p, tmp_arg2[j], arg2[j]); - } - } - } - } - - func(p, dst, mask, tmp_arg0, tmp_arg1, tmp_arg2); - - release_tmps(c, mark); -} - -/* Workaround for using brw_wm_emit.c's emit functions, which expect - * destination regs to be uniquely written. Moves arguments out to - * temporaries as necessary for instructions which use their destination as - * a temporary. - */ -static void -unalias2(struct brw_wm_compile *c, - void (*func)(struct brw_compile *c, - const struct brw_reg *dst, - GLuint mask, - const struct brw_reg *arg0, - const struct brw_reg *arg1), - const struct brw_reg *dst, - GLuint mask, - const struct brw_reg *arg0, - const struct brw_reg *arg1) -{ - struct brw_compile *p = &c->func; - struct brw_reg tmp_arg0[4], tmp_arg1[4]; - int i, j; - int mark = mark_tmps(c); - - for (j = 0; j < 4; j++) { - tmp_arg0[j] = arg0[j]; - tmp_arg1[j] = arg1[j]; - } - - for (i = 0; i < 4; i++) { - if (mask & (1<<i)) { - for (j = 0; j < 4; j++) { - if (arg0[j].file == dst[i].file && - dst[i].nr == arg0[j].nr) { - tmp_arg0[j] = alloc_tmp(c); - brw_MOV(p, tmp_arg0[j], arg0[j]); - } - if (arg1[j].file == dst[i].file && - dst[i].nr == arg1[j].nr) { - tmp_arg1[j] = alloc_tmp(c); - brw_MOV(p, tmp_arg1[j], arg1[j]); - } - } - } - } - - func(p, dst, mask, tmp_arg0, tmp_arg1); - - release_tmps(c, mark); -} - static void emit_arl(struct brw_wm_compile *c, const struct prog_instruction *inst) { @@ -1813,14 +1707,29 @@ static void get_argument_regs(struct brw_wm_compile *c, const struct prog_instruction *inst, int index, + struct brw_reg *dst, struct brw_reg *regs, int mask) { - int i; + struct brw_compile *p = &c->func; + int i, j; for (i = 0; i < 4; i++) { - if (mask & (1 << i)) + if (mask & (1 << i)) { regs[i] = get_src_reg(c, inst, index, i); + + /* Unalias destination registers from our sources. */ + if (regs[i].file == BRW_GENERAL_REGISTER_FILE) { + for (j = 0; j < 4; j++) { + if (memcmp(®s[i], &dst[j], sizeof(regs[0])) == 0) { + struct brw_reg tmp = alloc_tmp(c); + brw_MOV(p, tmp, regs[i]); + regs[i] = tmp; + break; + } + } + } + } } } @@ -1845,6 +1754,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) int dst_flags; struct brw_reg args[3][4], dst[4]; int j; + int mark = mark_tmps( c ); c->cur_inst = i; @@ -1866,7 +1776,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) } } for (j = 0; j < brw_wm_nr_args(inst->Opcode); j++) - get_argument_regs(c, inst, j, args[j], WRITEMASK_XYZW); + get_argument_regs(c, inst, j, dst, args[j], WRITEMASK_XYZW); dst_flags = inst->DstReg.WriteMask; if (inst->SaturateMode == SATURATE_ZERO_ONE) @@ -1920,8 +1830,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) emit_alu1(p, brw_RNDD, dst, dst_flags, args[0]); break; case OPCODE_LRP: - unalias3(c, emit_lrp, - dst, dst_flags, args[0], args[1], args[2]); + emit_lrp(p, dst, dst_flags, args[0], args[1], args[2]); break; case OPCODE_TRUNC: emit_alu1(p, brw_RNDZ, dst, dst_flags, args[0]); @@ -1961,10 +1870,10 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) emit_math1(c, BRW_MATH_FUNCTION_LOG, dst, dst_flags, args[0]); break; case OPCODE_MIN: - unalias2(c, emit_min, dst, dst_flags, args[0], args[1]); + emit_min(p, dst, dst_flags, args[0], args[1]); break; case OPCODE_MAX: - unalias2(c, emit_max, dst, dst_flags, args[0], args[1]); + emit_max(p, dst, dst_flags, args[0], args[1]); break; case OPCODE_DDX: case OPCODE_DDY: @@ -2103,11 +2012,13 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) /* patch all the BREAK/CONT instructions from last BGNLOOP */ while (inst0 > loop_inst[loop_depth]) { inst0--; - if (inst0->header.opcode == BRW_OPCODE_BREAK) { + if (inst0->header.opcode == BRW_OPCODE_BREAK && + inst0->bits3.if_else.jump_count == 0) { inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1); inst0->bits3.if_else.pop_count = 0; } - else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) { + else if (inst0->header.opcode == BRW_OPCODE_CONTINUE && + inst0->bits3.if_else.jump_count == 0) { inst0->bits3.if_else.jump_count = br * (inst1 - inst0); inst0->bits3.if_else.pop_count = 0; } @@ -2119,6 +2030,9 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) inst->Opcode); } + /* Release temporaries containing any unaliased source regs. */ + release_tmps( c, mark ); + if (inst->CondUpdate) brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); else diff --git a/src/mesa/drivers/dri/r200/Makefile b/src/mesa/drivers/dri/r200/Makefile index 3f871005705..9ea81fd5059 100644 --- a/src/mesa/drivers/dri/r200/Makefile +++ b/src/mesa/drivers/dri/r200/Makefile @@ -21,6 +21,7 @@ RADEON_COMMON_SOURCES = \ radeon_fbo.c \ radeon_lock.c \ radeon_mipmap_tree.c \ + radeon_pixel_read.c \ radeon_queryobj.c \ radeon_span.c \ radeon_texture.c \ diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c index dad2580e08b..4f1a56658cc 100644 --- a/src/mesa/drivers/dri/r200/r200_context.c +++ b/src/mesa/drivers/dri/r200/r200_context.c @@ -266,6 +266,7 @@ static void r200_init_vtbl(radeonContextPtr radeon) radeon->vtbl.emit_query_finish = r200_emit_query_finish; radeon->vtbl.check_blit = r200_check_blit; radeon->vtbl.blit = r200_blit; + radeon->vtbl.is_format_renderable = radeonIsFormatRenderable; } diff --git a/src/mesa/drivers/dri/r200/radeon_pixel_read.c b/src/mesa/drivers/dri/r200/radeon_pixel_read.c new file mode 120000 index 00000000000..3b03803126f --- /dev/null +++ b/src/mesa/drivers/dri/r200/radeon_pixel_read.c @@ -0,0 +1 @@ +../radeon/radeon_pixel_read.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile index 4257a32b89f..2245998c952 100644 --- a/src/mesa/drivers/dri/r300/Makefile +++ b/src/mesa/drivers/dri/r300/Makefile @@ -31,8 +31,9 @@ RADEON_COMMON_SOURCES = \ radeon_fbo.c \ radeon_lock.c \ radeon_mipmap_tree.c \ - radeon_span.c \ + radeon_pixel_read.c \ radeon_queryobj.c \ + radeon_span.c \ radeon_texture.c \ radeon_tex_copy.c \ radeon_tex_getimage.c \ diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c index 6cfa5686f4a..e2dbb1dbf40 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -332,36 +332,37 @@ void r300_emit_cb_setup(struct r300_context *r300, assert(offset % 32 == 0); switch (format) { - case MESA_FORMAT_RGB565: - assert(_mesa_little_endian()); - cbpitch |= R300_COLOR_FORMAT_RGB565; + case MESA_FORMAT_SL8: + case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + cbpitch |= R300_COLOR_FORMAT_I8; break; + case MESA_FORMAT_RGB565: case MESA_FORMAT_RGB565_REV: - assert(!_mesa_little_endian()); cbpitch |= R300_COLOR_FORMAT_RGB565; break; case MESA_FORMAT_ARGB4444: - assert(_mesa_little_endian()); - cbpitch |= R300_COLOR_FORMAT_ARGB4444; - break; case MESA_FORMAT_ARGB4444_REV: - assert(!_mesa_little_endian()); cbpitch |= R300_COLOR_FORMAT_ARGB4444; break; + case MESA_FORMAT_RGBA5551: case MESA_FORMAT_ARGB1555: - assert(_mesa_little_endian()); - cbpitch |= R300_COLOR_FORMAT_ARGB1555; - break; case MESA_FORMAT_ARGB1555_REV: - assert(!_mesa_little_endian()); cbpitch |= R300_COLOR_FORMAT_ARGB1555; break; + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGBA8888_REV: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_XRGB8888_REV: + case MESA_FORMAT_ARGB8888_REV: + case MESA_FORMAT_SRGBA8: + case MESA_FORMAT_SARGB8: + cbpitch |= R300_COLOR_FORMAT_ARGB8888; + break; default: - if (cpp == 4) { - cbpitch |= R300_COLOR_FORMAT_ARGB8888; - } else { - _mesa_problem(r300->radeon.glCtx, "unexpected format in emit_cb_offset()");; - } + _mesa_problem(r300->radeon.glCtx, "unexpected format in emit_cb_offset()"); break; } diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c index ff35cd52753..364e0ba6b61 100644 --- a/src/mesa/drivers/dri/r300/r300_context.c +++ b/src/mesa/drivers/dri/r300/r300_context.c @@ -321,6 +321,12 @@ static void r300_init_vtbl(radeonContextPtr radeon) radeon->vtbl.check_blit = r300_check_blit; radeon->vtbl.blit = r300_blit; + + if (radeon->radeonScreen->chip_family >= CHIP_FAMILY_RV515) { + radeon->vtbl.is_format_renderable = r500IsFormatRenderable; + } else { + radeon->vtbl.is_format_renderable = r300IsFormatRenderable; + } } static void r300InitConstValues(GLcontext *ctx, radeonScreenPtr screen) diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index 5979dedac4f..87489412419 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -46,6 +46,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/simple_list.h" #include "main/api_arrayelt.h" +#include "drivers/common/meta.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "shader/prog_parameter.h" @@ -2237,6 +2238,68 @@ void r300UpdateShaderStates(r300ContextPtr rmesa) } } +#define EASY_US_OUT_FMT(comps, c0, c1, c2, c3) \ + (R500_OUT_FMT_##comps | R500_C0_SEL_##c0 | R500_C1_SEL_##c1 | \ + R500_C2_SEL_##c2 | R500_C3_SEL_##c3) +static void r300SetupUsOutputFormat(GLcontext *ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + uint32_t hw_format; + struct radeon_renderbuffer *rrb = radeon_get_colorbuffer(&rmesa->radeon); + + if (!rrb) { + return; + } + + switch (rrb->base.Format) + { + case MESA_FORMAT_RGBA5551: + case MESA_FORMAT_RGBA8888: + hw_format = EASY_US_OUT_FMT(C4_8, A, B, G, R); + break; + case MESA_FORMAT_RGB565_REV: + case MESA_FORMAT_RGBA8888_REV: + hw_format = EASY_US_OUT_FMT(C4_8, R, G, B, A); + break; + case MESA_FORMAT_RGB565: + case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_ARGB8888: + hw_format = EASY_US_OUT_FMT(C4_8, B, G, R, A); + break; + case MESA_FORMAT_ARGB4444_REV: + case MESA_FORMAT_ARGB1555_REV: + case MESA_FORMAT_XRGB8888_REV: + case MESA_FORMAT_ARGB8888_REV: + hw_format = EASY_US_OUT_FMT(C4_8, A, R, G, B); + break; + case MESA_FORMAT_SRGBA8: + hw_format = EASY_US_OUT_FMT(C4_10_GAMMA, A, B, G, R); + break; + case MESA_FORMAT_SARGB8: + hw_format = EASY_US_OUT_FMT(C4_10_GAMMA, B, G, R, A); + break; + case MESA_FORMAT_SL8: + hw_format = EASY_US_OUT_FMT(C4_10_GAMMA, A, A, R, A); + break; + case MESA_FORMAT_A8: + hw_format = EASY_US_OUT_FMT(C4_8, A, A, A, A); + break; + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + hw_format = EASY_US_OUT_FMT(C4_8, A, A, R, A); + break; + default: + assert(!"Unsupported format"); + break; + } + + R300_STATECHANGE(rmesa, us_out_fmt); + rmesa->hw.us_out_fmt.cmd[1] = hw_format; +} +#undef EASY_US_OUT_FMT + /** * Called by Mesa after an internal state update. */ @@ -2266,6 +2329,10 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state) r300->hw.shade2.cmd[1] &= ~R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; } + if (new_state & _NEW_BUFFERS) { + r300SetupUsOutputFormat(ctx); + } + r300->radeon.NewGLState |= new_state; } @@ -2326,8 +2393,12 @@ void r300InitStateFuncs(struct dd_function_table *functions) functions->ClipPlane = r300ClipPlane; functions->Scissor = radeonScissor; - functions->DrawBuffer = radeonDrawBuffer; - functions->ReadBuffer = radeonReadBuffer; + functions->DrawBuffer = radeonDrawBuffer; + functions->ReadBuffer = radeonReadBuffer; + + functions->CopyPixels = _mesa_meta_CopyPixels; + functions->DrawPixels = _mesa_meta_DrawPixels; + functions->ReadPixels = radeonReadPixels; } void r300InitShaderFunctions(r300ContextPtr r300) diff --git a/src/mesa/drivers/dri/r300/r300_tex.c b/src/mesa/drivers/dri/r300/r300_tex.c index 8dd85073954..baef206bc26 100644 --- a/src/mesa/drivers/dri/r300/r300_tex.c +++ b/src/mesa/drivers/dri/r300/r300_tex.c @@ -308,6 +308,45 @@ static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx, return &t->base; } +unsigned r300IsFormatRenderable(gl_format mesa_format) +{ + switch (mesa_format) + { + case MESA_FORMAT_RGB565: + case MESA_FORMAT_RGBA5551: + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGB565_REV: + case MESA_FORMAT_RGBA8888_REV: + case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_ARGB4444_REV: + case MESA_FORMAT_ARGB1555_REV: + case MESA_FORMAT_XRGB8888_REV: + case MESA_FORMAT_ARGB8888_REV: + case MESA_FORMAT_SRGBA8: + case MESA_FORMAT_SARGB8: + case MESA_FORMAT_SL8: + case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + case MESA_FORMAT_Z16: + return 1; + default: + return 0; + } +} + +unsigned r500IsFormatRenderable(gl_format mesa_format) +{ + if (mesa_format == MESA_FORMAT_S8_Z24) { + return 1; + } else { + return r300IsFormatRenderable(mesa_format); + } +} + void r300InitTextureFuncs(radeonContextPtr radeon, struct dd_function_table *functions) { /* Note: we only plug in the functions we implement in the driver diff --git a/src/mesa/drivers/dri/r300/r300_tex.h b/src/mesa/drivers/dri/r300/r300_tex.h index 9694e703b83..aca44cd7669 100644 --- a/src/mesa/drivers/dri/r300/r300_tex.h +++ b/src/mesa/drivers/dri/r300/r300_tex.h @@ -53,4 +53,7 @@ extern void r300InitTextureFuncs(radeonContextPtr radeon, struct dd_function_tab int32_t r300TranslateTexFormat(gl_format mesaFormat); +unsigned r300IsFormatRenderable(gl_format mesaFormat); +unsigned r500IsFormatRenderable(gl_format mesaFormat); + #endif /* __r300_TEX_H__ */ diff --git a/src/mesa/drivers/dri/r300/radeon_pixel_read.c b/src/mesa/drivers/dri/r300/radeon_pixel_read.c new file mode 120000 index 00000000000..3b03803126f --- /dev/null +++ b/src/mesa/drivers/dri/r300/radeon_pixel_read.c @@ -0,0 +1 @@ +../radeon/radeon_pixel_read.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r600/Makefile b/src/mesa/drivers/dri/r600/Makefile index f76859d11e2..17915621ee4 100644 --- a/src/mesa/drivers/dri/r600/Makefile +++ b/src/mesa/drivers/dri/r600/Makefile @@ -31,9 +31,10 @@ RADEON_COMMON_SOURCES = \ radeon_fbo.c \ radeon_lock.c \ radeon_mipmap_tree.c \ + radeon_pixel_read.c \ + radeon_queryobj.c \ radeon_span.c \ radeon_texture.c \ - radeon_queryobj.c \ radeon_tex_copy.c \ radeon_tex_getimage.c \ radeon_tile.c diff --git a/src/mesa/drivers/dri/r600/r600_context.c b/src/mesa/drivers/dri/r600/r600_context.c index 134e97e7c33..76d5027649e 100644 --- a/src/mesa/drivers/dri/r600/r600_context.c +++ b/src/mesa/drivers/dri/r600/r600_context.c @@ -239,6 +239,7 @@ static void r600_init_vtbl(radeonContextPtr radeon) radeon->vtbl.emit_query_finish = r600_emit_query_finish; radeon->vtbl.check_blit = r600_check_blit; radeon->vtbl.blit = r600_blit; + radeon->vtbl.is_format_renderable = radeonIsFormatRenderable; } static void r600InitConstValues(GLcontext *ctx, radeonScreenPtr screen) diff --git a/src/mesa/drivers/dri/r600/radeon_pixel_read.c b/src/mesa/drivers/dri/r600/radeon_pixel_read.c new file mode 120000 index 00000000000..3b03803126f --- /dev/null +++ b/src/mesa/drivers/dri/r600/radeon_pixel_read.c @@ -0,0 +1 @@ +../radeon/radeon_pixel_read.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/radeon/Makefile b/src/mesa/drivers/dri/radeon/Makefile index 6904ebbee3b..19df62742ec 100644 --- a/src/mesa/drivers/dri/radeon/Makefile +++ b/src/mesa/drivers/dri/radeon/Makefile @@ -22,6 +22,7 @@ RADEON_COMMON_SOURCES = \ radeon_fbo.c \ radeon_lock.c \ radeon_mipmap_tree.c \ + radeon_pixel_read.c \ radeon_queryobj.c \ radeon_span.c \ radeon_texture.c \ diff --git a/src/mesa/drivers/dri/radeon/radeon_common.h b/src/mesa/drivers/dri/radeon/radeon_common.h index cd01c9984e3..35b3f08fff9 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common.h +++ b/src/mesa/drivers/dri/radeon/radeon_common.h @@ -44,6 +44,12 @@ radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb, struct radeon_renderbuffer * radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv); +void +radeonReadPixels(GLcontext * ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, GLvoid * pixels); + void radeon_check_front_buffer_rendering(GLcontext *ctx); static inline struct radeon_renderbuffer *radeon_renderbuffer(struct gl_renderbuffer *rb) { diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h index d1a24e265f2..5156c5d0d0a 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h @@ -539,6 +539,7 @@ struct radeon_context { unsigned reg_width, unsigned reg_height, unsigned flip_y); + unsigned (*is_format_renderable)(gl_format mesa_format); } vtbl; }; diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c index 878a453bd53..56aba16e9e0 100644 --- a/src/mesa/drivers/dri/radeon/radeon_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_context.c @@ -200,6 +200,7 @@ static void r100_init_vtbl(radeonContextPtr radeon) radeon->vtbl.emit_query_finish = r100_emit_query_finish; radeon->vtbl.check_blit = r100_check_blit; radeon->vtbl.blit = r100_blit; + radeon->vtbl.is_format_renderable = radeonIsFormatRenderable; } /* Create the device specific context. diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c index 46664a17556..63986058356 100644 --- a/src/mesa/drivers/dri/radeon/radeon_fbo.c +++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c @@ -409,82 +409,51 @@ radeon_framebuffer_renderbuffer(GLcontext * ctx, radeon_draw_buffer(ctx, fb); } - -/* TODO: According to EXT_fbo spec internal format of texture image - * once set during glTexImage call, should be preserved when - * attaching image to renderbuffer. When HW doesn't support - * rendering to format of attached image, set framebuffer - * completeness accordingly in radeon_validate_framebuffer (issue #79). - */ static GLboolean radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb, struct gl_texture_image *texImage) { - int retry = 0; - gl_format texFormat; - radeon_print(RADEON_TEXTURE, RADEON_TRACE, - "%s(%p, rrb %p, texImage %p) \n", - __func__, ctx, rrb, texImage); - -restart: - if (texImage->TexFormat == _dri_texformat_argb8888) { - rrb->base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to RGBA8 texture OK\n"); + "%s(%p, rrb %p, texImage %p, texFormat %s) \n", + __func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat)); + + switch (texImage->TexFormat) { + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGBA8888_REV: + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_ARGB8888_REV: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_XRGB8888_REV: + case MESA_FORMAT_RGB565: + case MESA_FORMAT_RGB565_REV: + case MESA_FORMAT_RGBA5551: + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_ARGB1555_REV: + case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB4444_REV: + rrb->base.DataType = GL_UNSIGNED_BYTE; + break; + case MESA_FORMAT_Z16: + rrb->base.DataType = GL_UNSIGNED_SHORT; + break; + case MESA_FORMAT_X8_Z24: + rrb->base.DataType = GL_UNSIGNED_INT; + break; + case MESA_FORMAT_S8_Z24: + rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; + break; } - else if (texImage->TexFormat == _dri_texformat_rgb565) { - rrb->base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to RGB5 texture OK\n"); - } - else if (texImage->TexFormat == _dri_texformat_argb1555) { - rrb->base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to ARGB1555 texture OK\n"); - } - else if (texImage->TexFormat == _dri_texformat_argb4444) { - rrb->base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to ARGB4444 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_Z16) { - rrb->base.DataType = GL_UNSIGNED_SHORT; - DBG("Render to DEPTH16 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_S8_Z24) { - rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; - DBG("Render to DEPTH_STENCIL texture OK\n"); - } - else { - /* try redoing the FBO */ - if (retry == 1) { - DBG("Render to texture BAD FORMAT %d\n", - texImage->TexFormat); - return GL_FALSE; - } - /* XXX why is the tex format being set here? - * I think this can be removed. - */ - texImage->TexFormat = radeonChooseTextureFormat(ctx, texImage->InternalFormat, 0, - _mesa_get_format_datatype(texImage->TexFormat), - 1); - - retry++; - goto restart; - } - - texFormat = texImage->TexFormat; - - rrb->base.Format = texFormat; - - rrb->cpp = _mesa_get_format_bytes(texFormat); + + rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat); rrb->pitch = texImage->Width * rrb->cpp; + rrb->base.Format = texImage->TexFormat; rrb->base.InternalFormat = texImage->InternalFormat; - rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat); - + rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat); rrb->base.Width = texImage->Width; rrb->base.Height = texImage->Height; - rrb->base.Delete = radeon_delete_renderbuffer; rrb->base.AllocStorage = radeon_nop_alloc_storage; - + return GL_TRUE; } @@ -607,6 +576,35 @@ radeon_finish_render_texture(GLcontext * ctx, static void radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) { + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + gl_format mesa_format; + int i; + + for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { + struct gl_renderbuffer_attachment *att; + if (i == -2) { + att = &fb->Attachment[BUFFER_DEPTH]; + } else if (i == -1) { + att = &fb->Attachment[BUFFER_STENCIL]; + } else { + att = &fb->Attachment[BUFFER_COLOR0 + i]; + } + + if (att->Type == GL_TEXTURE) { + mesa_format = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->TexFormat; + } else { + /* All renderbuffer formats are renderable, but not sampable */ + continue; + } + + if (!radeon->vtbl.is_format_renderable(mesa_format)){ + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; + radeon_print(RADEON_TEXTURE, RADEON_TRACE, + "%s: HW doesn't support format %s as output format of attachment %d\n", + __FUNCTION__, _mesa_get_format_name(mesa_format), i); + return; + } + } } void radeon_fbo_init(struct radeon_context *radeon) diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c index c6cc417dd6c..78c5f5dd572 100644 --- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c +++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c @@ -468,12 +468,9 @@ static void migrate_image_to_miptree(radeon_mipmap_tree *mt, radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel]; - /* TODO: bring back these assertions once the FBOs are fixed */ -#if 0 assert(image->mtlevel == level); assert(srclvl->size == dstlvl->size); assert(srclvl->rowstride == dstlvl->rowstride); -#endif radeon_bo_map(image->mt->bo, GL_FALSE); diff --git a/src/mesa/drivers/dri/radeon/radeon_pixel_read.c b/src/mesa/drivers/dri/radeon/radeon_pixel_read.c new file mode 100644 index 00000000000..27841938e66 --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_pixel_read.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2010 Maciej Cencora <[email protected]> + * + * 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, sublicense, 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 NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "stdint.h" +#include "main/bufferobj.h" +#include "main/enums.h" +#include "main/image.h" +#include "main/state.h" +#include "swrast/swrast.h" + +#include "radeon_common_context.h" +#include "radeon_debug.h" +#include "radeon_mipmap_tree.h" + +static gl_format gl_format_and_type_to_mesa_format(GLenum format, GLenum type) +{ + switch (format) + { + case GL_RGB: + switch (type) { + case GL_UNSIGNED_SHORT_5_6_5: + return MESA_FORMAT_RGB565; + case GL_UNSIGNED_SHORT_5_6_5_REV: + return MESA_FORMAT_RGB565_REV; + } + break; + case GL_RGBA: + switch (type) { + case GL_UNSIGNED_BYTE: + return MESA_FORMAT_RGBA8888_REV; + case GL_FLOAT: + return MESA_FORMAT_RGBA_FLOAT32; + case GL_UNSIGNED_SHORT_4_4_4_4: + return MESA_FORMAT_ARGB4444; + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return MESA_FORMAT_ARGB4444; + case GL_UNSIGNED_SHORT_5_5_5_1: + return MESA_FORMAT_RGBA5551; + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return MESA_FORMAT_ARGB1555_REV; + case GL_UNSIGNED_INT_8_8_8_8: + return MESA_FORMAT_ARGB8888; + case GL_UNSIGNED_INT_8_8_8_8_REV: + return MESA_FORMAT_ARGB8888_REV; + } + break; + } + + return MESA_FORMAT_NONE; +} + +static GLboolean +do_blit_readpixels(GLcontext * ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, GLvoid * pixels) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + const struct radeon_renderbuffer *rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); + const gl_format dst_format = gl_format_and_type_to_mesa_format(format, type); + unsigned dst_rowstride, dst_imagesize, aligned_rowstride, flip_y; + struct radeon_bo *dst_buffer; + GLint dst_x = 0, dst_y = 0; + + /* It's not worth if number of pixels to copy is really small */ + if (width * height < 100) { + return GL_FALSE; + } + + if (dst_format == MESA_FORMAT_NONE || + !radeon->vtbl.check_blit(dst_format) || !radeon->vtbl.blit) { + return GL_FALSE; + } + + if (ctx->_ImageTransferState) { + return GL_FALSE; + } + + if (pack->SwapBytes || pack->LsbFirst) { + return GL_FALSE; + } + + if (pack->RowLength > 0) { + dst_rowstride = pack->RowLength; + } else { + dst_rowstride = width; + } + + if (!_mesa_clip_copytexsubimage(ctx, &dst_x, &dst_y, &x, &y, &width, &height)) { + return GL_TRUE; + } + assert(x >= 0 && y >= 0); + + aligned_rowstride = get_texture_image_row_stride(radeon, dst_format, dst_rowstride, 0); + dst_imagesize = get_texture_image_size(dst_format, + aligned_rowstride, + height, 1, 0); + dst_buffer = radeon_bo_open(radeon->radeonScreen->bom, 0, dst_imagesize, 1024, RADEON_GEM_DOMAIN_GTT, 0); + + /* Disable source Y flipping for FBOs */ + flip_y = (ctx->ReadBuffer->Name == 0); + if (pack->Invert) { + y = rrb->base.Height - height - y; + flip_y = !flip_y; + } + + if (radeon->vtbl.blit(ctx, + rrb->bo, + rrb->draw_offset, + rrb->base.Format, + rrb->pitch / rrb->cpp, + rrb->base.Width, + rrb->base.Height, + x, + y, + dst_buffer, + 0, /* dst_offset */ + dst_format, + aligned_rowstride / _mesa_get_format_bytes(dst_format), + width, + height, + 0, /* dst_x */ + 0, /* dst_y */ + width, + height, + flip_y)) + { + radeon_bo_map(dst_buffer, 0); + dst_rowstride *= _mesa_get_format_bytes(dst_format); + copy_rows(pixels, dst_rowstride, dst_buffer->ptr, + aligned_rowstride, height, dst_rowstride); + radeon_bo_unmap(dst_buffer); + radeon_bo_unref(dst_buffer); + return GL_TRUE; + } else { + radeon_bo_unref(dst_buffer); + return GL_FALSE; + } +} + +void +radeonReadPixels(GLcontext * ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, GLvoid * pixels) +{ + if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels)) + return; + + /* Update Mesa state before calling down into _swrast_ReadPixels, as + * the spans code requires the computed buffer states to be up to date, + * but _swrast_ReadPixels only updates Mesa state after setting up + * the spans code. + */ + + radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, + "Falling back to sw for ReadPixels (format %s, type %s)\n", + _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); + + if (ctx->NewState) + _mesa_update_state(ctx); + + _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels); +} diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c index 3ccc711253b..2b655fbd953 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texture.c +++ b/src/mesa/drivers/dri/radeon/radeon_texture.c @@ -1006,3 +1006,19 @@ void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level, radeon_texsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, width, height, depth, 0, format, type, pixels, packing, texObj, texImage, 0); } + +unsigned radeonIsFormatRenderable(gl_format mesa_format) +{ + if (mesa_format == _dri_texformat_argb8888 || mesa_format == _dri_texformat_rgb565 || + mesa_format == _dri_texformat_argb1555 || mesa_format == _dri_texformat_argb4444) + return 1; + + switch (mesa_format) + { + case MESA_FORMAT_Z16: + case MESA_FORMAT_S8_Z24: + return 1; + default: + return 0; + } +} diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.h b/src/mesa/drivers/dri/radeon/radeon_texture.h index f09dd652142..4ce639ea34e 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texture.h +++ b/src/mesa/drivers/dri/radeon/radeon_texture.h @@ -135,4 +135,6 @@ void radeonCopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, GLint x, GLint y, GLsizei width, GLsizei height); +unsigned radeonIsFormatRenderable(gl_format mesa_format); + #endif |