incomplete. But, it works well enough that windows can be moved/resized.tags/pre-merge-glsl-compiler-1
@@ -8,6 +8,7 @@ LIBNAME = nouveau_dri.so | |||
MINIGLX_SOURCES = | |||
DRIVER_SOURCES = \ | |||
nouveau_buffers.c \ | |||
nouveau_card.c \ | |||
nouveau_context.c \ | |||
nouveau_driver.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; | |||
} | |||
@@ -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 |
@@ -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, |
@@ -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; |
@@ -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, |
@@ -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__ */ | |||
@@ -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; | |||
@@ -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); | |||
} | |||
@@ -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, | |||
}; | |||
@@ -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 |
@@ -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); |
@@ -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; |
@@ -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); | |||
} |
@@ -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__ */ | |||
@@ -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] ); | |||
} |
@@ -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); | |||
@@ -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 |
@@ -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; | |||
} | |||