summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/nouveau/Makefile1
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_buffers.c331
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_buffers.h41
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.c79
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.h20
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_driver.c29
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_driver.h5
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_lock.c18
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_object.c23
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_object.h9
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_screen.c128
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader.c2
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader.h2
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_span.c14
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_span.h3
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_state.c42
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_state.h6
-rw-r--r--src/mesa/drivers/dri/nouveau/nv30_fragprog.c29
-rw-r--r--src/mesa/drivers/dri/nouveau/nv30_state.c152
19 files changed, 784 insertions, 150 deletions
diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile
index 384713eeeb7..1a76169156a 100644
--- a/src/mesa/drivers/dri/nouveau/Makefile
+++ b/src/mesa/drivers/dri/nouveau/Makefile
@@ -8,6 +8,7 @@ LIBNAME = nouveau_dri.so
MINIGLX_SOURCES =
DRIVER_SOURCES = \
+ nouveau_buffers.c \
nouveau_card.c \
nouveau_context.c \
nouveau_driver.c \
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
new file mode 100644
index 00000000000..a356fd12129
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
@@ -0,0 +1,331 @@
+#include "utils.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "fbobject.h"
+
+#include "nouveau_context.h"
+#include "nouveau_buffers.h"
+
+void
+nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ drm_nouveau_mem_free_t memf;
+
+ if (mem->map)
+ drmUnmap(mem->map, mem->size);
+ memf.flags = mem->type;
+ memf.region_offset = mem->offset;
+ drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf, sizeof(memf));
+ FREE(mem);
+}
+
+nouveau_mem *
+nouveau_mem_alloc(GLcontext *ctx, int type, GLuint size, GLuint align)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ drm_nouveau_mem_alloc_t mema;
+ nouveau_mem *mem;
+ int ret;
+
+ mem = CALLOC(sizeof(nouveau_mem));
+ if (!mem)
+ return NULL;
+
+ mema.flags = mem->type = type;
+ mema.size = mem->size = size;
+ mema.alignment = align;
+ mem->map = NULL;
+ ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC,
+ &mema, sizeof(mema));
+ if (ret) {
+ FREE(mem);
+ return NULL;
+ }
+ mem->offset = mema.region_offset;
+
+ if (type & NOUVEAU_MEM_MAPPED)
+ ret = drmMap(nmesa->driFd, mem->offset, mem->size, &mem->map);
+ if (ret) {
+ mem->map = NULL;
+ nouveau_mem_free(ctx, mem);
+ mem = NULL;
+ }
+
+ return mem;
+}
+
+uint32_t
+nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (mem->type & NOUVEAU_MEM_FB)
+ return (uint32_t)mem->offset - nmesa->vram_phys;
+ else if (mem->type & NOUVEAU_MEM_AGP)
+ return (uint32_t)mem->offset - nmesa->agp_phys;
+ else
+ return 0xDEADF00D;
+}
+
+static GLboolean
+nouveau_renderbuffer_pixelformat(nouveau_renderbuffer *nrb,
+ GLenum internalFormat)
+{
+ nrb->mesa.InternalFormat = internalFormat;
+
+ /*TODO: We probably want to extend this a bit, and maybe make
+ * card-specific?
+ */
+ switch (internalFormat) {
+ case GL_RGBA:
+ case GL_RGBA8:
+ nrb->mesa._BaseFormat = GL_RGBA;
+ nrb->mesa._ActualFormat= GL_RGBA8;
+ nrb->mesa.DataType = GL_UNSIGNED_BYTE;
+ nrb->mesa.RedBits = 8;
+ nrb->mesa.GreenBits = 8;
+ nrb->mesa.BlueBits = 8;
+ nrb->mesa.AlphaBits = 8;
+ nrb->cpp = 4;
+ break;
+ case GL_RGB5:
+ nrb->mesa._BaseFormat = GL_RGB;
+ nrb->mesa._ActualFormat= GL_RGB5;
+ nrb->mesa.DataType = GL_UNSIGNED_BYTE;
+ nrb->mesa.RedBits = 5;
+ nrb->mesa.GreenBits = 6;
+ nrb->mesa.BlueBits = 5;
+ nrb->mesa.AlphaBits = 0;
+ nrb->cpp = 2;
+ break;
+ case GL_DEPTH_COMPONENT16:
+ nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT;
+ nrb->mesa._ActualFormat= GL_DEPTH_COMPONENT16;
+ nrb->mesa.DataType = GL_UNSIGNED_SHORT;
+ nrb->mesa.DepthBits = 16;
+ nrb->cpp = 2;
+ break;
+ case GL_DEPTH_COMPONENT24:
+ nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT;
+ nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+ nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ nrb->mesa.DepthBits = 24;
+ nrb->cpp = 4;
+ break;
+ case GL_STENCIL_INDEX8_EXT:
+ nrb->mesa._BaseFormat = GL_STENCIL_INDEX;
+ nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+ nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ nrb->mesa.StencilBits = 8;
+ nrb->cpp = 4;
+ break;
+ case GL_DEPTH24_STENCIL8_EXT:
+ nrb->mesa._BaseFormat = GL_DEPTH_STENCIL_EXT;
+ nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+ nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ nrb->mesa.DepthBits = 24;
+ nrb->mesa.StencilBits = 8;
+ nrb->cpp = 4;
+ break;
+ default:
+ return GL_FALSE;
+ break;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean
+nouveau_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width,
+ GLuint height)
+{
+ nouveau_renderbuffer *nrb = (nouveau_renderbuffer*)rb;
+
+ if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) {
+ fprintf(stderr, "%s: unknown internalFormat\n", __func__);
+ return GL_FALSE;
+ }
+
+ /* If this buffer isn't statically alloc'd, we may need to ask the
+ * drm for more memory */
+ if (!nrb->map && (rb->Width != width || rb->Height != height)) {
+ GLuint pitch;
+
+ /* align pitches to 64 bytes */
+ pitch = ((width * nrb->cpp) + 63) & ~63;
+
+ if (nrb->mem)
+ nouveau_mem_free(ctx, nrb->mem);
+ nrb->mem = nouveau_mem_alloc(ctx,
+ NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED,
+ pitch*height,
+ 0);
+ if (!nrb->mem)
+ return GL_FALSE;
+
+ /* update nouveau_renderbuffer info */
+ nrb->offset = nouveau_mem_gpu_offset_get(ctx, nrb->mem);
+ nrb->pitch = pitch;
+ }
+
+ rb->Width = width;
+ rb->Height = height;
+ rb->InternalFormat = internalFormat;
+ return GL_TRUE;
+}
+
+static void
+nouveau_renderbuffer_delete(struct gl_renderbuffer *rb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ nouveau_renderbuffer *nrb = (nouveau_renderbuffer*)rb;
+
+ if (nrb->mem)
+ nouveau_mem_free(ctx, nrb->mem);
+ FREE(nrb);
+}
+
+nouveau_renderbuffer *
+nouveau_renderbuffer_new(GLenum internalFormat, GLvoid *map,
+ GLuint offset, GLuint pitch,
+ __DRIdrawablePrivate *dPriv)
+{
+ nouveau_renderbuffer *nrb;
+
+ nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
+ if (nrb) {
+ _mesa_init_renderbuffer(&nrb->mesa, 0);
+
+ nouveau_renderbuffer_pixelformat(nrb, internalFormat);
+
+ nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
+ nrb->mesa.Delete = nouveau_renderbuffer_delete;
+
+ nrb->dPriv = dPriv;
+ nrb->offset = offset;
+ nrb->pitch = pitch;
+ nrb->map = map;
+ }
+
+ return nrb;
+}
+
+void
+nouveau_window_moved(GLcontext *ctx)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ /* Viewport depends on window size/position, nouveauCalcViewport
+ * will take care of calling the hw-specific WindowMoved
+ */
+ ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height);
+ /* Scissor depends on window position */
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+GLboolean
+nouveau_build_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_renderbuffer *color[MAX_DRAW_BUFFERS];
+ nouveau_renderbuffer *depth;
+
+ _mesa_update_framebuffer(ctx);
+ _mesa_update_draw_buffer_bounds(ctx);
+
+ color[0] = (nouveau_renderbuffer *)fb->_ColorDrawBuffers[0][0];
+ depth = (nouveau_renderbuffer *)fb->_DepthBuffer;
+
+ if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth))
+ return GL_FALSE;
+ nouveau_window_moved(ctx);
+
+ return GL_TRUE;
+}
+
+nouveau_renderbuffer *
+nouveau_current_draw_buffer(GLcontext *ctx)
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ nouveau_renderbuffer *nrb;
+
+ if (!fb)
+ return NULL;
+
+ if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT)
+ nrb = (nouveau_renderbuffer *)
+ fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT)
+ nrb = (nouveau_renderbuffer *)
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ else
+ nrb = NULL;
+ return nrb;
+}
+
+static struct gl_framebuffer *
+nouveauNewFramebuffer(GLcontext *ctx, GLuint name)
+{
+ return _mesa_new_framebuffer(ctx, name);
+}
+
+static struct gl_renderbuffer *
+nouveauNewRenderbuffer(GLcontext *ctx, GLuint name)
+{
+ nouveau_renderbuffer *nrb;
+
+ nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
+ if (nrb) {
+ _mesa_init_renderbuffer(&nrb->mesa, name);
+
+ nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
+ nrb->mesa.Delete = nouveau_renderbuffer_delete;
+ }
+ return &nrb->mesa;
+}
+
+static void
+nouveauBindFramebuffer(GLcontext *ctx, GLenum target, struct gl_framebuffer *fb)
+{
+ nouveau_build_framebuffer(ctx, fb);
+}
+
+static void
+nouveauFramebufferRenderbuffer(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb)
+{
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+ nouveau_build_framebuffer(ctx, fb);
+}
+
+static void
+nouveauRenderTexture(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att)
+{
+}
+
+static void
+nouveauFinishRenderTexture(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+}
+
+void
+nouveauInitBufferFuncs(struct dd_function_table *func)
+{
+ func->NewFramebuffer = nouveauNewFramebuffer;
+ func->NewRenderbuffer = nouveauNewRenderbuffer;
+ func->BindFramebuffer = nouveauBindFramebuffer;
+ func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer;
+ func->RenderTexture = nouveauRenderTexture;
+ func->FinishRenderTexture = nouveauFinishRenderTexture;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
new file mode 100644
index 00000000000..bb297ad5587
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
@@ -0,0 +1,41 @@
+#ifndef __NOUVEAU_BUFFERS_H__
+#define __NOUVEAU_BUFFERS_H__
+
+#include <stdint.h>
+#include "mtypes.h"
+#include "utils.h"
+#include "renderbuffer.h"
+
+typedef struct nouveau_mem_t {
+ int type;
+ uint64_t offset;
+ uint64_t size;
+ void* map;
+} nouveau_mem;
+
+extern nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, int type,
+ GLuint size, GLuint align);
+extern void nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem);
+extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem);
+
+typedef struct nouveau_renderbuffer_t {
+ struct gl_renderbuffer mesa; /* must be first! */
+ __DRIdrawablePrivate *dPriv;
+
+ nouveau_mem *mem;
+ void * map;
+
+ int cpp;
+ uint32_t offset;
+ uint32_t pitch;
+} nouveau_renderbuffer;
+
+extern nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat,
+ GLvoid *map, GLuint offset, GLuint pitch, __DRIdrawablePrivate *dPriv);
+extern void nouveau_window_moved(GLcontext *ctx);
+extern GLboolean nouveau_build_framebuffer(GLcontext *, struct gl_framebuffer *);
+extern nouveau_renderbuffer *nouveau_current_draw_buffer(GLcontext *ctx);
+
+extern void nouveauInitBufferFuncs(struct dd_function_table *func);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index b208d6c9f5e..f48c54416a3 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -32,6 +32,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "array_cache/acache.h"
+#include "framebuffer.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
@@ -47,6 +48,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "nouveau_fifo.h"
#include "nouveau_tex.h"
#include "nouveau_msg.h"
+#include "nouveau_reg.h"
#include "nv10_swtcl.h"
#include "vblank.h"
@@ -96,10 +98,17 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
screen=nmesa->screen;
/* Create the hardware context */
+ if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_PHYSICAL,
+ &nmesa->vram_phys))
+ return GL_FALSE;
+ if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_PHYSICAL,
+ &nmesa->agp_phys))
+ return GL_FALSE;
if (!nouveauFifoInit(nmesa))
return GL_FALSE;
nouveauObjectInit(nmesa);
+
/* Init default driver functions then plug in our nouveau-specific functions
* (the texture functions are especially important)
*/
@@ -169,6 +178,7 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
break;
}
+ nmesa->hw_func.InitCard(nmesa);
nouveauInitState(ctx);
driContextPriv->driverPrivate = (void *)nmesa;
@@ -208,17 +218,26 @@ GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driReadPriv )
{
if ( driContextPriv ) {
- GET_CURRENT_CONTEXT(ctx);
- nouveauContextPtr oldNOUVEAUCtx = ctx ? NOUVEAU_CONTEXT(ctx) : NULL;
- nouveauContextPtr newNOUVEAUCtx = (nouveauContextPtr) driContextPriv->driverPrivate;
-
- driDrawableInitVBlank(driDrawPriv, newNOUVEAUCtx->vblank_flags, &newNOUVEAUCtx->vblank_seq );
- newNOUVEAUCtx->driDrawable = driDrawPriv;
-
- _mesa_make_current( newNOUVEAUCtx->glCtx,
- (GLframebuffer *) driDrawPriv->driverPrivate,
- (GLframebuffer *) driReadPriv->driverPrivate );
-
+ nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
+ struct gl_framebuffer *draw_fb =
+ (struct gl_framebuffer*)driDrawPriv->driverPrivate;
+ struct gl_framebuffer *read_fb =
+ (struct gl_framebuffer*)driReadPriv->driverPrivate;
+
+ driDrawableInitVBlank(driDrawPriv, nmesa->vblank_flags, &nmesa->vblank_seq );
+ nmesa->driDrawable = driDrawPriv;
+
+ _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+ driDrawPriv->w, driDrawPriv->h);
+ if (draw_fb != read_fb) {
+ _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+ driReadPriv->w,
+ driReadPriv->h);
+ }
+ _mesa_make_current(nmesa->glCtx, draw_fb, read_fb);
+
+ nouveau_build_framebuffer(nmesa->glCtx,
+ driDrawPriv->driverPrivate);
} else {
_mesa_make_current( NULL, NULL, NULL );
}
@@ -234,8 +253,46 @@ GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
return GL_TRUE;
}
+static void nouveauDoSwapBuffers(nouveauContextPtr nmesa,
+ __DRIdrawablePrivate *dPriv)
+{
+ struct gl_framebuffer *fb;
+ nouveau_renderbuffer *src, *dst;
+
+ fb = (struct gl_framebuffer *)dPriv->driverPrivate;
+ dst = (nouveau_renderbuffer*)
+ fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ src = (nouveau_renderbuffer*)
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+ /* Ignore this.. it's a hack to test double-buffering, and not how
+ * SwapBuffers should look :)
+ */
+ BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
+ OUT_RING (6); /* X8R8G8B8 */
+ OUT_RING ((dst->pitch << 16) | src->pitch);
+ OUT_RING (src->offset);
+ OUT_RING (dst->offset);
+
+ BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_POINT, 3);
+ OUT_RING ((0 << 16) | 0); /* src point */
+ OUT_RING ((0 << 16) | 0); /* dst point */
+ OUT_RING ((fb->Height << 16) | fb->Width); /* width/height */
+#endif
+}
+
void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv)
{
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate;
+
+ if (nmesa->glCtx->Visual.doubleBufferMode) {
+ _mesa_notifySwapBuffers(nmesa->glCtx);
+ nouveauDoSwapBuffers(nmesa, dPriv);
+ }
+
+ }
}
void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
index 947e95d18b7..211d4e0a6d3 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -38,6 +38,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "nouveau_screen.h"
#include "nouveau_state_cache.h"
+#include "nouveau_buffers.h"
#include "nouveau_shader.h"
#include "xmlconfig.h"
@@ -75,6 +76,17 @@ typedef void (*nouveau_line_func)( struct nouveau_context*,
typedef void (*nouveau_point_func)( struct nouveau_context*,
nouveauVertex * );
+typedef struct nouveau_hw_func_t {
+ /* Initialise any card-specific non-GL related state */
+ GLboolean (*InitCard)(struct nouveau_context *);
+ /* Update buffer offset/pitch/format */
+ GLboolean (*BindBuffers)(struct nouveau_context *, int num_color,
+ nouveau_renderbuffer **color,
+ nouveau_renderbuffer *depth);
+ /* Update anything that depends on the window position/size */
+ void (*WindowMoved)(struct nouveau_context *);
+} nouveau_hw_func;
+
typedef struct nouveau_context {
/* Mesa context */
GLcontext *glCtx;
@@ -85,6 +97,13 @@ typedef struct nouveau_context {
/* The read-only regs */
volatile unsigned char* mmio;
+ /* Physical addresses of AGP/VRAM apertures */
+ uint64_t vram_phys;
+ uint64_t agp_phys;
+
+ /* Additional hw-specific functions */
+ nouveau_hw_func hw_func;
+
/* FIXME : do we want to put all state into a separate struct ? */
/* State for tris */
GLuint color_offset;
@@ -132,6 +151,7 @@ typedef struct nouveau_context {
__DRIcontextPrivate *driContext; /* DRI context */
__DRIscreenPrivate *driScreen; /* DRI screen */
__DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */
+ GLint lastStamp;
drm_context_t hHWContext;
drm_hw_lock_t *driHwLock;
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
index a45530e4511..f85dc62e748 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_driver.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
@@ -36,6 +36,35 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "utils.h"
+/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
+GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa,
+ unsigned int param,
+ uint64_t* value)
+{
+ drm_nouveau_getparam_t getp;
+
+ getp.param = param;
+ if (!value || drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_GETPARAM,
+ &getp, sizeof(getp)))
+ return GL_FALSE;
+ *value = getp.value;
+ return GL_TRUE;
+}
+
+/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
+GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa,
+ unsigned int param,
+ uint64_t value)
+{
+ drm_nouveau_setparam_t setp;
+
+ setp.param = param;
+ setp.value = value;
+ if (drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_SETPARAM, &setp,
+ sizeof(setp)))
+ return GL_FALSE;
+ return GL_TRUE;
+}
/* Return the width and height of the current color buffer */
static void nouveauGetBufferSize( GLframebuffer *buffer,
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.h b/src/mesa/drivers/dri/nouveau/nouveau_driver.h
index e1541aa3c57..6164012b5b7 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_driver.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.h
@@ -33,7 +33,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define DRIVER_AUTHOR "Stephane Marchesin"
extern void nouveauDriverInitFunctions( struct dd_function_table *functions );
-
+extern GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa, unsigned int param,
+ uint64_t *value);
+extern GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa, unsigned int param,
+ uint64_t value);
#endif /* __NOUVEAU_DRIVER_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_lock.c b/src/mesa/drivers/dri/nouveau/nouveau_lock.c
index 7dd67a143a9..c119d14dd75 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_lock.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_lock.c
@@ -29,6 +29,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "nouveau_lock.h"
#include "drirenderbuffer.h"
+#include "framebuffer.h"
/* Update the hardware state. This is called if another context has
@@ -57,6 +58,23 @@ void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags )
*/
DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
+ /* If timestamps don't match, the window has been changed */
+ if (nmesa->lastStamp != dPriv->lastStamp) {
+ struct gl_framebuffer *fb = (struct gl_framebuffer *)dPriv->driverPrivate;
+
+ /* _mesa_resize_framebuffer will take care of calling the renderbuffer's
+ * AllocStorage function if we need more memory to hold it */
+ if (fb->Width != dPriv->w || fb->Height != dPriv->h) {
+ _mesa_resize_framebuffer(nmesa->glCtx, fb, dPriv->w, dPriv->h);
+ /* resize buffers, will call nouveau_window_moved */
+ nouveau_build_framebuffer(nmesa->glCtx, fb);
+ } else {
+ nouveau_window_moved(nmesa->glCtx);
+ }
+
+ nmesa->lastStamp = dPriv->lastStamp;
+ }
+
nmesa->numClipRects = dPriv->numClipRects;
nmesa->pClipRects = dPriv->pClipRects;
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.c b/src/mesa/drivers/dri/nouveau/nouveau_object.c
index 032cdee2f79..ef8a428c220 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_object.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_object.c
@@ -1,6 +1,7 @@
#include "nouveau_fifo.h"
#include "nouveau_object.h"
+#include "nouveau_reg.h"
static GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle, int class, uint32_t flags, uint32_t dma_in, uint32_t dma_out, uint32_t dma_notifier)
@@ -51,14 +52,30 @@ void nouveauObjectInit(nouveauContextPtr nmesa)
return;
#endif
- nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d, 0, 0, 0, 0);
- nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
/* We need to know vram size.. */
-#if 0
nouveauCreateDmaObject( nmesa, NvDmaFB,
0, (256*1024*1024),
0 /*NV_DMA_TARGET_FB*/, 0 /*NV_DMA_ACCESS_RW*/);
+
+ nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d,
+ 0, 0, 0, 0);
+ nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV10_CONTEXT_SURFACES_2D,
+ 0, 0, 0, 0);
+ nouveauCreateContextObject(nmesa, NvImageBlit, NV10_IMAGE_BLIT,
+ NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY, 0, 0, 0);
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+ nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf2D, NvCtxSurf2D);
+ BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_SET_DMA_IN_MEMORY0, 2);
+ OUT_RING(NvDmaFB);
+ OUT_RING(NvDmaFB);
+
+ nouveauObjectOnSubchannel(nmesa, NvSubImageBlit, NvImageBlit);
+ BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_CONTEXT_SURFACES_2D, 1);
+ OUT_RING(NvCtxSurf2D);
#endif
+
+ nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.h b/src/mesa/drivers/dri/nouveau/nouveau_object.h
index 8386f923c3c..f555eba9b40 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_object.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_object.h
@@ -3,14 +3,21 @@
#include "nouveau_context.h"
+#define ALLOW_MULTI_SUBCHANNEL
+
void nouveauObjectInit(nouveauContextPtr nmesa);
enum DMAObjects {
Nv3D = 0x80000019,
- NvDmaFB = 0xD0FB0001
+ NvCtxSurf2D = 0x80000020,
+ NvImageBlit = 0x80000021,
+ NvDmaFB = 0xD0FB0001,
+ NvDmaAGP = 0xD0AA0001
};
enum DMASubchannel {
+ NvSubCtxSurf2D = 0,
+ NvSubImageBlit = 1,
NvSub3D = 7,
};
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
index 51f9fb14876..15c1c40925f 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
@@ -120,86 +120,69 @@ nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv,
GLboolean isPixmap)
{
nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private;
+ nouveau_renderbuffer *nrb;
+ struct gl_framebuffer *fb;
+ const GLboolean swAccum = mesaVis->accumRedBits > 0;
+ const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
- if (isPixmap) {
+ if (isPixmap)
return GL_FALSE; /* not implemented */
- }
- else {
- const GLboolean swDepth = GL_FALSE;
- const GLboolean swAlpha = GL_FALSE;
- const GLboolean swAccum = mesaVis->accumRedBits > 0;
- const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
- struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
-
- /* front color renderbuffer */
- {
- driRenderbuffer *frontRb
- = driNewRenderbuffer(GL_RGBA,
- driScrnPriv->pFB + screen->frontOffset,
- screen->fbFormat,
- screen->frontOffset, screen->frontPitch,
- driDrawPriv);
- nouveauSpanSetFunctions(frontRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
- }
- /* back color renderbuffer */
- if (mesaVis->doubleBufferMode) {
- driRenderbuffer *backRb
- = driNewRenderbuffer(GL_RGBA,
- driScrnPriv->pFB + screen->backOffset,
- screen->fbFormat,
- screen->backOffset, screen->backPitch,
- driDrawPriv);
- nouveauSpanSetFunctions(backRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
- }
+ fb = _mesa_create_framebuffer(mesaVis);
+ if (!fb)
+ return GL_FALSE;
- /* depth renderbuffer */
- if (mesaVis->depthBits == 16) {
- driRenderbuffer *depthRb
- = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
- driScrnPriv->pFB + screen->depthOffset,
- screen->fbFormat,
- screen->depthOffset, screen->depthPitch,
- driDrawPriv);
- nouveauSpanSetFunctions(depthRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
- }
- else if (mesaVis->depthBits == 24) {
- driRenderbuffer *depthRb
- = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
- driScrnPriv->pFB + screen->depthOffset,
- screen->fbFormat,
- screen->depthOffset, screen->depthPitch,
- driDrawPriv);
- nouveauSpanSetFunctions(depthRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+ /* Front buffer */
+ nrb = nouveau_renderbuffer_new(GL_RGBA,
+ driScrnPriv->pFB + screen->frontOffset,
+ screen->frontOffset,
+ screen->frontPitch * 4,
+ driDrawPriv);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa);
+
+ if (0 /* unified buffers if we choose to support them.. */) {
+ } else {
+ if (mesaVis->doubleBufferMode) {
+ nrb = nouveau_renderbuffer_new(GL_RGBA, NULL,
+ 0, 0,
+ driDrawPriv);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa);
}
- /* stencil renderbuffer */
- if (mesaVis->stencilBits > 0 && !swStencil) {
- driRenderbuffer *stencilRb
- = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
- driScrnPriv->pFB + screen->depthOffset,
- screen->fbFormat,
- screen->depthOffset, screen->depthPitch,
- driDrawPriv);
- nouveauSpanSetFunctions(stencilRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
+ if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
+ nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL,
+ 0, 0,
+ driDrawPriv);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+ _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa);
+ } else if (mesaVis->depthBits == 24) {
+ nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL,
+ 0, 0,
+ driDrawPriv);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+ } else if (mesaVis->depthBits == 16) {
+ nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL,
+ 0, 0,
+ driDrawPriv);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
}
+ }
- _mesa_add_soft_renderbuffers(fb,
- GL_FALSE, /* color */
- swDepth,
- swStencil,
- swAccum,
- swAlpha,
- GL_FALSE /* aux */);
- driDrawPriv->driverPrivate = (void *) fb;
+ _mesa_add_soft_renderbuffers(fb,
+ GL_FALSE, /* color */
+ GL_FALSE, /* depth */
+ swStencil,
+ swAccum,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux */);
- return (driDrawPriv->driverPrivate != NULL);
- }
+ driDrawPriv->driverPrivate = (void *) fb;
+ return (driDrawPriv->driverPrivate != NULL);
}
@@ -363,7 +346,8 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc
*driver_modes = nouveauFillInModes(dri_priv->bpp,
(dri_priv->bpp == 16) ? 16 : 24,
(dri_priv->bpp == 16) ? 0 : 8,
- (dri_priv->back_offset != dri_priv->depth_offset));
+ 1
+ );
/* Calling driInitExtensions here, with a NULL context pointer, does not actually
* enable the extensions. It just makes sure that all the dispatch offsets for all
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.c b/src/mesa/drivers/dri/nouveau/nouveau_shader.c
index 63da8420b29..4dedefe5a30 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_shader.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.c
@@ -132,6 +132,8 @@ nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs)
*/
nvs->func->UpdateConst(ctx, nvs, i);
} else if (plist->Parameters[i].Type == PROGRAM_STATE_VAR) {
+ if (!nvs->params[i].source_val) /* this is a workaround when consts aren't alloc'd from id=0.. */
+ continue;
/* update any changed state parameters */
if (!TEST_EQ_4V(nvs->params[i].val, nvs->params[i].source_val))
nvs->func->UpdateConst(ctx, nvs, i);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h
index a1e7794487c..dce2e23f46e 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_shader.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h
@@ -2,6 +2,7 @@
#define __SHADER_COMMON_H__
#include "mtypes.h"
+#include "nouveau_buffers.h"
typedef struct _nvsFunc nvsFunc;
@@ -40,6 +41,7 @@ typedef struct _nouveauShader {
unsigned int program_alloc_size;
unsigned int program_start_id;
unsigned int program_current;
+ nouveau_mem *program_buffer;
unsigned int inputs_read;
unsigned int outputs_written;
int inst_count;
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.c b/src/mesa/drivers/dri/nouveau/nouveau_span.c
index 1763b37e53c..6d99728b852 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_span.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_span.c
@@ -109,14 +109,10 @@ void nouveauSpanInitFunctions( GLcontext *ctx )
* Plug in the Get/Put routines for the given driRenderbuffer.
*/
void
-nouveauSpanSetFunctions(driRenderbuffer *drb, const GLvisual *vis)
+nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis)
{
- if (drb->Base.InternalFormat == GL_RGBA) {
- if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
- nouveauInitPointers_RGB565(&drb->Base);
- }
- else {
- nouveauInitPointers_ARGB8888(&drb->Base);
- }
- }
+ if (nrb->mesa._ActualFormat == GL_RGBA8)
+ nouveauInitPointers_ARGB8888(&nrb->mesa);
+ else if (nrb->mesa._ActualFormat == GL_RGB5)
+ nouveauInitPointers_RGB565(&nrb->mesa);
}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.h b/src/mesa/drivers/dri/nouveau/nouveau_span.h
index f5e5733ba88..bc39ecd17b5 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_span.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_span.h
@@ -30,9 +30,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define __NOUVEAU_SPAN_H__
#include "drirenderbuffer.h"
+#include "nouveau_buffers.h"
extern void nouveauSpanInitFunctions( GLcontext *ctx );
-extern void nouveauSpanSetFunctions(driRenderbuffer *rb, const GLvisual *vis);
+extern void nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis);
#endif /* __NOUVEAU_SPAN_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c
index 88a8c9ed59c..6406b2d9cd4 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_state.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c
@@ -59,20 +59,33 @@ static void nouveauCalcViewport(GLcontext *ctx)
/* Calculate the Viewport Matrix */
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_renderbuffer *nrb;
const GLfloat *v = ctx->Viewport._WindowMap.m;
GLfloat *m = nmesa->viewport.m;
+ GLfloat xoffset, yoffset;
GLint h = 0;
-
- if (nmesa->driDrawable)
- h = nmesa->driDrawable->h + SUBPIXEL_Y;
-
+
+ nrb = nouveau_current_draw_buffer(ctx);
+ nmesa->depth_scale = 1.0 / ctx->DrawBuffer->_DepthMaxF;
+
+ if (nrb && nrb->map) {
+ /* Window */
+ xoffset = nrb->dPriv->x;
+ yoffset = nrb->dPriv->y;
+ } else {
+ /* Offscreen or back buffer */
+ xoffset = 0.0;
+ yoffset = 0.0;
+ }
+
m[MAT_SX] = v[MAT_SX];
- m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
+ m[MAT_TX] = v[MAT_TX] + xoffset + SUBPIXEL_X;
m[MAT_SY] = - v[MAT_SY];
- m[MAT_TY] = - v[MAT_TY] + h;
+ m[MAT_TY] = v[MAT_TY] + yoffset + SUBPIXEL_Y;
m[MAT_SZ] = v[MAT_SZ] * nmesa->depth_scale;
m[MAT_TZ] = v[MAT_TZ] * nmesa->depth_scale;
+ nmesa->hw_func.WindowMoved(nmesa);
}
static void nouveauViewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
@@ -96,7 +109,7 @@ static void nouveauViewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei
nouveauCalcViewport(ctx);
}
-static void nouveauDepthRange(GLcontext *ctx)
+static void nouveauDepthRange(GLcontext *ctx, GLclampd near, GLclampd far)
{
nouveauCalcViewport(ctx);
}
@@ -161,15 +174,15 @@ void nouveauDDInitState(nouveauContextPtr nmesa)
/* No TCL engines for these ones */
break;
case NV_10:
- nv10InitStateFuncs(&nmesa->glCtx->Driver);
+ nv10InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
break;
case NV_20:
- nv20InitStateFuncs(&nmesa->glCtx->Driver);
+ nv20InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
break;
case NV_30:
case NV_40:
case NV_50:
- nv30InitStateFuncs(&nmesa->glCtx->Driver);
+ nv30InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
break;
default:
break;
@@ -270,7 +283,6 @@ void nouveauInitState(GLcontext *ctx)
STATE_INIT(CullFace)( ctx, ctx->Polygon.CullFaceMode );
STATE_INIT(DepthFunc)( ctx, ctx->Depth.Func );
STATE_INIT(DepthMask)( ctx, ctx->Depth.Mask );
- STATE_INIT(DepthRange)( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
STATE_INIT(Enable)( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
STATE_INIT(Enable)( ctx, GL_BLEND, ctx->Color.BlendEnabled );
@@ -320,8 +332,6 @@ void nouveauInitState(GLcontext *ctx)
ctx->Polygon.OffsetFactor,
ctx->Polygon.OffsetUnits );
STATE_INIT(PolygonStipple)( ctx, (const GLubyte *)ctx->PolygonStipple );
- STATE_INIT(Scissor)( ctx, ctx->Scissor.X, ctx->Scissor.Y,
- ctx->Scissor.Width, ctx->Scissor.Height );
STATE_INIT(ShadeModel)( ctx, ctx->Light.ShadeModel );
STATE_INIT(StencilFuncSeparate)( ctx, GL_FRONT,
ctx->Stencil.Function[0],
@@ -341,10 +351,4 @@ void nouveauInitState(GLcontext *ctx)
ctx->Stencil.FailFunc[1],
ctx->Stencil.ZFailFunc[1],
ctx->Stencil.ZPassFunc[1]);
-
- STATE_INIT(Viewport)( ctx,
- ctx->Viewport.X, ctx->Viewport.Y,
- ctx->Viewport.Width, ctx->Viewport.Height );
-
- STATE_INIT(DrawBuffer)( ctx, ctx->Color.DrawBuffer[0] );
}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.h b/src/mesa/drivers/dri/nouveau/nouveau_state.h
index 37f04f41bd4..16d63a6ac23 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_state.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_state.h
@@ -32,9 +32,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
extern void nouveauDDInitState(nouveauContextPtr nmesa);
extern void nouveauDDInitStateFuncs(GLcontext *ctx);
-extern void nv10InitStateFuncs(struct dd_function_table *func);
-extern void nv20InitStateFuncs(struct dd_function_table *func);
-extern void nv30InitStateFuncs(struct dd_function_table *func);
+extern void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
+extern void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
+extern void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
extern void nouveauInitState(GLcontext *ctx);
diff --git a/src/mesa/drivers/dri/nouveau/nv30_fragprog.c b/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
index 1c2664ec707..98aa27ea9c1 100644
--- a/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
+++ b/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
@@ -10,6 +10,7 @@
#include "nouveau_shader.h"
#include "nouveau_object.h"
#include "nouveau_msg.h"
+#include "nouveau_buffers.h"
#include "nv30_shader.h"
unsigned int NVFP_TX_AOP_COUNT = 64;
@@ -19,31 +20,22 @@ struct _op_xlat NVFP_TX_AOP[64];
* Support routines
*/
-/*XXX: bad bad bad bad */
-static uint64_t fragprog_ofs;
-static uint32_t *fragprog_buf = NULL;
-
static void
NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
drm_nouveau_mem_alloc_t mem;
- if (!fragprog_buf) {
- mem.flags = NOUVEAU_MEM_FB|NOUVEAU_MEM_MAPPED;
- mem.size = nvs->program_size * sizeof(uint32_t);
- mem.alignment = 0;
- mem.region_offset = &fragprog_ofs;
- if (drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC, &mem,
- sizeof(mem))) {
- fprintf(stderr, "MEM_ALLOC fail\n");
- return;
- }
+ if (!nvs->program_buffer) {
+ nouveau_mem *fpbuf;
- if (drmMap(nmesa->driFd, fragprog_ofs, mem.size, &fragprog_buf)) {
- fprintf(stderr, "MEM_MAP fail\n");
+ fpbuf = nouveau_mem_alloc(ctx, NOUVEAU_MEM_FB|NOUVEAU_MEM_MAPPED,
+ nvs->program_size * sizeof(uint32_t), 0);
+ if (!fpbuf) {
+ fprintf(stderr, "fragprog vram alloc fail!\n");
return;
}
+ nvs->program_buffer = fpbuf;
}
/*XXX: should do a DMA.. and not copy over a possibly in-use program.. */
@@ -52,9 +44,10 @@ NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
* caches the program somewhere? so, maybe not so bad to just clobber the
* old program in vram..
*/
- memcpy(fragprog_buf, nvs->program, nvs->program_size * sizeof(uint32_t));
+ memcpy(nvs->program_buffer->map, nvs->program,
+ nvs->program_size * sizeof(uint32_t));
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1);
- OUT_RING(((uint32_t)fragprog_ofs-0xE0000000)|1);
+ OUT_RING(nouveau_mem_gpu_offset_get(ctx, nvs->program_buffer) | 1);
}
static void
diff --git a/src/mesa/drivers/dri/nouveau/nv30_state.c b/src/mesa/drivers/dri/nouveau/nv30_state.c
index 3ffb5d3a41f..3228320623d 100644
--- a/src/mesa/drivers/dri/nouveau/nv30_state.c
+++ b/src/mesa/drivers/dri/nouveau/nv30_state.c
@@ -304,10 +304,16 @@ static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
// case GL_POST_COLOR_MATRIX_COLOR_TABLE:
// case GL_POST_CONVOLUTION_COLOR_TABLE:
// case GL_RESCALE_NORMAL:
-// case GL_SCISSOR_TEST:
+ case GL_SCISSOR_TEST:
+ /* No enable bit, nv30Scissor will adjust to max range */
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+ break;
// case GL_SEPARABLE_2D:
case GL_STENCIL_TEST:
// TODO BACK and FRONT ?
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
+ OUT_RING_CACHE(state);
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1);
OUT_RING_CACHE(state);
break;
@@ -514,9 +520,26 @@ void (*RenderMode)(GLcontext *ctx, GLenum mode );
static void nv30Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_renderbuffer *nrb;
+
+ /* Adjust offsets if drawing to a window */
+ nrb = nouveau_current_draw_buffer(ctx);
+ if (nrb && nrb->map) {
+ x += nrb->dPriv->x;
+ y += nrb->dPriv->y;
+ }
+
+ /* There's no scissor enable bit, so adjust the scissor to cover the
+ * maximum draw buffer bounds
+ */
+ if (!ctx->Scissor.Enabled) {
+ x = y = 0;
+ w = h = 4095;
+ }
+
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2);
- OUT_RING_CACHE((w << 16) | x);
- OUT_RING_CACHE((h << 16) | y);
+ OUT_RING_CACHE(((w) << 16) | x);
+ OUT_RING_CACHE(((h) << 16) | y);
}
/** Select flat or smooth shading */
@@ -602,18 +625,117 @@ static void nv30TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
OUT_RING_CACHEp(mat->m, 16);
}
-/** Set the viewport */
-static void nv30Viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+static void nv30WindowMoved(nouveauContextPtr nmesa)
{
- /* TODO: Where do the VIEWPORT_XFRM_* regs come in? */
- nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLcontext *ctx = nmesa->glCtx;
+ nouveau_renderbuffer *nrb;
+ GLfloat *v = nmesa->viewport.m;
+ GLuint w = ctx->Viewport.Width;
+ GLuint h = ctx->Viewport.Height;
+ GLuint x = ctx->Viewport.X;
+ GLuint y = ctx->Viewport.Y;
+
+ /* Adjust offsets if drawing to a window */
+ nrb = nouveau_current_draw_buffer(ctx);
+ if (nrb && nrb->map) {
+ x += nrb->dPriv->x;
+ y += nrb->dPriv->y;
+ }
+
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2);
OUT_RING_CACHE((w << 16) | x);
OUT_RING_CACHE((h << 16) | y);
-}
-
-void nv30InitStateFuncs(struct dd_function_table *func)
+ /* something to do with clears, possibly doesn't belong here */
+ BEGIN_RING_CACHE(NvSub3D,
+ NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2);
+ OUT_RING_CACHE(((w+x) << 16) | x);
+ OUT_RING_CACHE(((h+y) << 16) | y);
+ /* viewport transform */
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8);
+ OUT_RING_CACHEf (v[MAT_TX]);
+ OUT_RING_CACHEf (v[MAT_TY]);
+ OUT_RING_CACHEf (v[MAT_TZ]);
+ OUT_RING_CACHEf (0.0);
+ OUT_RING_CACHEf (v[MAT_SX]);
+ OUT_RING_CACHEf (v[MAT_SY]);
+ OUT_RING_CACHEf (v[MAT_SZ]);
+ OUT_RING_CACHEf (0.0);
+
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+static GLboolean nv30InitCard(nouveauContextPtr nmesa)
+{
+ /* Need some love.. */
+ return GL_FALSE;
+}
+
+static GLboolean nv40InitCard(nouveauContextPtr nmesa)
+{
+ nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
+
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 2);
+ OUT_RING(NvDmaFB);
+ OUT_RING(NvDmaFB);
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
+ OUT_RING(NvDmaFB);
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2);
+ OUT_RING(NvDmaFB);
+ OUT_RING(NvDmaFB);
+ BEGIN_RING_SIZE(NvSub3D, 0x0220, 1);
+ OUT_RING(1);
+ BEGIN_RING_SIZE(NvSub3D, 0x1fc8, 2);
+ OUT_RING(0xedcba987);
+ OUT_RING(0x00000021);
+ BEGIN_RING_SIZE(NvSub3D, 0x1d60, 1);
+ OUT_RING(0x03008000);
+
+ return GL_TRUE;
+}
+
+static GLboolean nv30BindBuffers(nouveauContextPtr nmesa, int num_color,
+ nouveau_renderbuffer **color,
+ nouveau_renderbuffer *depth)
+{
+ nouveau_renderbuffer *nrb;
+ GLuint x, y, w, h;
+
+ /* Adjust offsets if drawing to a window */
+ nrb = nouveau_current_draw_buffer(nmesa->glCtx);
+ w = nrb->mesa.Width;
+ h = nrb->mesa.Height;
+ if (nrb && nrb->map) {
+ x = nrb->dPriv->x;
+ y = nrb->dPriv->y;
+ } else {
+ x = 0;
+ y = 0;
+ }
+
+ if (num_color != 1)
+ return GL_FALSE;
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 5);
+ OUT_RING (((w+x)<<16)|x);
+ OUT_RING (((h+y)<<16)|y);
+ OUT_RING (0x148);
+ OUT_RING (color[0]->pitch);
+ OUT_RING (color[0]->offset);
+
+ if (depth) {
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_OFFSET, 1);
+ OUT_RING (depth->offset);
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH, 1);
+ OUT_RING (depth->pitch);
+ }
+
+ return GL_TRUE;
+}
+
+void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
func->AlphaFunc = nv30AlphaFunc;
func->BlendColor = nv30BlendColor;
func->BlendEquationSeparate = nv30BlendEquationSeparate;
@@ -628,7 +750,6 @@ void nv30InitStateFuncs(struct dd_function_table *func)
func->FrontFace = nv30FrontFace;
func->DepthFunc = nv30DepthFunc;
func->DepthMask = nv30DepthMask;
- func->DepthRange = nv30DepthRange;
func->Enable = nv30Enable;
func->Fogfv = nv30Fogfv;
func->Hint = nv30Hint;
@@ -656,6 +777,13 @@ void nv30InitStateFuncs(struct dd_function_table *func)
func->TexParameter = nv30TexParameter;
#endif
func->TextureMatrix = nv30TextureMatrix;
- func->Viewport = nv30Viewport;
+
+
+ if (nmesa->screen->card->type >= NV_40)
+ nmesa->hw_func.InitCard = nv40InitCard;
+ else
+ nmesa->hw_func.InitCard = nv30InitCard;
+ nmesa->hw_func.BindBuffers = nv30BindBuffers;
+ nmesa->hw_func.WindowMoved = nv30WindowMoved;
}