summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/nouveau')
-rw-r--r--src/mesa/drivers/dri/nouveau/Makefile3
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c6
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.c104
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.h13
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_driver.c6
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_driver.h2
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_fbo.c7
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_screen.c8
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_span.c11
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_state.c12
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_state.h1
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_texture.c402
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_texture.h8
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_util.h18
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c73
-rw-r--r--src/mesa/drivers/dri/nouveau/nv04_context.c2
-rw-r--r--src/mesa/drivers/dri/nouveau/nv04_state_fb.c2
-rw-r--r--src/mesa/drivers/dri/nouveau/nv04_state_frag.c76
-rw-r--r--src/mesa/drivers/dri/nouveau/nv04_state_raster.c23
-rw-r--r--src/mesa/drivers/dri/nouveau/nv04_state_tex.c7
-rw-r--r--src/mesa/drivers/dri/nouveau/nv04_surface.c134
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_context.c8
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_driver.h11
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_state_fb.c2
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_state_frag.c240
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_state_raster.c5
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_state_tex.c45
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_state_tnl.c6
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_context.c18
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_driver.h7
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_state_fb.c2
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_state_frag.c73
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_state_tex.c52
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_state_tnl.c2
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)));