diff options
Diffstat (limited to 'src/mesa/drivers/dri/nouveau')
34 files changed, 939 insertions, 450 deletions
diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile index 43bc9f9516..7be19b26fd 100644 --- a/src/mesa/drivers/dri/nouveau/Makefile +++ b/src/mesa/drivers/dri/nouveau/Makefile @@ -8,8 +8,6 @@ DRI_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs) LIBNAME = nouveau_vieux_dri.so -MINIGLX_SOURCES = - DRIVER_SOURCES = \ nouveau_screen.c \ nouveau_context.c \ @@ -42,6 +40,7 @@ DRIVER_SOURCES = \ nv20_state_polygon.c \ nv20_state_raster.c \ nv20_state_tex.c \ + nv20_state_frag.c \ nv20_state_tnl.c C_SOURCES = \ diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c index 1118b96de1..5906ad6d39 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c @@ -72,7 +72,7 @@ nouveau_bufferobj_data(GLcontext *ctx, GLenum target, GLsizeiptrARB size, if (data) { nouveau_bo_map(nbo->bo, NOUVEAU_BO_WR); - _mesa_memcpy(nbo->bo->map, data, size); + memcpy(nbo->bo->map, data, size); nouveau_bo_unmap(nbo->bo); } @@ -87,7 +87,7 @@ nouveau_bufferobj_subdata(GLcontext *ctx, GLenum target, GLintptrARB offset, struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); nouveau_bo_map(nbo->bo, NOUVEAU_BO_WR); - _mesa_memcpy(nbo->bo->map + offset, data, size); + memcpy(nbo->bo->map + offset, data, size); nouveau_bo_unmap(nbo->bo); } @@ -99,7 +99,7 @@ nouveau_bufferobj_get_subdata(GLcontext *ctx, GLenum target, GLintptrARB offset, struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); nouveau_bo_map(nbo->bo, NOUVEAU_BO_RD); - _mesa_memcpy(data, nbo->bo->map + offset, size); + memcpy(data, nbo->bo->map + offset, size); nouveau_bo_unmap(nbo->bo); } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index b1b0e81643..502e01255c 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -43,18 +43,23 @@ #define need_GL_EXT_framebuffer_object #define need_GL_EXT_fog_coord +#define need_GL_EXT_secondary_color #include "main/remap_helper.h" static const struct dri_extension nouveau_extensions[] = { - { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, { "GL_ARB_multitexture", NULL }, - { "GL_EXT_texture_lod_bias", NULL }, - { "GL_SGIS_generate_mipmap", NULL }, + { "GL_ARB_texture_env_add", NULL }, { "GL_ARB_texture_env_combine", NULL }, { "GL_ARB_texture_env_dot3", NULL }, - { "GL_ARB_texture_env_add", NULL }, + { "GL_ARB_texture_mirrored_repeat", NULL }, { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, + { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, + { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, + { "GL_EXT_stencil_wrap", NULL }, + { "GL_EXT_texture_lod_bias", NULL }, + { "GL_NV_blend_square", NULL }, + { "GL_SGIS_generate_mipmap", NULL }, { NULL, NULL } }; @@ -168,19 +173,19 @@ nouveau_context_destroy(__DRIcontext *dri_ctx) context_drv(ctx)->context_destroy(ctx); } -static void -nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, - unsigned int *stamp) +void +nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw) { - struct nouveau_context *nctx = context->driverPrivate; - GLcontext *ctx = &nctx->base; - __DRIscreen *screen = context->driScreenPriv; - struct gl_framebuffer *fb = drawable->driverPrivate; + GLcontext *ctx = dri_ctx->driverPrivate; + __DRIscreen *screen = dri_ctx->driScreenPriv; + struct gl_framebuffer *fb = draw->driverPrivate; unsigned int attachments[10]; __DRIbuffer *buffers = NULL; int i = 0, count, ret; - *stamp = *drawable->pStamp; + if (draw->lastStamp == *draw->pStamp) + return; + draw->lastStamp = *draw->pStamp; attachments[i++] = __DRI_BUFFER_FRONT_LEFT; if (fb->Visual.doubleBufferMode) @@ -192,10 +197,9 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, else if (fb->Visual.haveStencilBuffer) attachments[i++] = __DRI_BUFFER_STENCIL; - buffers = (*screen->dri2.loader->getBuffers)(drawable, - &drawable->w, &drawable->h, + buffers = (*screen->dri2.loader->getBuffers)(draw, &draw->w, &draw->h, attachments, i, &count, - drawable->loaderPrivate); + draw->loaderPrivate); if (buffers == NULL) return; @@ -227,8 +231,8 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, rb = fb->Attachment[index].Renderbuffer; s = &to_nouveau_renderbuffer(rb)->surface; - s->width = drawable->w; - s->height = drawable->h; + s->width = draw->w; + s->height = draw->h; s->pitch = buffers[i].pitch; s->cpp = buffers[i].cpp; @@ -244,12 +248,25 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, ret = nouveau_bo_handle_ref(context_dev(ctx), buffers[i].name, &s->bo); assert(!ret); - - context_dirty(ctx, FRAMEBUFFER); } } - _mesa_resize_framebuffer(ctx, fb, drawable->w, drawable->h); + _mesa_resize_framebuffer(NULL, fb, draw->w, draw->h); +} + +static void +update_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw, + int *stamp) +{ + GLcontext *ctx = dri_ctx->driverPrivate; + struct gl_framebuffer *fb = draw->driverPrivate; + + *stamp = *draw->pStamp; + + nouveau_update_renderbuffers(dri_ctx, draw); + _mesa_resize_framebuffer(ctx, fb, draw->w, draw->h); + + context_dirty(ctx, FRAMEBUFFER); } GLboolean @@ -260,16 +277,15 @@ nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw, struct nouveau_context *nctx = dri_ctx->driverPrivate; GLcontext *ctx = &nctx->base; - if (dri_draw->driverPrivate == ctx->WinSysDrawBuffer && - dri_read->driverPrivate == ctx->WinSysReadBuffer) - return GL_TRUE; - /* Ask the X server for new renderbuffers. */ - nouveau_update_renderbuffers(dri_ctx, dri_draw, - &nctx->drawable.d_stamp); - if (dri_draw != dri_read) - nouveau_update_renderbuffers(dri_ctx, dri_read, - &nctx->drawable.r_stamp); + if (dri_draw->driverPrivate != ctx->WinSysDrawBuffer) + update_framebuffer(dri_ctx, dri_draw, + &dri_ctx->dri2.draw_stamp); + + if (dri_draw != dri_read && + dri_read->driverPrivate != ctx->WinSysReadBuffer) + update_framebuffer(dri_ctx, dri_read, + &dri_ctx->dri2.read_stamp); /* Pass it down to mesa. */ _mesa_make_current(ctx, dri_draw->driverPrivate, @@ -307,30 +323,20 @@ nouveau_fallback(GLcontext *ctx, enum nouveau_fallback mode) void nouveau_validate_framebuffer(GLcontext *ctx) { - struct nouveau_context *nctx = to_nouveau_context(ctx); __DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context; __DRIdrawable *dri_draw = dri_ctx->driDrawablePriv; __DRIdrawable *dri_read = dri_ctx->driReadablePriv; - if ((ctx->DrawBuffer->Name == 0 && - nctx->drawable.d_stamp != *dri_draw->pStamp) || - (dri_draw != dri_read && - ctx->ReadBuffer->Name == 0 && - nctx->drawable.r_stamp != *dri_read->pStamp)) { - if (nctx->drawable.dirty) - ctx->Driver.Flush(ctx); + if (ctx->DrawBuffer->Name == 0 && + dri_ctx->dri2.draw_stamp != *dri_draw->pStamp) + update_framebuffer(dri_ctx, dri_draw, + &dri_ctx->dri2.draw_stamp); - /* Ask the X server for new renderbuffers. */ - nouveau_update_renderbuffers(dri_ctx, dri_draw, - &nctx->drawable.d_stamp); - if (dri_draw != dri_read) - nouveau_update_renderbuffers(dri_ctx, dri_read, - &nctx->drawable.r_stamp); - - if (nouveau_next_dirty_state(ctx) >= 0) - FIRE_RING(context_chan(ctx)); - } + if (ctx->ReadBuffer->Name == 0 && dri_draw != dri_read && + dri_ctx->dri2.read_stamp != *dri_read->pStamp) + update_framebuffer(dri_ctx, dri_read, + &dri_ctx->dri2.read_stamp); - /* Someone's planning to draw something really soon. */ - nctx->drawable.dirty = GL_TRUE; + if (nouveau_next_dirty_state(ctx) >= 0) + FIRE_RING(context_chan(ctx)); } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h index efe3e5148b..682f8a414e 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -56,12 +56,6 @@ struct nouveau_hw_state { struct nouveau_grobj *sifm; }; -struct nouveau_drawable_state { - GLboolean dirty; - unsigned int d_stamp; - unsigned int r_stamp; -}; - struct nouveau_context { GLcontext base; __DRIcontext *dri_context; @@ -73,7 +67,6 @@ struct nouveau_context { struct nouveau_hw_state hw; struct nouveau_bo_state bo; struct nouveau_render_state render; - struct nouveau_drawable_state drawable; }; #define to_nouveau_context(ctx) ((struct nouveau_context *)(ctx)) @@ -107,9 +100,11 @@ nouveau_context_deinit(GLcontext *ctx); void nouveau_context_destroy(__DRIcontext *dri_ctx); +void +nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw); + GLboolean -nouveau_context_make_current(__DRIcontext *dri_ctx, - __DRIdrawable *ddraw, +nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *ddraw, __DRIdrawable *rdraw); GLboolean diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/src/mesa/drivers/dri/nouveau/nouveau_driver.c index bf0e20ca81..1d12f43741 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_driver.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c @@ -67,8 +67,6 @@ nouveau_flush(GLcontext *ctx) dri2->flushFrontBuffer(drawable, drawable->loaderPrivate); } - - nctx->drawable.dirty = GL_FALSE; } static void @@ -112,8 +110,8 @@ nouveau_clear(GLcontext *ctx, GLbitfield buffers) mask = pack_zs_i(s->format, (buffers & BUFFER_BIT_DEPTH && ctx->Depth.Mask) ? ~0 : 0, - (buffers & BUFFER_BIT_STENCIL && - ctx->Stencil.WriteMask[0]) ? ~0 : 0); + (buffers & BUFFER_BIT_STENCIL ? + ctx->Stencil.WriteMask[0] : 0)); value = pack_zs_f(s->format, ctx->Depth.Clear, ctx->Stencil.Clear); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.h b/src/mesa/drivers/dri/nouveau/nouveau_driver.h index 54bf981a0f..283f6eac2c 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_driver.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.h @@ -70,7 +70,7 @@ struct nouveau_driver { }; #define nouveau_error(format, ...) \ - _mesa_fprintf(stderr, "%s: " format, __func__, ## __VA_ARGS__) + fprintf(stderr, "%s: " format, __func__, ## __VA_ARGS__) void nouveau_clear(GLcontext *ctx, GLbitfield buffers); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fbo.c b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c index 91eade8d63..2ec3dc9242 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_fbo.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c @@ -70,9 +70,9 @@ set_renderbuffer_format(struct gl_renderbuffer *rb, GLenum internalFormat) case GL_DEPTH_COMPONENT24: case GL_STENCIL_INDEX8_EXT: case GL_DEPTH24_STENCIL8_EXT: - rb->_BaseFormat = GL_DEPTH_COMPONENT; + rb->_BaseFormat = GL_DEPTH_STENCIL; rb->Format = MESA_FORMAT_Z24_S8; - rb->DataType = GL_UNSIGNED_INT; + rb->DataType = GL_UNSIGNED_INT_24_8_EXT; s->cpp = 4; break; default: @@ -142,7 +142,6 @@ nouveau_renderbuffer_dri_storage(GLcontext *ctx, struct gl_renderbuffer *rb, rb->Width = width; rb->Height = height; - context_dirty(ctx, FRAMEBUFFER); return GL_TRUE; } @@ -216,6 +215,8 @@ get_tex_format(struct gl_texture_image *ti) switch (ti->TexFormat) { case MESA_FORMAT_ARGB8888: return GL_RGBA8; + case MESA_FORMAT_XRGB8888: + return GL_RGB8; case MESA_FORMAT_RGB565: return GL_RGB5; default: diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c index 71e57e17e6..18db12f626 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c @@ -27,6 +27,7 @@ #include "nouveau_driver.h" #include "nouveau_context.h" #include "nouveau_fbo.h" +#include "nouveau_texture.h" #include "nouveau_drmif.h" #include "nv04_driver.h" #include "nv10_driver.h" @@ -226,8 +227,15 @@ static const struct __DRI2flushExtensionRec nouveau_flush_extension = { dri2InvalidateDrawable, }; +static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = { + { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, + NULL, + nouveau_set_texbuffer, +}; + static const __DRIextension *nouveau_screen_extensions[] = { &nouveau_flush_extension.base, + &nouveau_texbuffer_extension.base, NULL }; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.c b/src/mesa/drivers/dri/nouveau/nouveau_span.c index dbbbf15b09..f1a56dd03a 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_span.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_span.c @@ -61,6 +61,15 @@ #include "spantmp2.h" +/* RGB888 span functions */ +#define SPANTMP_PIXEL_FMT GL_BGR +#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV +#define TAG(x) nouveau_##x##_rgb888 +#define TAG2(x, y) nouveau_##x##_rgb888##y +#define GET_PTR(x, y) (s->bo->map + (y)*s->pitch + (x)*s->cpp) + +#include "spantmp2.h" + /* ARGB8888 span functions */ #define SPANTMP_PIXEL_FMT GL_BGRA #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV @@ -101,6 +110,8 @@ renderbuffer_map_unmap(struct gl_renderbuffer *rb, GLboolean map) nouveau_InitPointers_rgb565(rb); break; case MESA_FORMAT_XRGB8888: + nouveau_InitPointers_rgb888(rb); + break; case MESA_FORMAT_ARGB8888: nouveau_InitPointers_argb8888(rb); break; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c index d727822175..bc610451b4 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c @@ -150,6 +150,7 @@ nouveau_enable(GLcontext *ctx, GLenum cap, GLboolean state) break; case GL_COLOR_SUM_EXT: context_dirty(ctx, FRAG); + context_dirty(ctx, LIGHT_MODEL); break; case GL_CULL_FACE: context_dirty(ctx, CULL_FACE); @@ -243,12 +244,6 @@ nouveau_fog(GLcontext *ctx, GLenum pname, const GLfloat *params) } static void -nouveau_index_mask(GLcontext *ctx, GLuint mask) -{ - context_dirty(ctx, INDEX_MASK); -} - -static void nouveau_light(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params) { switch (pname) { @@ -396,7 +391,6 @@ nouveau_tex_parameter(GLcontext *ctx, GLenum target, const GLfloat *params) { switch (pname) { - case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: @@ -408,9 +402,10 @@ nouveau_tex_parameter(GLcontext *ctx, GLenum target, context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); break; + case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_MAX_LEVEL: - texture_dirty(t); + nouveau_texture_reallocate(ctx, t); context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); break; } @@ -504,7 +499,6 @@ nouveau_state_init(GLcontext *ctx) ctx->Driver.DrawBuffers = nouveau_draw_buffers; ctx->Driver.Enable = nouveau_enable; ctx->Driver.Fogfv = nouveau_fog; - ctx->Driver.IndexMask = nouveau_index_mask; ctx->Driver.Lightfv = nouveau_light; ctx->Driver.LightModelfv = nouveau_light_model; ctx->Driver.LineStipple = nouveau_line_stipple; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.h b/src/mesa/drivers/dri/nouveau/nouveau_state.h index d001fa259a..d01d962c9f 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.h @@ -47,7 +47,6 @@ enum { NOUVEAU_STATE_FRAG, NOUVEAU_STATE_FRAMEBUFFER, NOUVEAU_STATE_FOG, - NOUVEAU_STATE_INDEX_MASK, NOUVEAU_STATE_LIGHT_ENABLE, NOUVEAU_STATE_LIGHT_MODEL, NOUVEAU_STATE_LIGHT_SOURCE0, diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.c b/src/mesa/drivers/dri/nouveau/nouveau_texture.c index ab6e93cceb..bf365bfca3 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_texture.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.c @@ -27,6 +27,7 @@ #include "nouveau_driver.h" #include "nouveau_context.h" #include "nouveau_texture.h" +#include "nouveau_fbo.h" #include "nouveau_util.h" #include "main/texobj.h" @@ -36,6 +37,7 @@ #include "main/texgetimage.h" #include "main/mipmap.h" #include "main/texfetch.h" +#include "main/teximage.h" static struct gl_texture_object * nouveau_texture_new(GLcontext *ctx, GLuint name, GLenum target) @@ -81,10 +83,12 @@ nouveau_teximage_map(GLcontext *ctx, struct gl_texture_image *ti) struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; int ret; - ret = nouveau_bo_map(s->bo, NOUVEAU_BO_RDWR); - assert(!ret); + if (s->bo) { + ret = nouveau_bo_map(s->bo, NOUVEAU_BO_RDWR); + assert(!ret); - ti->Data = s->bo->map; + ti->Data = s->bo->map; + } } static void @@ -92,7 +96,8 @@ nouveau_teximage_unmap(GLcontext *ctx, struct gl_texture_image *ti) { struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; - nouveau_bo_unmap(s->bo); + if (s->bo) + nouveau_bo_unmap(s->bo); ti->Data = NULL; } @@ -103,43 +108,28 @@ nouveau_choose_tex_format(GLcontext *ctx, GLint internalFormat, switch (internalFormat) { case 4: case GL_RGBA: - case GL_RGB10_A2: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGBA8: case GL_RGBA12: case GL_RGBA16: - case GL_RGBA8: + case GL_RGB10_A2: + return MESA_FORMAT_ARGB8888; + case GL_RGB5_A1: + return MESA_FORMAT_ARGB1555; + case GL_RGB: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: - return MESA_FORMAT_ARGB8888; - case GL_RGB5_A1: - return MESA_FORMAT_ARGB1555; - case GL_RGBA2: - case GL_RGBA4: - return MESA_FORMAT_ARGB4444; - + return MESA_FORMAT_XRGB8888; case 3: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: return MESA_FORMAT_RGB565; - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA12: - case GL_ALPHA16: - case GL_ALPHA8: - return MESA_FORMAT_A8; - - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - case GL_LUMINANCE8: - return MESA_FORMAT_L8; - case 2: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE4_ALPHA4: @@ -150,12 +140,27 @@ nouveau_choose_tex_format(GLcontext *ctx, GLint internalFormat, case GL_LUMINANCE8_ALPHA8: return MESA_FORMAT_ARGB8888; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_LUMINANCE8: + return MESA_FORMAT_L8; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA12: + case GL_ALPHA16: + case GL_ALPHA8: + return MESA_FORMAT_A8; + case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY12: case GL_INTENSITY16: case GL_INTENSITY8: - return MESA_FORMAT_ARGB8888; + return MESA_FORMAT_I8; case GL_COLOR_INDEX: case GL_COLOR_INDEX1_EXT: @@ -171,6 +176,152 @@ nouveau_choose_tex_format(GLcontext *ctx, GLint internalFormat, } } +static GLboolean +teximage_fits(struct gl_texture_object *t, int level, + struct gl_texture_image *ti) +{ + struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level]; + + return t->Target == GL_TEXTURE_RECTANGLE || + (s->bo && s->width == ti->Width && + s->height == ti->Height && + s->format == ti->TexFormat); +} + +static GLboolean +validate_teximage(GLcontext *ctx, struct gl_texture_object *t, + int level, int x, int y, int z, + int width, int height, int depth) +{ + struct gl_texture_image *ti = t->Image[0][level]; + + if (ti && teximage_fits(t, level, ti)) { + struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces; + struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; + + if (t->Target == GL_TEXTURE_RECTANGLE) + nouveau_surface_ref(s, &ss[level]); + else + context_drv(ctx)->surface_copy(ctx, &ss[level], s, + x, y, x, y, + width, height); + + return GL_TRUE; + } + + return GL_FALSE; +} + +static int +get_last_level(struct gl_texture_object *t) +{ + struct gl_texture_image *base = t->Image[0][t->BaseLevel]; + + if (t->MinFilter == GL_NEAREST || + t->MinFilter == GL_LINEAR || !base) + return t->BaseLevel; + else + return MIN2(t->BaseLevel + base->MaxLog2, t->MaxLevel); +} + +static void +relayout_texture(GLcontext *ctx, struct gl_texture_object *t) +{ + struct gl_texture_image *base = t->Image[0][t->BaseLevel]; + + if (base && t->Target != GL_TEXTURE_RECTANGLE) { + struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces; + struct nouveau_surface *s = &to_nouveau_teximage(base)->surface; + int i, ret, last = get_last_level(t); + unsigned size, offset = 0, + width = s->width, + height = s->height; + + /* Deallocate the old storage. */ + for (i = 0; i < MAX_TEXTURE_LEVELS; i++) + nouveau_bo_ref(NULL, &ss[i].bo); + + /* Relayout the mipmap tree. */ + for (i = t->BaseLevel; i <= last; i++) { + size = width * height * s->cpp; + + /* Images larger than 16B have to be aligned. */ + if (size > 16) + offset = align(offset, 64); + + ss[i] = (struct nouveau_surface) { + .offset = offset, + .layout = SWIZZLED, + .format = s->format, + .width = width, + .height = height, + .cpp = s->cpp, + .pitch = width * s->cpp, + }; + + offset += size; + width = MAX2(1, width / 2); + height = MAX2(1, height / 2); + } + + /* Get new storage. */ + size = align(offset, 64); + + ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP | + NOUVEAU_BO_GART | NOUVEAU_BO_VRAM, + 0, size, &ss[last].bo); + assert(!ret); + + for (i = t->BaseLevel; i < last; i++) + nouveau_bo_ref(ss[last].bo, &ss[i].bo); + } +} + +GLboolean +nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t) +{ + struct nouveau_texture *nt = to_nouveau_texture(t); + int i, last = get_last_level(t); + + if (!nt->surfaces[last].bo) + return GL_FALSE; + + if (nt->dirty) { + nt->dirty = GL_FALSE; + + /* Copy the teximages to the actual miptree. */ + for (i = t->BaseLevel; i <= last; i++) { + struct nouveau_surface *s = &nt->surfaces[i]; + + validate_teximage(ctx, t, i, 0, 0, 0, + s->width, s->height, 1); + } + } + + return GL_TRUE; +} + +void +nouveau_texture_reallocate(GLcontext *ctx, struct gl_texture_object *t) +{ + texture_dirty(t); + relayout_texture(ctx, t); + nouveau_texture_validate(ctx, t); +} + +static unsigned +get_teximage_placement(struct gl_texture_image *ti) +{ + if (ti->TexFormat == MESA_FORMAT_A8 || + ti->TexFormat == MESA_FORMAT_L8 || + ti->TexFormat == MESA_FORMAT_I8) + /* 1 cpp formats will have to be swizzled by the CPU, + * so leave them in system RAM for now. */ + return NOUVEAU_BO_MAP; + else + return NOUVEAU_BO_GART | NOUVEAU_BO_MAP; +} + static void nouveau_teximage(GLcontext *ctx, GLint dims, GLenum target, GLint level, GLint internalFormat, @@ -181,37 +332,45 @@ nouveau_teximage(GLcontext *ctx, GLint dims, GLenum target, GLint level, struct gl_texture_image *ti) { struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; - unsigned bo_flags = NOUVEAU_BO_GART | NOUVEAU_BO_RDWR | NOUVEAU_BO_MAP; int ret; /* Allocate a new bo for the image. */ - nouveau_surface_alloc(ctx, s, LINEAR, bo_flags, ti->TexFormat, - width, height); + nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti), + ti->TexFormat, width, height); ti->RowStride = s->pitch / s->cpp; pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, type, pixels, packing, "glTexImage"); - if (!pixels) - return; - - /* Store the pixel data. */ - nouveau_teximage_map(ctx, ti); - - ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, - ti->TexFormat, ti->Data, - 0, 0, 0, s->pitch, - ti->ImageOffsets, - width, height, depth, - format, type, pixels, packing); - assert(ret); + if (pixels) { + /* Store the pixel data. */ + nouveau_teximage_map(ctx, ti); + + ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, + ti->TexFormat, ti->Data, + 0, 0, 0, s->pitch, + ti->ImageOffsets, + width, height, depth, + format, type, pixels, packing); + assert(ret); + + nouveau_teximage_unmap(ctx, ti); + _mesa_unmap_teximage_pbo(ctx, packing); + + if (!validate_teximage(ctx, t, level, 0, 0, 0, + width, height, depth)) + /* It doesn't fit, mark it as dirty. */ + texture_dirty(t); + } - nouveau_teximage_unmap(ctx, ti); - _mesa_unmap_teximage_pbo(ctx, packing); + if (level == t->BaseLevel) { + if (!teximage_fits(t, level, ti)) + relayout_texture(ctx, t); + nouveau_texture_validate(ctx, t); + } context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); - texture_dirty(t); } static void @@ -271,8 +430,9 @@ nouveau_texsubimage_3d(GLcontext *ctx, GLenum target, GLint level, packing, t, ti); nouveau_teximage_unmap(ctx, ti); - context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); - texture_dirty(t); + if (!to_nouveau_texture(t)->dirty) + validate_teximage(ctx, t, level, xoffset, yoffset, zoffset, + width, height, depth); } static void @@ -290,8 +450,9 @@ nouveau_texsubimage_2d(GLcontext *ctx, GLenum target, GLint level, packing, t, ti); nouveau_teximage_unmap(ctx, ti); - context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); - texture_dirty(t); + if (!to_nouveau_texture(t)->dirty) + validate_teximage(ctx, t, level, xoffset, yoffset, 0, + width, height, 1); } static void @@ -308,8 +469,9 @@ nouveau_texsubimage_1d(GLcontext *ctx, GLenum target, GLint level, packing, t, ti); nouveau_teximage_unmap(ctx, ti); - context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); - texture_dirty(t); + if (!to_nouveau_texture(t)->dirty) + validate_teximage(ctx, t, level, xoffset, 0, 0, + width, 1, 1); } static void @@ -332,6 +494,57 @@ nouveau_bind_texture(GLcontext *ctx, GLenum target, context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); } +static gl_format +get_texbuffer_format(struct gl_renderbuffer *rb, GLint format) +{ + struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; + + if (s->cpp < 4) + return s->format; + else if (format == __DRI_TEXTURE_FORMAT_RGBA) + return MESA_FORMAT_ARGB8888; + else + return MESA_FORMAT_XRGB8888; +} + +void +nouveau_set_texbuffer(__DRIcontext *dri_ctx, + GLint target, GLint format, + __DRIdrawable *draw) +{ + struct nouveau_context *nctx = dri_ctx->driverPrivate; + GLcontext *ctx = &nctx->base; + struct gl_framebuffer *fb = draw->driverPrivate; + struct gl_renderbuffer *rb = + fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target); + struct gl_texture_image *ti; + struct nouveau_surface *s; + + _mesa_lock_texture(ctx, t); + ti = _mesa_get_tex_image(ctx, t, target, 0); + s = &to_nouveau_teximage(ti)->surface; + + /* Update the texture surface with the given drawable. */ + nouveau_update_renderbuffers(dri_ctx, draw); + nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s); + + /* Update the image fields. */ + _mesa_init_teximage_fields(ctx, target, ti, s->width, s->height, + 1, 0, s->cpp); + ti->RowStride = s->pitch / s->cpp; + ti->TexFormat = s->format = get_texbuffer_format(rb, format); + + /* Try to validate it. */ + if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1)) + nouveau_texture_reallocate(ctx, t); + + context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); + context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); + + _mesa_unlock_texture(ctx, t); +} + static void nouveau_texture_map(GLcontext *ctx, struct gl_texture_object *t) { @@ -354,87 +567,6 @@ nouveau_texture_unmap(GLcontext *ctx, struct gl_texture_object *t) } } -static void -relayout_miptree(GLcontext *ctx, struct gl_texture_object *t) -{ - struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces; - unsigned last_level, offset = 0; - unsigned size; - int i, ret; - - if (t->MinFilter == GL_NEAREST || - t->MinFilter == GL_LINEAR) - last_level = t->BaseLevel; - else - last_level = t->_MaxLevel; - - /* Deallocate the old storage. */ - for (i = 0; i < MAX_TEXTURE_LEVELS; i++) - nouveau_bo_ref(NULL, &ss[i].bo); - - /* Relayout the mipmap tree. */ - for (i = t->BaseLevel; i <= last_level; i++) { - struct nouveau_surface *s = - &to_nouveau_teximage(t->Image[0][i])->surface; - - size = s->width * s->height * s->cpp; - - /* Images larger than 16B have to be aligned. */ - if (size > 16) - offset = align(offset, 64); - - ss[i] = (struct nouveau_surface) { - .offset = offset, - .layout = SWIZZLED, - .format = s->format, - .width = s->width, - .height = s->height, - .cpp = s->cpp, - .pitch = s->width * s->cpp, - }; - - offset += size; - } - - /* Get new storage. */ - size = align(offset, 64); - - ret = nouveau_bo_new(context_dev(ctx), - NOUVEAU_BO_GART | NOUVEAU_BO_VRAM, - 0, size, &ss[last_level].bo); - assert(!ret); - - for (i = t->BaseLevel; i < last_level; i++) - nouveau_bo_ref(ss[last_level].bo, &ss[i].bo); -} - -void -nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t) -{ - struct nouveau_texture *nt = to_nouveau_texture(t); - int i; - - if (!nt->dirty) - return; - - nt->dirty = GL_FALSE; - - relayout_miptree(ctx, t); - - /* Copy the teximages to the actual swizzled miptree. */ - for (i = t->BaseLevel; i < MAX_TEXTURE_LEVELS; i++) { - struct gl_texture_image *ti = t->Image[0][i]; - struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; - - if (!nt->surfaces[i].bo) - break; - - context_drv(ctx)->surface_copy(ctx, &nt->surfaces[i], s, - 0, 0, 0, 0, - s->width, s->height); - } -} - void nouveau_texture_functions_init(struct dd_function_table *functions) { diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.h b/src/mesa/drivers/dri/nouveau/nouveau_texture.h index 695c0897b5..b91facbdeb 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_texture.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.h @@ -44,6 +44,14 @@ struct nouveau_texture { to_nouveau_texture(t)->dirty = GL_TRUE; void +nouveau_set_texbuffer(__DRIcontext *dri_ctx, + GLint target, GLint format, + __DRIdrawable *draw); + +GLboolean nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t); +void +nouveau_texture_reallocate(GLcontext *ctx, struct gl_texture_object *t); + #endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_util.h b/src/mesa/drivers/dri/nouveau/nouveau_util.h index 076f225fed..d6007aba2b 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_util.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_util.h @@ -173,4 +173,22 @@ OUT_RINGm(struct nouveau_channel *chan, float m[16]) OUT_RINGf(chan, m[4*j + i]); } +static inline GLboolean +is_color_operand(int op) +{ + return op == GL_SRC_COLOR || op == GL_ONE_MINUS_SRC_COLOR; +} + +static inline GLboolean +is_negative_operand(int op) +{ + return op == GL_ONE_MINUS_SRC_COLOR || op == GL_ONE_MINUS_SRC_ALPHA; +} + +static inline GLboolean +is_texture_source(int s) +{ + return s == GL_TEXTURE || (s >= GL_TEXTURE0 && s <= GL_TEXTURE31); +} + #endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c index 02c8580760..a365b977f2 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c @@ -24,8 +24,11 @@ * */ -#include "main/bufferobj.h" #include "nouveau_bufferobj.h" +#include "nouveau_util.h" + +#include "main/bufferobj.h" +#include "main/image.h" /* Arbitrary pushbuf length we can assume we can get with a single * WAIT_RING. */ @@ -58,7 +61,11 @@ vbo_init_array(struct nouveau_array_state *a, int attr, int stride, } else { nouveau_bo_ref(NULL, &a->bo); a->offset = 0; - a->buf = ptr; + + if (map) + a->buf = ptr; + else + a->buf = NULL; } if (a->buf) @@ -94,11 +101,20 @@ vbo_init_arrays(GLcontext *ctx, const struct _mesa_index_buffer *ib, if (attr >= 0) { const struct gl_client_array *array = arrays[attr]; + int stride; + + if (render->mode == VBO && + !_mesa_is_bufferobj(array->BufferObj)) + /* Pack client buffers. */ + stride = align(_mesa_sizeof_type(array->Type) + * array->Size, 4); + else + stride = array->StrideB; vbo_init_array(&render->attrs[attr], attr, - array->StrideB, array->Size, - array->Type, array->BufferObj, - array->Ptr, render->mode == IMM); + stride, array->Size, array->Type, + array->BufferObj, array->Ptr, + render->mode == IMM); } } } @@ -227,6 +243,23 @@ vbo_choose_attrs(GLcontext *ctx, const struct gl_client_array **arrays) vbo_emit_attr(ctx, arrays, VERT_ATTRIB_POS); } +static unsigned +get_max_client_stride(GLcontext *ctx) +{ + struct nouveau_render_state *render = to_render_state(ctx); + int i, s = 0; + + for (i = 0; i < render->attr_count; i++) { + int attr = render->map[i]; + struct nouveau_array_state *a = &render->attrs[attr]; + + if (attr >= 0 && !a->bo) + s = MAX2(a->stride, s); + } + + return s; +} + static void TAG(vbo_render_prims)(GLcontext *ctx, const struct gl_client_array **arrays, const struct _mesa_prim *prims, GLuint nr_prims, @@ -241,12 +274,20 @@ vbo_maybe_split(GLcontext *ctx, const struct gl_client_array **arrays, GLuint min_index, GLuint max_index) { struct nouveau_context *nctx = to_nouveau_context(ctx); + struct nouveau_render_state *render = to_render_state(ctx); unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * nctx->bo.count, vert_avail = get_max_vertices(ctx, NULL, pushbuf_avail), idx_avail = get_max_vertices(ctx, ib, pushbuf_avail); + int stride; - if ((ib && ib->count > idx_avail) || - (!ib && max_index - min_index > vert_avail)) { + /* Try to keep client buffers smaller than the scratch BOs. */ + if (render->mode == VBO && + (stride = get_max_client_stride(ctx))) + vert_avail = MIN2(vert_avail, + RENDER_SCRATCH_SIZE / stride); + + if (max_index - min_index > vert_avail || + (ib && ib->count > idx_avail)) { struct split_limits limits = { .max_verts = vert_avail, .max_indices = idx_avail, @@ -276,17 +317,21 @@ vbo_bind_vertices(GLcontext *ctx, const struct gl_client_array **arrays, if (attr >= 0) { const struct gl_client_array *array = arrays[attr]; struct nouveau_array_state *a = &render->attrs[attr]; - unsigned delta = (basevertex + min_index) * a->stride, - size = (max_index - min_index + 1) * a->stride; + unsigned delta = (basevertex + min_index) + * array->StrideB; if (a->bo) { a->offset = (intptr_t)array->Ptr + delta; } else { - void *scratch = get_scratch_vbo(ctx, size, - &a->bo, - &a->offset); - - memcpy(scratch, a->buf + delta, size); + int j, n = max_index - min_index + 1; + char *sp = (char *)array->Ptr + delta; + char *dp = get_scratch_vbo(ctx, n * a->stride, + &a->bo, &a->offset); + + for (j = 0; j < n; j++) + memcpy(dp + j * a->stride, + sp + j * array->StrideB, + a->stride); } } } diff --git a/src/mesa/drivers/dri/nouveau/nv04_context.c b/src/mesa/drivers/dri/nouveau/nv04_context.c index 1056171342..a442425e44 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_context.c +++ b/src/mesa/drivers/dri/nouveau/nv04_context.c @@ -40,6 +40,7 @@ nv04_context_engine(GLcontext *ctx) if (ctx->Texture.Unit[0].EnvMode == GL_COMBINE || ctx->Texture.Unit[0].EnvMode == GL_BLEND || + ctx->Texture.Unit[0].EnvMode == GL_ADD || ctx->Texture.Unit[1]._ReallyEnabled || ctx->Stencil.Enabled) fahrenheit = hw->eng3dm; @@ -264,7 +265,6 @@ const struct nouveau_driver nv04_driver = { nouveau_emit_nothing, nouveau_emit_nothing, nouveau_emit_nothing, - nouveau_emit_nothing, nv04_emit_scissor, nv04_defer_blend, nv04_defer_control, diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_fb.c b/src/mesa/drivers/dri/nouveau/nv04_state_fb.c index aad1e491d2..5e5e0c5874 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_state_fb.c +++ b/src/mesa/drivers/dri/nouveau/nv04_state_fb.c @@ -63,7 +63,7 @@ nv04_emit_framebuffer(GLcontext *ctx, int emit) return; /* Render target */ - if (fb->_NumColorDrawBuffers) { + if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_frag.c b/src/mesa/drivers/dri/nouveau/nv04_state_frag.c index 34ee296202..d7c86d4178 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_state_frag.c +++ b/src/mesa/drivers/dri/nouveau/nv04_state_frag.c @@ -41,6 +41,7 @@ NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ALPHA0 struct combiner_state { + GLcontext *ctx; int unit; GLboolean alpha; @@ -59,11 +60,12 @@ struct combiner_state { /* Initialize a combiner_state struct from the texture unit * context. */ -#define INIT_COMBINER(chan, rc, i) do { \ +#define INIT_COMBINER(chan, ctx, rc, i) do { \ struct gl_tex_env_combine_state *c = \ ctx->Texture.Unit[i]._CurrentCombine; \ - (rc)->alpha = __INIT_COMBINER_ALPHA_##chan; \ + (rc)->ctx = ctx; \ (rc)->unit = i; \ + (rc)->alpha = __INIT_COMBINER_ALPHA_##chan; \ (rc)->mode = c->Mode##chan; \ (rc)->source = c->Source##chan; \ (rc)->operand = c->Operand##chan; \ @@ -72,11 +74,11 @@ struct combiner_state { } while (0) /* Get the combiner source for the specified EXT_texture_env_combine - * argument. */ + * source. */ static uint32_t -get_arg_source(struct combiner_state *rc, int arg) +get_input_source(struct combiner_state *rc, int source) { - switch (rc->source[arg]) { + switch (source) { case GL_TEXTURE: return rc->unit ? COMBINER_SOURCE(TEXTURE1) : COMBINER_SOURCE(TEXTURE0); @@ -103,38 +105,53 @@ get_arg_source(struct combiner_state *rc, int arg) } /* Get the (possibly inverted) combiner input mapping for the - * specified argument. */ + * specified EXT_texture_env_combine operand. */ #define INVERT 0x1 static uint32_t -get_arg_mapping(struct combiner_state *rc, int arg, int flags) +get_input_mapping(struct combiner_state *rc, int operand, int flags) { int map = 0; - switch (rc->operand[arg]) { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - break; + if (!is_color_operand(operand) && !rc->alpha) + map |= COMBINER_ALPHA; - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - map |= rc->alpha ? 0 : COMBINER_ALPHA; - break; - } + if (is_negative_operand(operand) == !(flags & INVERT)) + map |= COMBINER_INVERT; - switch (rc->operand[arg]) { - case GL_SRC_COLOR: - case GL_SRC_ALPHA: - map |= flags & INVERT ? COMBINER_INVERT : 0; - break; + return map; +} - case GL_ONE_MINUS_SRC_COLOR: - case GL_ONE_MINUS_SRC_ALPHA: - map |= flags & INVERT ? 0 : COMBINER_INVERT; - break; +static uint32_t +get_input_arg(struct combiner_state *rc, int arg, int flags) +{ + int source = rc->source[arg]; + int operand = rc->operand[arg]; + + /* Fake several unsupported texture formats. */ + if (is_texture_source(source)) { + int i = (source == GL_TEXTURE ? + rc->unit : source - GL_TEXTURE0); + struct gl_texture_object *t = rc->ctx->Texture.Unit[i]._Current; + gl_format format = t->Image[0][t->BaseLevel]->TexFormat; + + if (format == MESA_FORMAT_A8) { + /* Emulated using I8. */ + if (is_color_operand(operand)) + return COMBINER_SOURCE(ZERO) | + get_input_mapping(rc, operand, flags); + + } else if (format == MESA_FORMAT_L8) { + /* Emulated using I8. */ + if (!is_color_operand(operand)) + return COMBINER_SOURCE(ZERO) | + get_input_mapping(rc, operand, + flags ^ INVERT); + } } - return map; + return get_input_source(rc, source) | + get_input_mapping(rc, operand, flags); } /* Bind the combiner input <in> to the combiner source <src>, @@ -146,8 +163,7 @@ get_arg_mapping(struct combiner_state *rc, int arg, int flags) /* Bind the combiner input <in> to the EXT_texture_env_combine * argument <arg>, possibly inverted. */ #define INPUT_ARG(rc, in, arg, flags) \ - (rc)->hw |= (get_arg_source(rc, arg) | \ - get_arg_mapping(rc, arg, flags)) << COMBINER_SHIFT(in) + (rc)->hw |= get_input_arg(rc, arg, flags) << COMBINER_SHIFT(in) #define UNSIGNED_OP(rc) \ (rc)->hw |= ((rc)->logscale ? \ @@ -222,10 +238,10 @@ nv04_emit_tex_env(GLcontext *ctx, int emit) /* Compute the new combiner state. */ if (ctx->Texture.Unit[i]._ReallyEnabled) { - INIT_COMBINER(A, &rc_a, i); + INIT_COMBINER(A, ctx, &rc_a, i); setup_combiner(&rc_a); - INIT_COMBINER(RGB, &rc_c, i); + INIT_COMBINER(RGB, ctx, &rc_c, i); setup_combiner(&rc_c); } else { diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_raster.c b/src/mesa/drivers/dri/nouveau/nv04_state_raster.c index 5e3788d185..c191571a5f 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_state_raster.c +++ b/src/mesa/drivers/dri/nouveau/nv04_state_raster.c @@ -61,12 +61,20 @@ get_stencil_op(unsigned op) switch (op) { case GL_KEEP: return 0x1; + case GL_ZERO: + return 0x2; + case GL_REPLACE: + return 0x3; case GL_INCR: return 0x4; case GL_DECR: return 0x5; case GL_INVERT: return 0x6; + case GL_INCR_WRAP: + return 0x7; + case GL_DECR_WRAP: + return 0x8; default: assert(0); } @@ -78,8 +86,6 @@ get_texenv_mode(unsigned mode) switch (mode) { case GL_REPLACE: return 0x1; - case GL_ADD: - return 0x2; case GL_DECAL: return 0x3; case GL_MODULATE: @@ -269,6 +275,10 @@ nv04_emit_blend(GLcontext *ctx, int emit) else blend |= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_FLAT; + /* Secondary color */ + if (NEED_SECONDARY_COLOR(ctx)) + blend |= NV04_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE; + /* Fog. */ if (ctx->Fog.Enabled) blend |= NV04_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE; @@ -298,7 +308,14 @@ nv04_emit_blend(GLcontext *ctx, int emit) blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT; /* Texture environment. */ - blend |= get_texenv_mode(ctx->Texture.Unit[0].EnvMode); + if (ctx->Texture._EnabledUnits) + blend |= get_texenv_mode(ctx->Texture.Unit[0].EnvMode); + else + blend |= get_texenv_mode(GL_MODULATE); + + /* Secondary color */ + if (NEED_SECONDARY_COLOR(ctx)) + blend |= NV04_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE; /* Fog. */ if (ctx->Fog.Enabled) diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_tex.c b/src/mesa/drivers/dri/nouveau/nv04_state_tex.c index 99ea310c65..6d8762b7d1 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_state_tex.c +++ b/src/mesa/drivers/dri/nouveau/nv04_state_tex.c @@ -38,6 +38,7 @@ get_tex_format(struct gl_texture_image *ti) switch (ti->TexFormat) { case MESA_FORMAT_A8: case MESA_FORMAT_L8: + case MESA_FORMAT_I8: return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_Y8; case MESA_FORMAT_ARGB1555: return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A1R5G5B5; @@ -47,6 +48,8 @@ get_tex_format(struct gl_texture_image *ti) return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_R5G6B5; case MESA_FORMAT_ARGB8888: return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A8R8G8B8; + case MESA_FORMAT_XRGB8888: + return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_X8R8G8B8; default: assert(0); } @@ -89,7 +92,9 @@ nv04_emit_tex_obj(GLcontext *ctx, int emit) struct gl_texture_image *ti = t->Image[0][t->BaseLevel]; int lod_max = 1, lod_bias = 0; - nouveau_texture_validate(ctx, t); + if (!nouveau_texture_validate(ctx, t)) + return; + s = &to_nouveau_texture(t)->surfaces[t->BaseLevel]; if (t->MinFilter != GL_NEAREST && diff --git a/src/mesa/drivers/dri/nouveau/nv04_surface.c b/src/mesa/drivers/dri/nouveau/nv04_surface.c index 86fa1dcd7a..e3febf7d2f 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_surface.c +++ b/src/mesa/drivers/dri/nouveau/nv04_surface.c @@ -216,8 +216,8 @@ nv04_surface_copy_swizzle(GLcontext *ctx, /* If area is too large to copy in one shot we must copy it in * POT chunks to meet alignment requirements */ - assert(sub_w == w || _mesa_is_pow_two(sub_w)); - assert(sub_h == h || _mesa_is_pow_two(sub_h)); + assert(sub_w == w || _mesa_is_pow_two(w)); + assert(sub_h == h || _mesa_is_pow_two(h)); nouveau_bo_marko(bctx, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, src->bo, bo_flags | NOUVEAU_BO_RD); @@ -239,8 +239,6 @@ nv04_surface_copy_swizzle(GLcontext *ctx, for (x = 0; x < w; x += sub_w) { sub_w = MIN2(sub_w, w - x); - /* Must be 64-byte aligned */ - assert(!(dst->offset & 63)); MARK_RING(chan, 15, 1); @@ -277,10 +275,10 @@ nv04_surface_copy_swizzle(GLcontext *ctx, static void nv04_surface_copy_m2mf(GLcontext *ctx, - struct nouveau_surface *dst, - struct nouveau_surface *src, - int dx, int dy, int sx, int sy, - int w, int h) + struct nouveau_surface *dst, + struct nouveau_surface *src, + int dx, int dy, int sx, int sy, + int w, int h) { struct nouveau_channel *chan = context_chan(ctx); struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; @@ -323,6 +321,82 @@ nv04_surface_copy_m2mf(GLcontext *ctx, FIRE_RING(chan); } +typedef unsigned (*get_offset_t)(struct nouveau_surface *s, + unsigned x, unsigned y); + +static unsigned +get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y) +{ + return x * s->cpp + y * s->pitch; +} + +static unsigned +get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y) +{ + unsigned k = log2i(MIN2(s->width, s->height)); + + unsigned u = (x & 0x001) << 0 | + (x & 0x002) << 1 | + (x & 0x004) << 2 | + (x & 0x008) << 3 | + (x & 0x010) << 4 | + (x & 0x020) << 5 | + (x & 0x040) << 6 | + (x & 0x080) << 7 | + (x & 0x100) << 8 | + (x & 0x200) << 9 | + (x & 0x400) << 10 | + (x & 0x800) << 11; + + unsigned v = (y & 0x001) << 1 | + (y & 0x002) << 2 | + (y & 0x004) << 3 | + (y & 0x008) << 4 | + (y & 0x010) << 5 | + (y & 0x020) << 6 | + (y & 0x040) << 7 | + (y & 0x080) << 8 | + (y & 0x100) << 9 | + (y & 0x200) << 10 | + (y & 0x400) << 11 | + (y & 0x800) << 12; + + return s->cpp * (((u | v) & ~(~0 << 2*k)) | + (x & (~0 << k)) << k | + (y & (~0 << k)) << k); +} + +static void +nv04_surface_copy_cpu(GLcontext *ctx, + struct nouveau_surface *dst, + struct nouveau_surface *src, + int dx, int dy, int sx, int sy, + int w, int h) +{ + int x, y; + get_offset_t get_dst = (dst->layout == SWIZZLED ? + get_swizzled_offset : get_linear_offset); + get_offset_t get_src = (src->layout == SWIZZLED ? + get_swizzled_offset : get_linear_offset); + void *dp, *sp; + + nouveau_bo_map(dst->bo, NOUVEAU_BO_WR); + nouveau_bo_map(src->bo, NOUVEAU_BO_RD); + + dp = dst->bo->map + dst->offset; + sp = src->bo->map + src->offset; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + memcpy(dp + get_dst(dst, dx + x, dy + y), + sp + get_src(src, sx + x, sy + y), dst->cpp); + } + } + + nouveau_bo_unmap(src->bo); + nouveau_bo_unmap(dst->bo); +} + void nv04_surface_copy(GLcontext *ctx, struct nouveau_surface *dst, @@ -330,16 +404,22 @@ nv04_surface_copy(GLcontext *ctx, int dx, int dy, int sx, int sy, int w, int h) { - /* Setup transfer to swizzle the texture to vram if needed */ - if (src->layout != SWIZZLED && - dst->layout == SWIZZLED && - dst->width > 2 && dst->height > 1) { - nv04_surface_copy_swizzle(ctx, dst, src, - dx, dy, sx, sy, w, h); + /* Linear texture copy. */ + if ((src->layout == LINEAR && dst->layout == LINEAR) || + dst->width <= 2 || dst->height <= 1) { + nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h); + return; + } + + /* Swizzle using sifm+swzsurf. */ + if (src->layout == LINEAR && dst->layout == SWIZZLED && + dst->cpp != 1 && !(dst->offset & 63)) { + nv04_surface_copy_swizzle(ctx, dst, src, dx, dy, sx, sy, w, h); return; } - nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h); + /* Fallback to CPU copy. */ + nv04_surface_copy_cpu(ctx, dst, src, dx, dy, sx, sy, w, h); } void @@ -369,7 +449,7 @@ nv04_surface_fill(GLcontext *ctx, BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_COLOR_FORMAT, 1); OUT_RING (chan, rect_format(dst->format)); BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_MONOCHROME_COLOR1, 1); - OUT_RING (chan, mask | ~0 << (8 * dst->cpp)); + OUT_RING (chan, mask | ~0ll << (8 * dst->cpp)); BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1); OUT_RING (chan, rect_format(dst->format)); @@ -484,34 +564,20 @@ nv04_surface_init(GLcontext *ctx) OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE); /* Swizzled surface. */ - switch (context_chipset(ctx) & 0xf0) { - case 0x00: - case 0x10: + if (context_chipset(ctx) < 0x20) class = NV04_SWIZZLED_SURFACE; - break; - case 0x20: + else class = NV20_SWIZZLED_SURFACE; - break; - default: - /* Famous last words: this really can't happen.. */ - assert(0); - break; - } ret = nouveau_grobj_alloc(chan, handle++, class, &hw->swzsurf); if (ret) goto fail; /* Scaled image from memory. */ - switch (context_chipset(ctx) & 0xf0) { - case 0x00: + if (context_chipset(ctx) < 0x10) class = NV04_SCALED_IMAGE_FROM_MEMORY; - break; - case 0x10: - case 0x20: + else class = NV10_SCALED_IMAGE_FROM_MEMORY; - break; - } ret = nouveau_grobj_alloc(chan, handle++, class, &hw->sifm); if (ret) diff --git a/src/mesa/drivers/dri/nouveau/nv10_context.c b/src/mesa/drivers/dri/nouveau/nv10_context.c index d80d99caa8..860d0aeb8f 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_context.c +++ b/src/mesa/drivers/dri/nouveau/nv10_context.c @@ -32,6 +32,11 @@ #include "nv04_driver.h" #include "nv10_driver.h" +static const struct dri_extension nv10_extensions[] = { + { "GL_EXT_texture_rectangle", NULL }, + { NULL, NULL } +}; + static void nv10_clear(GLcontext *ctx, GLbitfield buffers) { @@ -301,6 +306,8 @@ nv10_context_create(struct nouveau_screen *screen, const GLvisual *visual, if (!nouveau_context_init(ctx, screen, visual, share_ctx)) goto fail; + driInitExtensions(ctx, nv10_extensions, GL_FALSE); + /* GL constants. */ ctx->Const.MaxTextureLevels = 12; ctx->Const.MaxTextureCoordUnits = NV10_TEXTURE_UNITS; @@ -363,7 +370,6 @@ const struct nouveau_driver nv10_driver = { nv10_emit_frag, nv10_emit_framebuffer, nv10_emit_fog, - nv10_emit_index_mask, nv10_emit_light_enable, nv10_emit_light_model, nv10_emit_light_source, diff --git a/src/mesa/drivers/dri/nouveau/nv10_driver.h b/src/mesa/drivers/dri/nouveau/nv10_driver.h index 4c220b0373..d662712533 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_driver.h +++ b/src/mesa/drivers/dri/nouveau/nv10_driver.h @@ -100,9 +100,6 @@ void nv10_emit_dither(GLcontext *ctx, int emit); void -nv10_emit_index_mask(GLcontext *ctx, int emit); - -void nv10_emit_logic_opcode(GLcontext *ctx, int emit); void @@ -119,6 +116,14 @@ nv10_emit_stencil_op(GLcontext *ctx, int emit); /* nv10_state_frag.c */ void +nv10_get_general_combiner(GLcontext *ctx, int i, + uint32_t *a_in, uint32_t *a_out, + uint32_t *c_in, uint32_t *c_out, uint32_t *k); + +void +nv10_get_final_combiner(GLcontext *ctx, uint64_t *in, int *n); + +void nv10_emit_tex_env(GLcontext *ctx, int emit); void diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_fb.c b/src/mesa/drivers/dri/nouveau/nv10_state_fb.c index 05c36b4f8f..6bd383ebcd 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_fb.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_fb.c @@ -111,7 +111,7 @@ nv10_emit_framebuffer(GLcontext *ctx, int emit) } /* Render target */ - if (fb->_NumColorDrawBuffers) { + if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_frag.c b/src/mesa/drivers/dri/nouveau/nv10_state_frag.c index c1df26ecce..76b95fdd51 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_frag.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_frag.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Francisco Jerez. + * Copyright (C) 2009-2010 Francisco Jerez. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining @@ -90,11 +90,11 @@ struct combiner_state { } while (0) /* Get the RC input source for the specified EXT_texture_env_combine - * argument. */ + * source. */ static uint32_t -get_input_source(struct combiner_state *rc, int arg) +get_input_source(struct combiner_state *rc, int source) { - switch (rc->source[arg]) { + switch (source) { case GL_TEXTURE: return RC_IN_SOURCE(TEXTURE0) + rc->unit; @@ -127,52 +127,76 @@ get_input_source(struct combiner_state *rc, int arg) } } -/* Get the RC input mapping for the specified argument, possibly - * inverted or biased. */ +/* Get the RC input mapping for the specified texture_env_combine + * operand, possibly inverted or biased. */ #define INVERT 0x1 #define HALF_BIAS 0x2 static uint32_t -get_input_mapping(struct combiner_state *rc, int arg, int flags) +get_input_mapping(struct combiner_state *rc, int operand, int flags) { int map = 0; - switch (rc->operand[arg]) { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: + if (is_color_operand(operand)) map |= RC_IN_USAGE(RGB); - break; - - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: + else map |= RC_IN_USAGE(ALPHA); - break; - } - switch (rc->operand[arg]) { - case GL_SRC_COLOR: - case GL_SRC_ALPHA: - map |= (flags & INVERT ? RC_IN_MAPPING(UNSIGNED_INVERT) : - flags & HALF_BIAS ? RC_IN_MAPPING(HALF_BIAS_NORMAL) : - RC_IN_MAPPING(UNSIGNED_IDENTITY)); - break; + if (is_negative_operand(operand) == !(flags & INVERT)) + map |= flags & HALF_BIAS ? + RC_IN_MAPPING(HALF_BIAS_NEGATE) : + RC_IN_MAPPING(UNSIGNED_INVERT); + else + map |= flags & HALF_BIAS ? + RC_IN_MAPPING(HALF_BIAS_NORMAL) : + RC_IN_MAPPING(UNSIGNED_IDENTITY); - case GL_ONE_MINUS_SRC_COLOR: - case GL_ONE_MINUS_SRC_ALPHA: - map |= (flags & INVERT ? RC_IN_MAPPING(UNSIGNED_IDENTITY) : - flags & HALF_BIAS ? RC_IN_MAPPING(HALF_BIAS_NEGATE) : - RC_IN_MAPPING(UNSIGNED_INVERT)); - break; + return map; +} + +static uint32_t +get_input_arg(struct combiner_state *rc, int arg, int flags) +{ + int source = rc->source[arg]; + int operand = rc->operand[arg]; + + /* Fake several unsupported texture formats. */ + if (is_texture_source(source)) { + int i = (source == GL_TEXTURE ? + rc->unit : source - GL_TEXTURE0); + struct gl_texture_object *t = rc->ctx->Texture.Unit[i]._Current; + gl_format format = t->Image[0][t->BaseLevel]->TexFormat; + + if (format == MESA_FORMAT_A8) { + /* Emulated using I8. */ + if (is_color_operand(operand)) + return RC_IN_SOURCE(ZERO) | + get_input_mapping(rc, operand, flags); + + } else if (format == MESA_FORMAT_L8) { + /* Sometimes emulated using I8. */ + if (!is_color_operand(operand)) + return RC_IN_SOURCE(ZERO) | + get_input_mapping(rc, operand, + flags ^ INVERT); + + } else if (format == MESA_FORMAT_XRGB8888) { + /* Sometimes emulated using ARGB8888. */ + if (!is_color_operand(operand)) + return RC_IN_SOURCE(ZERO) | + get_input_mapping(rc, operand, + flags ^ INVERT); + } } - return map; + return get_input_source(rc, source) | + get_input_mapping(rc, operand, flags); } /* Bind the RC input variable <var> to the EXT_texture_env_combine * argument <arg>, possibly inverted or biased. */ #define INPUT_ARG(rc, var, arg, flags) \ - (rc)->in |= (get_input_mapping(rc, arg, flags) | \ - get_input_source(rc, arg)) << RC_IN_SHIFT_##var + (rc)->in |= get_input_arg(rc, arg, flags) << RC_IN_SHIFT_##var /* Bind the RC input variable <var> to the RC source <src>. */ #define INPUT_SRC(rc, var, src, chan) \ @@ -268,86 +292,13 @@ setup_combiner(struct combiner_state *rc) } } -/* Write the register combiner state out to the hardware. */ -static void -nv10_load_combiner(GLcontext *ctx, int i, struct combiner_state *rc_a, - struct combiner_state *rc_c, uint32_t rc_const) -{ - struct nouveau_channel *chan = context_chan(ctx); - struct nouveau_grobj *celsius = context_eng3d(ctx); - - /* Enable the combiners we're going to need. */ - if (i == 1) { - if (rc_c->out || rc_a->out) - rc_c->out |= 0x5 << 27; - else - rc_c->out |= 0x3 << 27; - } - - BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(i), 1); - OUT_RING(chan, rc_a->in); - BEGIN_RING(chan, celsius, NV10TCL_RC_IN_RGB(i), 1); - OUT_RING(chan, rc_c->in); - BEGIN_RING(chan, celsius, NV10TCL_RC_COLOR(i), 1); - OUT_RING(chan, rc_const); - BEGIN_RING(chan, celsius, NV10TCL_RC_OUT_ALPHA(i), 1); - OUT_RING(chan, rc_a->out); - BEGIN_RING(chan, celsius, NV10TCL_RC_OUT_RGB(i), 1); - OUT_RING(chan, rc_c->out); -} - -static void -nv10_load_final(GLcontext *ctx, struct combiner_state *rc, int n) -{ - struct nouveau_channel *chan = context_chan(ctx); - struct nouveau_grobj *celsius = context_eng3d(ctx); - - BEGIN_RING(chan, celsius, NV10TCL_RC_FINAL0, 2); - OUT_RING(chan, rc->in); - OUT_RING(chan, rc->in >> 32); -} - -static void -nv20_load_combiner(GLcontext *ctx, int i, struct combiner_state *rc_a, - struct combiner_state *rc_c, uint32_t rc_const) -{ - struct nouveau_channel *chan = context_chan(ctx); - struct nouveau_grobj *kelvin = context_eng3d(ctx); - - BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_ALPHA(i), 1); - OUT_RING(chan, rc_a->in); - BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_ALPHA(i), 1); - OUT_RING(chan, rc_a->out); - BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_RGB(i), 1); - OUT_RING(chan, rc_c->in); - BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_RGB(i), 1); - OUT_RING(chan, rc_c->out); - BEGIN_RING(chan, kelvin, NV20TCL_RC_CONSTANT_COLOR0(i), 1); - OUT_RING(chan, rc_const); -} - -static void -nv20_load_final(GLcontext *ctx, struct combiner_state *rc, int n) -{ - struct nouveau_channel *chan = context_chan(ctx); - struct nouveau_grobj *kelvin = context_eng3d(ctx); - - BEGIN_RING(chan, kelvin, NV20TCL_RC_FINAL0, 2); - OUT_RING(chan, rc->in); - OUT_RING(chan, rc->in >> 32); - - BEGIN_RING(chan, kelvin, NV20TCL_RC_ENABLE, 1); - OUT_RING(chan, n); -} - void -nv10_emit_tex_env(GLcontext *ctx, int emit) +nv10_get_general_combiner(GLcontext *ctx, int i, + uint32_t *a_in, uint32_t *a_out, + uint32_t *c_in, uint32_t *c_out, uint32_t *k) { - const int i = emit - NOUVEAU_STATE_TEX_ENV0; struct combiner_state rc_a, rc_c; - uint32_t rc_const; - /* Compute the new combiner state. */ if (ctx->Texture.Unit[i]._ReallyEnabled) { INIT_COMBINER(RGB, ctx, &rc_c, i); @@ -359,26 +310,22 @@ nv10_emit_tex_env(GLcontext *ctx, int emit) setup_combiner(&rc_c); setup_combiner(&rc_a); - rc_const = pack_rgba_f(MESA_FORMAT_ARGB8888, - ctx->Texture.Unit[i].EnvColor); - } else { - rc_a.in = rc_a.out = rc_c.in = rc_c.out = rc_const = 0; + rc_a.in = rc_a.out = rc_c.in = rc_c.out = 0; } - if (context_chipset(ctx) >= 0x20) - nv20_load_combiner(ctx, i, &rc_a, &rc_c, rc_const); - else - nv10_load_combiner(ctx, i, &rc_a, &rc_c, rc_const); - - context_dirty(ctx, FRAG); + *k = pack_rgba_f(MESA_FORMAT_ARGB8888, + ctx->Texture.Unit[i].EnvColor); + *a_in = rc_a.in; + *a_out = rc_a.out; + *c_in = rc_c.in; + *c_out = rc_c.out; } void -nv10_emit_frag(GLcontext *ctx, int emit) +nv10_get_final_combiner(GLcontext *ctx, uint64_t *in, int *n) { struct combiner_state rc = {}; - int n = log2i(ctx->Texture._EnabledUnits) + 1; /* * The final fragment value equation is something like: @@ -409,8 +356,53 @@ nv10_emit_frag(GLcontext *ctx, int emit) INPUT_SRC(&rc, G, PRIMARY_COLOR, ALPHA); } - if (context_chipset(ctx) >= 0x20) - nv20_load_final(ctx, &rc, n); - else - nv10_load_final(ctx, &rc, n); + *in = rc.in; + *n = log2i(ctx->Texture._EnabledUnits) + 1; +} + +void +nv10_emit_tex_env(GLcontext *ctx, int emit) +{ + const int i = emit - NOUVEAU_STATE_TEX_ENV0; + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *celsius = context_eng3d(ctx); + uint32_t a_in, a_out, c_in, c_out, k; + + nv10_get_general_combiner(ctx, i, &a_in, &a_out, &c_in, &c_out, &k); + + /* Enable the combiners we're going to need. */ + if (i == 1) { + if (c_out || a_out) + c_out |= 0x5 << 27; + else + c_out |= 0x3 << 27; + } + + BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(i), 1); + OUT_RING(chan, a_in); + BEGIN_RING(chan, celsius, NV10TCL_RC_IN_RGB(i), 1); + OUT_RING(chan, c_in); + BEGIN_RING(chan, celsius, NV10TCL_RC_COLOR(i), 1); + OUT_RING(chan, k); + BEGIN_RING(chan, celsius, NV10TCL_RC_OUT_ALPHA(i), 1); + OUT_RING(chan, a_out); + BEGIN_RING(chan, celsius, NV10TCL_RC_OUT_RGB(i), 1); + OUT_RING(chan, c_out); + + context_dirty(ctx, FRAG); +} + +void +nv10_emit_frag(GLcontext *ctx, int emit) +{ + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *celsius = context_eng3d(ctx); + uint64_t in; + int n; + + nv10_get_final_combiner(ctx, &in, &n); + + BEGIN_RING(chan, celsius, NV10TCL_RC_FINAL0, 2); + OUT_RING(chan, in); + OUT_RING(chan, in >> 32); } diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_raster.c b/src/mesa/drivers/dri/nouveau/nv10_state_raster.c index 68882ef05f..a62cd807a9 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_raster.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_raster.c @@ -119,11 +119,6 @@ nv10_emit_dither(GLcontext *ctx, int emit) } void -nv10_emit_index_mask(GLcontext *ctx, int emit) -{ -} - -void nv10_emit_logic_opcode(GLcontext *ctx, int emit) { struct nouveau_channel *chan = context_chan(ctx); diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c index e5d4f3d18d..02a5ca797a 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c @@ -38,12 +38,15 @@ nv10_emit_tex_gen(GLcontext *ctx, int emit) } static uint32_t -get_tex_format(struct gl_texture_image *ti) +get_tex_format_pot(struct gl_texture_image *ti) { switch (ti->TexFormat) { case MESA_FORMAT_ARGB8888: return NV10TCL_TX_FORMAT_FORMAT_A8R8G8B8; + case MESA_FORMAT_XRGB8888: + return NV10TCL_TX_FORMAT_FORMAT_X8R8G8B8; + case MESA_FORMAT_ARGB1555: return NV10TCL_TX_FORMAT_FORMAT_A1R5G5B5; @@ -54,6 +57,7 @@ get_tex_format(struct gl_texture_image *ti) return NV10TCL_TX_FORMAT_FORMAT_R5G6B5; case MESA_FORMAT_A8: + case MESA_FORMAT_I8: return NV10TCL_TX_FORMAT_FORMAT_A8; case MESA_FORMAT_L8: @@ -67,6 +71,30 @@ get_tex_format(struct gl_texture_image *ti) } } +static uint32_t +get_tex_format_rect(struct gl_texture_image *ti) +{ + switch (ti->TexFormat) { + case MESA_FORMAT_ARGB1555: + return NV10TCL_TX_FORMAT_FORMAT_A1R5G5B5_RECT; + + case MESA_FORMAT_RGB565: + return NV10TCL_TX_FORMAT_FORMAT_R5G6B5_RECT; + + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_XRGB8888: + return NV10TCL_TX_FORMAT_FORMAT_A8R8G8B8_RECT; + + case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + return NV10TCL_TX_FORMAT_FORMAT_A8_RECT; + + default: + assert(0); + } +} + void nv10_emit_tex_obj(GLcontext *ctx, int emit) { @@ -90,14 +118,14 @@ nv10_emit_tex_obj(GLcontext *ctx, int emit) s = &to_nouveau_texture(t)->surfaces[t->BaseLevel]; ti = t->Image[0][t->BaseLevel]; - nouveau_texture_validate(ctx, t); + if (!nouveau_texture_validate(ctx, t)) + return; /* Recompute the texturing registers. */ tx_format = nvgl_wrap_mode(t->WrapT) << 28 | nvgl_wrap_mode(t->WrapS) << 24 | ti->HeightLog2 << 20 | ti->WidthLog2 << 16 - | get_tex_format(ti) | 5 << 4 | 1 << 12; tx_filter = nvgl_filter_mode(t->MagFilter) << 28 @@ -106,6 +134,17 @@ nv10_emit_tex_obj(GLcontext *ctx, int emit) tx_enable = NV10TCL_TX_ENABLE_ENABLE | log2i(t->MaxAnisotropy) << 4; + if (t->Target == GL_TEXTURE_RECTANGLE) { + BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_PITCH(i), 1); + OUT_RING(chan, s->pitch << 16); + BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_SIZE(i), 1); + OUT_RING(chan, align(s->width, 2) << 16 | s->height); + + tx_format |= get_tex_format_rect(ti); + } else { + tx_format |= get_tex_format_pot(ti); + } + if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) { int lod_min = t->MinLod; diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c index 6db14d83b8..406e24c455 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c @@ -201,8 +201,10 @@ nv10_emit_light_model(GLcontext *ctx, int emit) BEGIN_RING(chan, celsius, NV10TCL_LIGHT_MODEL, 1); OUT_RING(chan, ((m->LocalViewer ? NV10TCL_LIGHT_MODEL_LOCAL_VIEWER : 0) | - (m->ColorControl == GL_SEPARATE_SPECULAR_COLOR ? - NV10TCL_LIGHT_MODEL_SEPARATE_SPECULAR : 0))); + (NEED_SECONDARY_COLOR(ctx) ? + NV10TCL_LIGHT_MODEL_SEPARATE_SPECULAR : 0) | + (!ctx->Light.Enabled && ctx->Fog.ColorSumEnabled ? + NV10TCL_LIGHT_MODEL_VERTEX_SPECULAR : 0))); } static float diff --git a/src/mesa/drivers/dri/nouveau/nv20_context.c b/src/mesa/drivers/dri/nouveau/nv20_context.c index 82a13fb6ff..db39ef7075 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_context.c +++ b/src/mesa/drivers/dri/nouveau/nv20_context.c @@ -31,6 +31,11 @@ #include "nv10_driver.h" #include "nv20_driver.h" +static const struct dri_extension nv20_extensions[] = { + { "GL_EXT_texture_rectangle", NULL }, + { NULL, NULL } +}; + static void nv20_hwctx_init(GLcontext *ctx) { @@ -394,6 +399,8 @@ nv20_context_create(struct nouveau_screen *screen, const GLvisual *visual, if (!nouveau_context_init(ctx, screen, visual, share_ctx)) goto fail; + driInitExtensions(ctx, nv20_extensions, GL_FALSE); + /* GL constants. */ ctx->Const.MaxTextureCoordUnits = NV20_TEXTURE_UNITS; ctx->Const.MaxTextureImageUnits = NV20_TEXTURE_UNITS; @@ -449,10 +456,9 @@ const struct nouveau_driver nv20_driver = { nv10_emit_front_face, nv10_emit_depth, nv10_emit_dither, - nv10_emit_frag, + nv20_emit_frag, nv20_emit_framebuffer, nv20_emit_fog, - nv10_emit_index_mask, nv10_emit_light_enable, nv20_emit_light_model, nv20_emit_light_source, @@ -487,10 +493,10 @@ const struct nouveau_driver nv20_driver = { nv10_emit_stencil_func, nv10_emit_stencil_mask, nv10_emit_stencil_op, - nv10_emit_tex_env, - nv10_emit_tex_env, - nv10_emit_tex_env, - nv10_emit_tex_env, + nv20_emit_tex_env, + nv20_emit_tex_env, + nv20_emit_tex_env, + nv20_emit_tex_env, nv10_emit_tex_gen, nv10_emit_tex_gen, nv10_emit_tex_gen, diff --git a/src/mesa/drivers/dri/nouveau/nv20_driver.h b/src/mesa/drivers/dri/nouveau/nv20_driver.h index f82a292cf7..18574e9be6 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_driver.h +++ b/src/mesa/drivers/dri/nouveau/nv20_driver.h @@ -59,6 +59,13 @@ nv20_emit_point_mode(GLcontext *ctx, int emit); void nv20_emit_logic_opcode(GLcontext *ctx, int emit); +/* nv20_state_frag.c */ +void +nv20_emit_tex_env(GLcontext *ctx, int emit); + +void +nv20_emit_frag(GLcontext *ctx, int emit); + /* nv20_state_tex.c */ void nv20_emit_tex_obj(GLcontext *ctx, int emit); diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_fb.c b/src/mesa/drivers/dri/nouveau/nv20_state_fb.c index 869acd6e31..d638541df9 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_fb.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_fb.c @@ -67,7 +67,7 @@ nv20_emit_framebuffer(GLcontext *ctx, int emit) return; /* Render target */ - if (fb->_NumColorDrawBuffers) { + if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_frag.c b/src/mesa/drivers/dri/nouveau/nv20_state_frag.c new file mode 100644 index 0000000000..74803d2ae8 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nv20_state_frag.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2009-2010 Francisco Jerez. + * 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 "nouveau_driver.h" +#include "nouveau_context.h" +#include "nouveau_class.h" +#include "nv10_driver.h" +#include "nv20_driver.h" + +void +nv20_emit_tex_env(GLcontext *ctx, int emit) +{ + const int i = emit - NOUVEAU_STATE_TEX_ENV0; + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *kelvin = context_eng3d(ctx); + uint32_t a_in, a_out, c_in, c_out, k; + + nv10_get_general_combiner(ctx, i, &a_in, &a_out, &c_in, &c_out, &k); + + BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_ALPHA(i), 1); + OUT_RING(chan, a_in); + BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_ALPHA(i), 1); + OUT_RING(chan, a_out); + BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_RGB(i), 1); + OUT_RING(chan, c_in); + BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_RGB(i), 1); + OUT_RING(chan, c_out); + BEGIN_RING(chan, kelvin, NV20TCL_RC_CONSTANT_COLOR0(i), 1); + OUT_RING(chan, k); + + context_dirty(ctx, FRAG); +} + +void +nv20_emit_frag(GLcontext *ctx, int emit) +{ + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *kelvin = context_eng3d(ctx); + uint64_t in; + int n; + + nv10_get_final_combiner(ctx, &in, &n); + + BEGIN_RING(chan, kelvin, NV20TCL_RC_FINAL0, 2); + OUT_RING(chan, in); + OUT_RING(chan, in >> 32); + + BEGIN_RING(chan, kelvin, NV20TCL_RC_ENABLE, 1); + OUT_RING(chan, n); +} diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c index d01e91f8ee..92870105f9 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c @@ -33,7 +33,7 @@ #include "nv20_driver.h" static uint32_t -get_tex_format(struct gl_texture_image *ti) +get_tex_format_pot(struct gl_texture_image *ti) { switch (ti->TexFormat) { case MESA_FORMAT_ARGB8888: @@ -45,10 +45,14 @@ get_tex_format(struct gl_texture_image *ti) case MESA_FORMAT_ARGB4444: return NV20TCL_TX_FORMAT_FORMAT_A4R4G4B4; + case MESA_FORMAT_XRGB8888: + return NV20TCL_TX_FORMAT_FORMAT_X8R8G8B8; + case MESA_FORMAT_RGB565: return NV20TCL_TX_FORMAT_FORMAT_R5G6B5; case MESA_FORMAT_A8: + case MESA_FORMAT_I8: return NV20TCL_TX_FORMAT_FORMAT_A8; case MESA_FORMAT_L8: @@ -62,6 +66,37 @@ get_tex_format(struct gl_texture_image *ti) } } +static uint32_t +get_tex_format_rect(struct gl_texture_image *ti) +{ + switch (ti->TexFormat) { + case MESA_FORMAT_ARGB8888: + return NV20TCL_TX_FORMAT_FORMAT_A8R8G8B8_RECT; + + case MESA_FORMAT_ARGB1555: + return NV20TCL_TX_FORMAT_FORMAT_A1R5G5B5_RECT; + + case MESA_FORMAT_ARGB4444: + return NV20TCL_TX_FORMAT_FORMAT_A4R4G4B4_RECT; + + case MESA_FORMAT_XRGB8888: + return NV20TCL_TX_FORMAT_FORMAT_R8G8B8_RECT; + + case MESA_FORMAT_RGB565: + return NV20TCL_TX_FORMAT_FORMAT_R5G6B5_RECT; + + case MESA_FORMAT_L8: + return NV20TCL_TX_FORMAT_FORMAT_L8_RECT; + + case MESA_FORMAT_A8: + case MESA_FORMAT_I8: + return NV20TCL_TX_FORMAT_FORMAT_A8_RECT; + + default: + assert(0); + } +} + void nv20_emit_tex_obj(GLcontext *ctx, int emit) { @@ -87,13 +122,13 @@ nv20_emit_tex_obj(GLcontext *ctx, int emit) s = &to_nouveau_texture(t)->surfaces[t->BaseLevel]; ti = t->Image[0][t->BaseLevel]; - nouveau_texture_validate(ctx, t); + if (!nouveau_texture_validate(ctx, t)) + return; /* Recompute the texturing registers. */ tx_format = ti->DepthLog2 << 28 | ti->HeightLog2 << 24 | ti->WidthLog2 << 20 - | get_tex_format(ti) | NV20TCL_TX_FORMAT_DIMS_2D | NV20TCL_TX_FORMAT_NO_BORDER | 1 << 16; @@ -108,6 +143,17 @@ nv20_emit_tex_obj(GLcontext *ctx, int emit) tx_enable = NV20TCL_TX_ENABLE_ENABLE | log2i(t->MaxAnisotropy) << 4; + if (t->Target == GL_TEXTURE_RECTANGLE) { + BEGIN_RING(chan, kelvin, NV20TCL_TX_NPOT_PITCH(i), 1); + OUT_RING(chan, s->pitch << 16); + BEGIN_RING(chan, kelvin, NV20TCL_TX_NPOT_SIZE(i), 1); + OUT_RING(chan, s->width << 16 | s->height); + + tx_format |= get_tex_format_rect(ti); + } else { + tx_format |= get_tex_format_pot(ti); + } + if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) { int lod_min = t->MinLod; diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c index 0d566064f6..43f8c72312 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c @@ -158,7 +158,7 @@ nv20_emit_light_model(GLcontext *ctx, int emit) OUT_RING(chan, ((m->LocalViewer ? NV20TCL_LIGHT_MODEL_VIEWER_LOCAL : NV20TCL_LIGHT_MODEL_VIEWER_NONLOCAL) | - (m->ColorControl == GL_SEPARATE_SPECULAR_COLOR ? + (NEED_SECONDARY_COLOR(ctx) ? NV20TCL_LIGHT_MODEL_SEPARATE_SPECULAR : 0))); |