mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-04 20:38:06 +02:00
Merge branch 'nouveau-import'
This commit is contained in:
commit
e3358dea66
50 changed files with 13423 additions and 0 deletions
47
src/mesa/drivers/dri/nouveau/Makefile
Normal file
47
src/mesa/drivers/dri/nouveau/Makefile
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# src/mesa/drivers/dri/nouveau/Makefile
|
||||
|
||||
TOP = ../../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = nouveau_dri.so
|
||||
|
||||
MINIGLX_SOURCES =
|
||||
|
||||
DRIVER_SOURCES = \
|
||||
nouveau_buffers.c \
|
||||
nouveau_card.c \
|
||||
nouveau_context.c \
|
||||
nouveau_driver.c \
|
||||
nouveau_fifo.c \
|
||||
nouveau_lock.c \
|
||||
nouveau_object.c \
|
||||
nouveau_screen.c \
|
||||
nouveau_span.c \
|
||||
nouveau_state.c \
|
||||
nouveau_shader.c \
|
||||
nouveau_shader_0_arb.c \
|
||||
nouveau_shader_1.c \
|
||||
nouveau_shader_2.c \
|
||||
nouveau_tex.c \
|
||||
nouveau_swtcl.c \
|
||||
nv10_swtcl.c \
|
||||
nv10_state.c \
|
||||
nv20_state.c \
|
||||
nv30_state.c \
|
||||
nouveau_state_cache.c \
|
||||
nv20_vertprog.c \
|
||||
nv30_fragprog.c \
|
||||
nv30_vertprog.c \
|
||||
nv40_fragprog.c \
|
||||
nv40_vertprog.c
|
||||
|
||||
C_SOURCES = \
|
||||
$(COMMON_SOURCES) \
|
||||
$(DRIVER_SOURCES)
|
||||
|
||||
ASM_SOURCES =
|
||||
|
||||
|
||||
include ../Makefile.template
|
||||
|
||||
symlinks:
|
||||
334
src/mesa/drivers/dri/nouveau/nouveau_buffers.c
Normal file
334
src/mesa/drivers/dri/nouveau/nouveau_buffers.c
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
#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];
|
||||
if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped)
|
||||
depth = (nouveau_renderbuffer *)fb->_DepthBuffer->Wrapped;
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
41
src/mesa/drivers/dri/nouveau/nouveau_buffers.h
Normal file
41
src/mesa/drivers/dri/nouveau/nouveau_buffers.h
Normal file
|
|
@ -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
|
||||
20
src/mesa/drivers/dri/nouveau/nouveau_card.c
Normal file
20
src/mesa/drivers/dri/nouveau/nouveau_card.c
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
#include "nouveau_card.h"
|
||||
#include "nouveau_reg.h"
|
||||
#include "nouveau_drm.h"
|
||||
// FIXME hack for now
|
||||
#define NV15_TCL_PRIMITIVE_3D 0x0096
|
||||
#define NV17_TCL_PRIMITIVE_3D 0x0099
|
||||
#include "nouveau_card_list.h"
|
||||
|
||||
|
||||
nouveau_card* nouveau_card_lookup(uint32_t device_id)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<sizeof(nouveau_card_list)/sizeof(nouveau_card)-1;i++)
|
||||
if (nouveau_card_list[i].id==(device_id&0xffff))
|
||||
break;
|
||||
return &(nouveau_card_list[i]);
|
||||
}
|
||||
|
||||
|
||||
49
src/mesa/drivers/dri/nouveau/nouveau_card.h
Normal file
49
src/mesa/drivers/dri/nouveau/nouveau_card.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_CARD_H__
|
||||
#define __NOUVEAU_CARD_H__
|
||||
|
||||
#include "dri_util.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drm.h"
|
||||
|
||||
typedef struct nouveau_card_t {
|
||||
uint16_t id; /* last 4 digits of pci id, last digit is always 0 */
|
||||
char* name; /* the user-friendly card name */
|
||||
uint32_t class_3d; /* the object class this card uses for 3D */
|
||||
uint32_t type; /* the major card family */
|
||||
uint32_t flags;
|
||||
}
|
||||
nouveau_card;
|
||||
|
||||
#define NV_HAS_LMA 0x00000001
|
||||
|
||||
extern nouveau_card* nouveau_card_lookup(uint32_t device_id);
|
||||
|
||||
#endif
|
||||
|
||||
229
src/mesa/drivers/dri/nouveau/nouveau_card_list.h
Normal file
229
src/mesa/drivers/dri/nouveau/nouveau_card_list.h
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
static nouveau_card nouveau_card_list[]={
|
||||
{0x0008, "EDGE 3D", 0, NV_03, 0},
|
||||
{0x0009, "EDGE 3D", 0, NV_03, 0},
|
||||
{0x0010, "Mutara V08", 0, NV_03, 0},
|
||||
{0x0020, "RIVA TNT", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x0028, "RIVA TNT2/TNT2 Pro", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x0029, "RIVA TNT2 Ultra", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x002A, "Riva TnT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x002B, "Riva TnT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x002C, "Vanta/Vanta LT", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x002D, "RIVA TNT2 Model 64/Model 64 Pro", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x002E, "Vanta", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x002F, "Vanta", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x0040, "GeForce 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0041, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0042, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0043, "NV40.3", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0044, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0045, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0046, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0047, "GeForce 6800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0048, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0049, "NV40GL", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x004D, "Quadro FX 4000", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x004E, "Quadro FX 4000", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0090, "GeForce 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0091, "GeForce 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0092, "GeForce 7800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0093, "GeForce 7800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0098, "GeForce Go 7800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0099, "GE Force Go 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x009D, "Quadro FX4500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00A0, "Aladdin TNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x00C0, "GeForce 6800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00C1, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00C2, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00C3, "Geforce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00C8, "GeForce Go 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00C9, "GeForce Go 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00CC, "Quadro FX Go1400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00CD, "Quadro FX 3450/4000 SDI", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00CE, "Quadro FX 1400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F0, "GeForce 6800/GeForce 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F1, "GeForce 6600/GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F2, "GeForce 6600/GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F3, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F4, "GeForce 6600 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F5, "GeForce 7800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F6, "GeForce 6600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F8, "Quadro FX 3400/4400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00F9, "GeForce 6800 Ultra/GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x00FA, "GeForce PCX 5750", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x00FB, "GeForce PCX 5900", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
|
||||
{0x00FC, "Quadro FX 330/GeForce PCX 5300", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
|
||||
{0x00FD, "Quadro FX 330/Quadro NVS280", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
|
||||
{0x00FE, "Quadro FX 1300", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x00FF, "GeForce PCX 4300", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0100, "GeForce 256 SDR", NV10_TCL_PRIMITIVE_3D, NV_10, 0},
|
||||
{0x0101, "GeForce 256 DDR", NV10_TCL_PRIMITIVE_3D, NV_10, 0},
|
||||
{0x0103, "Quadro", NV10_TCL_PRIMITIVE_3D, NV_10, 0},
|
||||
{0x0110, "GeForce2 MX/MX 400", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
|
||||
{0x0111, "GeForce2 MX 100 DDR/200 DDR", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
|
||||
{0x0112, "GeForce2 Go", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
|
||||
{0x0113, "Quadro2 MXR/EX/Go", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
|
||||
{0x0140, "GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0141, "GeForce 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0142, "GeForce 6600 PCIe", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0144, "GeForce Go 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0145, "GeForce 6610 XL", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0146, "Geforce Go 6600TE/6200TE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0148, "GeForce Go 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0149, "GeForce Go 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x014A, "Quadro NVS 440", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x014D, "Quadro FX 550", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x014E, "Quadro FX 540", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x014F, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0150, "GeForce2 GTS/Pro", NV11_TCL_PRIMITIVE_3D, NV_15, 0},
|
||||
{0x0151, "GeForce2 Ti", NV11_TCL_PRIMITIVE_3D, NV_15, 0},
|
||||
{0x0152, "GeForce2 Ultra, Bladerunner", NV11_TCL_PRIMITIVE_3D, NV_15, 0},
|
||||
{0x0153, "Quadro2 Pro", NV11_TCL_PRIMITIVE_3D, NV_15, 0},
|
||||
{0x0161, "GeForce 6200 TurboCache(TM)", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0162, "GeForce 6200 SE TurboCache (TM)", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0163, "GeForce 6200 LE", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0164, "GeForce Go 6200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0165, "Quadro NVS 285", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0166, "GeForce Go 6400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0167, "GeForce Go 6200 TurboCache", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0168, "GeForce Go 6200 TurboCache", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0170, "GeForce4 MX 460", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0171, "GeForce4 MX 440", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0172, "GeForce4 MX 420", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0173, "GeForce4 MX 440-SE", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0174, "GeForce4 440 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0175, "GeForce4 420 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0176, "GeForce4 420 Go 32M", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0177, "GeForce4 460 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0178, "Quadro4 550 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0179, "GeForce4 420 Go 32M", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x017A, "Quadro4 200/400 NVS", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x017B, "Quadro4 550 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x017C, "Quadro4 500 GoGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x017D, "GeForce4 410 Go 16M", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0181, "GeForce4 MX 440 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0182, "GeForce4 MX 440SE AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0183, "GeForce4 MX 420 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0185, "GeForce4 MX 4000 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0186, "GeForce4 448 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0187, "GeForce4 488 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0188, "Quadro4 580 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x018A, "Quadro4 NVS AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x018B, "Quadro4 380 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x018C, "Quadro NVS 50 PCI", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x018D, "GeForce4 448 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0191, "GeForce 8800 GTX", NV30_TCL_PRIMITIVE_3D|0x5000, NV_50, 0},
|
||||
{0x0193, "GeForce 8800 GTS", NV30_TCL_PRIMITIVE_3D|0x5000, NV_50, 0},
|
||||
{0x01A0, "GeForce2 MX Integrated Graphics", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
|
||||
{0x01D1, "GeForce 7300 LE", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x01D6, "GeForce Go 7200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x01D7, "Quadro NVS 110M / GeForce Go 7300", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x01D8, "GeForce Go 7400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x01DA, "Quadro NVS 110M", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x01DF, "GeForce 7300 GS", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x01F0, "GeForce4 MX - nForce GPU", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
|
||||
{0x0200, "GeForce3", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
|
||||
{0x0201, "GeForce3 Ti 200", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
|
||||
{0x0202, "GeForce3 Ti 500", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
|
||||
{0x0203, "Quadro DCC", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
|
||||
{0x0211, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0212, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0215, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0218, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0221, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0240, "GeForce 6150", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0242, "GeForce 6100", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0250, "GeForce4 Ti 4600", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0251, "GeForce4 Ti 4400", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0252, "GeForce4 Ti", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0253, "GeForce4 Ti 4200", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0258, "Quadro4 900 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0259, "Quadro4 750 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x025B, "Quadro4 700 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0280, "GeForce4 Ti 4800", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0281, "GeForce4 Ti 4200 AGP 8x", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0282, "GeForce4 Ti 4800 SE", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0286, "GeForce4 Ti 4200 Go AGP 8x", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0288, "Quadro4 980 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0289, "Quadro4 780 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x028C, "Quadro4 700 GoGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
|
||||
{0x0290, "GeForce 7900 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0291, "GeForce 7900 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0292, "GeForce 7900 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0298, "GeForce Go 7900 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0299, "GeForce Go 7900 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x029A, "Quadro FX 2500M", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x029B, "Quadro FX 1500M", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x029C, "Quadro FX 5500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x029D, "Quadro FX 3500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x029E, "Quadro FX 1500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x029F, "Quadro FX 4500 X2", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x02A0, "XGPU", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
|
||||
{0x02E1, "GeForce 7600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0300, "GeForce FX", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0301, "GeForce FX 5800 Ultra", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0302, "GeForce FX 5800", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0308, "Quadro FX 2000", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0309, "Quadro FX 1000", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0311, "GeForce FX 5600 Ultra", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0312, "GeForce FX 5600", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0313, "NV31", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0314, "GeForce FX 5600XT", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0316, "NV31M", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0317, "NV31M Pro", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x031A, "GeForce FX Go5600", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x031B, "GeForce FX Go5650", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x031D, "NV31GLM", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x031E, "NV31GLM Pro", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x031F, "NV31GLM Pro", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0320, "GeForce FX 5200", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0321, "GeForce FX 5200 Ultra", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0322, "GeForce FX 5200", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0323, "GeForce FX 5200LE", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0324, "GeForce FX Go5200", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0325, "GeForce FX Go5250", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0326, "GeForce FX 5500", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0327, "GeForce FX 5100", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0328, "GeForce FX Go5200 32M/64M", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0329, "GeForce FX Go5200", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x032A, "Quadro NVS 280 PCI", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x032B, "Quadro FX 500/600 PCI", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x032C, "GeForce FX Go 5300", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x032D, "GeForce FX Go5100", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x032F, "NV34GL", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
|
||||
{0x0330, "GeForce FX 5900 Ultra", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
|
||||
{0x0331, "GeForce FX 5900", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
|
||||
{0x0332, "GeForce FX 5900XT", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
|
||||
{0x0333, "GeForce FX 5950 Ultra", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0334, "GeForce FX 5900ZT", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
|
||||
{0x0338, "Quadro FX 3000", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x033F, "Quadro FX 700", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0341, "GeForce FX 5700 Ultra", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0342, "GeForce FX 5700", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0343, "GeForce FX 5700LE", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0344, "GeForce FX 5700VE", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0345, "NV36.5", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0347, "GeForce FX Go5700", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0348, "GeForce FX Go5700", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0349, "NV36M Pro", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x034B, "NV36MAP", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x034C, "Quadro FX Go1000", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x034E, "Quadro FX 1100", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x034F, "NV36GL", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
|
||||
{0x0391, "GeForce 7600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0392, "GeForce 7600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0393, "GeForce 7300 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x0398, "GeForce Go 7600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
|
||||
{0x03D0, "GeForce 6100 nForce 430", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x03D1, "GeForce 6100 nForce 405", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x03D2, "GeForce 6100 nForce 400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x03D5, "GeForce 6100 nForce 420", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
|
||||
{0x0008, "NV1", 0, NV_03, 0},
|
||||
{0x0009, "DAC64", 0, NV_03, 0},
|
||||
{0x0018, "Riva128", 0, NV_03, 0},
|
||||
{0x0019, "Riva128ZX", 0, NV_03, 0},
|
||||
{0x0020, "TNT", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x0028, "TNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x0029, "UTNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x002C, "VTNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
{0x00A0, "ITNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
|
||||
};
|
||||
358
src/mesa/drivers/dri/nouveau/nouveau_context.c
Normal file
358
src/mesa/drivers/dri/nouveau/nouveau_context.c
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 "glheader.h"
|
||||
#include "context.h"
|
||||
#include "simple_list.h"
|
||||
#include "imports.h"
|
||||
#include "matrix.h"
|
||||
#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"
|
||||
#include "tnl/t_vp_build.h"
|
||||
|
||||
#include "drivers/common/driverfuncs.h"
|
||||
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_driver.h"
|
||||
//#include "nouveau_state.h"
|
||||
#include "nouveau_span.h"
|
||||
#include "nouveau_object.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_tex.h"
|
||||
#include "nouveau_msg.h"
|
||||
#include "nouveau_reg.h"
|
||||
#include "nouveau_lock.h"
|
||||
#include "nv10_swtcl.h"
|
||||
|
||||
#include "vblank.h"
|
||||
#include "utils.h"
|
||||
#include "texmem.h"
|
||||
#include "xmlpool.h" /* for symbolic values of enum-type options */
|
||||
|
||||
#ifndef NOUVEAU_DEBUG
|
||||
int NOUVEAU_DEBUG = 0;
|
||||
#endif
|
||||
|
||||
static const struct dri_debug_control debug_control[] =
|
||||
{
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
#define need_GL_ARB_vertex_program
|
||||
#include "extension_helper.h"
|
||||
|
||||
const struct dri_extension common_extensions[] =
|
||||
{
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
const struct dri_extension nv10_extensions[] =
|
||||
{
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
const struct dri_extension nv20_extensions[] =
|
||||
{
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
const struct dri_extension nv30_extensions[] =
|
||||
{
|
||||
{ "GL_ARB_fragment_program", NULL },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
const struct dri_extension nv40_extensions[] =
|
||||
{
|
||||
/* ARB_vp can be moved to nv20/30 once the shader backend has been
|
||||
* written for those cards.
|
||||
*/
|
||||
{ "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
const struct dri_extension nv50_extensions[] =
|
||||
{
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* Create the device specific context.
|
||||
*/
|
||||
GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
void *sharedContextPrivate )
|
||||
{
|
||||
GLcontext *ctx, *shareCtx;
|
||||
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
|
||||
struct dd_function_table functions;
|
||||
nouveauContextPtr nmesa;
|
||||
nouveauScreenPtr screen;
|
||||
|
||||
/* Allocate the context */
|
||||
nmesa = (nouveauContextPtr) CALLOC( sizeof(*nmesa) );
|
||||
if ( !nmesa )
|
||||
return GL_FALSE;
|
||||
|
||||
nmesa->driContext = driContextPriv;
|
||||
nmesa->driScreen = sPriv;
|
||||
nmesa->driDrawable = NULL;
|
||||
nmesa->hHWContext = driContextPriv->hHWContext;
|
||||
nmesa->driHwLock = &sPriv->pSAREA->lock;
|
||||
nmesa->driFd = sPriv->fd;
|
||||
|
||||
nmesa->screen = (nouveauScreenPtr)(sPriv->private);
|
||||
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)
|
||||
*/
|
||||
_mesa_init_driver_functions( &functions );
|
||||
nouveauDriverInitFunctions( &functions );
|
||||
nouveauTexInitFunctions( &functions );
|
||||
|
||||
/* Allocate the Mesa context */
|
||||
if (sharedContextPrivate)
|
||||
shareCtx = ((nouveauContextPtr) sharedContextPrivate)->glCtx;
|
||||
else
|
||||
shareCtx = NULL;
|
||||
nmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
|
||||
&functions, (void *) nmesa);
|
||||
if (!nmesa->glCtx) {
|
||||
FREE(nmesa);
|
||||
return GL_FALSE;
|
||||
}
|
||||
driContextPriv->driverPrivate = nmesa;
|
||||
ctx = nmesa->glCtx;
|
||||
|
||||
/* Parse configuration files */
|
||||
driParseConfigFiles (&nmesa->optionCache, &screen->optionCache,
|
||||
screen->driScreen->myNum, "nouveau");
|
||||
|
||||
nmesa->sarea = (drm_nouveau_sarea_t *)((char *)sPriv->pSAREA +
|
||||
screen->sarea_priv_offset);
|
||||
|
||||
/* Enable any supported extensions */
|
||||
driInitExtensions(ctx, common_extensions, GL_TRUE);
|
||||
if (nmesa->screen->card->type >= NV_10)
|
||||
driInitExtensions(ctx, nv10_extensions, GL_FALSE);
|
||||
if (nmesa->screen->card->type >= NV_20)
|
||||
driInitExtensions(ctx, nv20_extensions, GL_FALSE);
|
||||
if (nmesa->screen->card->type >= NV_30)
|
||||
driInitExtensions(ctx, nv30_extensions, GL_FALSE);
|
||||
if (nmesa->screen->card->type >= NV_40)
|
||||
driInitExtensions(ctx, nv40_extensions, GL_FALSE);
|
||||
if (nmesa->screen->card->type >= NV_50)
|
||||
driInitExtensions(ctx, nv50_extensions, GL_FALSE);
|
||||
|
||||
nmesa->current_primitive = -1;
|
||||
|
||||
nouveauShaderInitFuncs(ctx);
|
||||
/* Install Mesa's fixed-function texenv shader support */
|
||||
if (nmesa->screen->card->type >= NV_40)
|
||||
ctx->_MaintainTexEnvProgram = GL_TRUE;
|
||||
|
||||
/* Initialize the swrast */
|
||||
_swrast_CreateContext( ctx );
|
||||
_ac_CreateContext( ctx );
|
||||
_tnl_CreateContext( ctx );
|
||||
_swsetup_CreateContext( ctx );
|
||||
|
||||
_math_matrix_ctr(&nmesa->viewport);
|
||||
|
||||
nouveauDDInitStateFuncs( ctx );
|
||||
nouveauSpanInitFunctions( ctx );
|
||||
nouveauDDInitState( nmesa );
|
||||
switch(nmesa->screen->card->type)
|
||||
{
|
||||
case NV_03:
|
||||
//nv03TriInitFunctions( ctx );
|
||||
break;
|
||||
case NV_04:
|
||||
case NV_05:
|
||||
//nv04TriInitFunctions( ctx );
|
||||
break;
|
||||
case NV_10:
|
||||
case NV_20:
|
||||
case NV_30:
|
||||
case NV_40:
|
||||
case NV_44:
|
||||
case NV_50:
|
||||
default:
|
||||
nv10TriInitFunctions( ctx );
|
||||
break;
|
||||
}
|
||||
|
||||
nmesa->hw_func.InitCard(nmesa);
|
||||
nouveauInitState(ctx);
|
||||
|
||||
driContextPriv->driverPrivate = (void *)nmesa;
|
||||
|
||||
NOUVEAU_DEBUG = driParseDebugString( getenv( "NOUVEAU_DEBUG" ),
|
||||
debug_control );
|
||||
|
||||
if (driQueryOptionb(&nmesa->optionCache, "no_rast")) {
|
||||
fprintf(stderr, "disabling 3D acceleration\n");
|
||||
FALLBACK(nmesa, NOUVEAU_FALLBACK_DISABLE, 1);
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* Destroy the device specific context. */
|
||||
void nouveauDestroyContext( __DRIcontextPrivate *driContextPriv )
|
||||
{
|
||||
nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
|
||||
|
||||
assert(nmesa);
|
||||
if ( nmesa ) {
|
||||
/* free the option cache */
|
||||
driDestroyOptionCache (&nmesa->optionCache);
|
||||
|
||||
FREE( nmesa );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Force the context `c' to be the current context and associate with it
|
||||
* buffer `b'.
|
||||
*/
|
||||
GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
|
||||
__DRIdrawablePrivate *driDrawPriv,
|
||||
__DRIdrawablePrivate *driReadPriv )
|
||||
{
|
||||
if ( driContextPriv ) {
|
||||
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 );
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Force the context `c' to be unbound from its buffer.
|
||||
*/
|
||||
GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
|
||||
{
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static void nouveauDoSwapBuffers(nouveauContextPtr nmesa,
|
||||
__DRIdrawablePrivate *dPriv)
|
||||
{
|
||||
struct gl_framebuffer *fb;
|
||||
nouveau_renderbuffer *src, *dst;
|
||||
drm_clip_rect_t *box;
|
||||
int nbox, i;
|
||||
|
||||
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
|
||||
LOCK_HARDWARE(nmesa);
|
||||
nbox = dPriv->numClipRects;
|
||||
box = dPriv->pClipRects;
|
||||
|
||||
if (nbox) {
|
||||
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);
|
||||
}
|
||||
|
||||
for (i=0; i<nbox; i++, box++) {
|
||||
BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_POINT, 3);
|
||||
OUT_RING (((box->y1 - dPriv->y) << 16) |
|
||||
(box->x1 - dPriv->x));
|
||||
OUT_RING ((box->y1 << 16) | box->x1);
|
||||
OUT_RING (((box->y2 - box->y1) << 16) |
|
||||
(box->x2 - box->x1));
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE(nmesa);
|
||||
#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,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
}
|
||||
|
||||
211
src/mesa/drivers/dri/nouveau/nouveau_context.h
Normal file
211
src/mesa/drivers/dri/nouveau/nouveau_context.h
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_CONTEXT_H__
|
||||
#define __NOUVEAU_CONTEXT_H__
|
||||
|
||||
#include "dri_util.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drm.h"
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "tnl/t_vertex.h"
|
||||
|
||||
#include "nouveau_screen.h"
|
||||
#include "nouveau_state_cache.h"
|
||||
#include "nouveau_buffers.h"
|
||||
#include "nouveau_shader.h"
|
||||
|
||||
#include "xmlconfig.h"
|
||||
|
||||
typedef struct nouveau_fifo_t{
|
||||
u_int32_t* buffer;
|
||||
u_int32_t* mmio;
|
||||
u_int32_t put_base;
|
||||
u_int32_t current;
|
||||
u_int32_t put;
|
||||
u_int32_t free;
|
||||
u_int32_t max;
|
||||
}
|
||||
nouveau_fifo;
|
||||
|
||||
#define TAG(x) nouveau##x
|
||||
#include "tnl_dd/t_dd_vertex.h"
|
||||
#undef TAG
|
||||
|
||||
/* Subpixel offsets for window coordinates (triangles): */
|
||||
#define SUBPIXEL_X (0.0F)
|
||||
#define SUBPIXEL_Y (0.125F)
|
||||
|
||||
struct nouveau_context;
|
||||
|
||||
typedef void (*nouveau_tri_func)( struct nouveau_context*,
|
||||
nouveauVertex *,
|
||||
nouveauVertex *,
|
||||
nouveauVertex * );
|
||||
|
||||
typedef void (*nouveau_line_func)( struct nouveau_context*,
|
||||
nouveauVertex *,
|
||||
nouveauVertex * );
|
||||
|
||||
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;
|
||||
|
||||
/* The per-context fifo */
|
||||
nouveau_fifo fifo;
|
||||
|
||||
/* 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;
|
||||
GLuint specular_offset;
|
||||
|
||||
/* Vertex state */
|
||||
GLuint vertex_size;
|
||||
GLubyte *verts;
|
||||
struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
|
||||
GLuint vertex_attr_count;
|
||||
|
||||
/* Depth/stencil clear state */
|
||||
uint32_t clear_value;
|
||||
|
||||
/* Light state */
|
||||
GLboolean lighting_enabled;
|
||||
uint32_t enabled_lights;
|
||||
|
||||
/* Cached state */
|
||||
nouveau_state_cache state_cache;
|
||||
|
||||
/* The drawing fallbacks */
|
||||
GLuint Fallback;
|
||||
nouveau_tri_func draw_tri;
|
||||
nouveau_line_func draw_line;
|
||||
nouveau_point_func draw_point;
|
||||
|
||||
/* Cliprects information */
|
||||
GLuint numClipRects;
|
||||
drm_clip_rect_t *pClipRects;
|
||||
|
||||
/* The rendering context information */
|
||||
GLenum current_primitive; /* the current primitive enum */
|
||||
DECLARE_RENDERINPUTS(render_inputs_bitset); /* the current render inputs */
|
||||
|
||||
/* Shader state */
|
||||
nvsFunc VPfunc;
|
||||
nvsFunc FPfunc;
|
||||
nouveauShader *current_fragprog;
|
||||
nouveauShader *current_vertprog;
|
||||
nouveauShader *passthrough_vp;
|
||||
|
||||
nouveauScreenRec *screen;
|
||||
drm_nouveau_sarea_t *sarea;
|
||||
|
||||
__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;
|
||||
int driFd;
|
||||
|
||||
/* Configuration cache */
|
||||
driOptionCache optionCache;
|
||||
|
||||
/* vblank stuff */
|
||||
uint32_t vblank_flags;
|
||||
uint32_t vblank_seq;
|
||||
|
||||
GLuint new_state;
|
||||
GLuint new_render_state;
|
||||
GLuint render_index;
|
||||
GLmatrix viewport;
|
||||
GLfloat depth_scale;
|
||||
|
||||
}nouveauContextRec, *nouveauContextPtr;
|
||||
|
||||
|
||||
#define NOUVEAU_CONTEXT(ctx) ((nouveauContextPtr)(ctx->DriverCtx))
|
||||
|
||||
/* Flags for software fallback cases: */
|
||||
#define NOUVEAU_FALLBACK_TEXTURE 0x0001
|
||||
#define NOUVEAU_FALLBACK_DRAW_BUFFER 0x0002
|
||||
#define NOUVEAU_FALLBACK_READ_BUFFER 0x0004
|
||||
#define NOUVEAU_FALLBACK_STENCIL 0x0008
|
||||
#define NOUVEAU_FALLBACK_RENDER_MODE 0x0010
|
||||
#define NOUVEAU_FALLBACK_LOGICOP 0x0020
|
||||
#define NOUVEAU_FALLBACK_SEP_SPECULAR 0x0040
|
||||
#define NOUVEAU_FALLBACK_BLEND_EQ 0x0080
|
||||
#define NOUVEAU_FALLBACK_BLEND_FUNC 0x0100
|
||||
#define NOUVEAU_FALLBACK_PROJTEX 0x0200
|
||||
#define NOUVEAU_FALLBACK_DISABLE 0x0400
|
||||
|
||||
|
||||
extern GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
void *sharedContextPrivate );
|
||||
|
||||
extern void nouveauDestroyContext( __DRIcontextPrivate * );
|
||||
|
||||
extern GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
|
||||
__DRIdrawablePrivate *driDrawPriv,
|
||||
__DRIdrawablePrivate *driReadPriv );
|
||||
|
||||
extern GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv );
|
||||
|
||||
extern void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv);
|
||||
|
||||
extern void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
|
||||
int x, int y, int w, int h);
|
||||
|
||||
#endif /* __NOUVEAU_CONTEXT_H__ */
|
||||
|
||||
44
src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h
Normal file
44
src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin, Sylvain Munaut
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#define NV03_STATUS 0x004006b0
|
||||
#define NV04_STATUS 0x00400700
|
||||
|
||||
#define NV03_FIFO_REGS_SIZE 0x10000
|
||||
# define NV03_FIFO_REGS_DMAPUT 0x00000040
|
||||
# define NV03_FIFO_REGS_DMAGET 0x00000044
|
||||
|
||||
/* Fifo commands. These are not regs, neither masks */
|
||||
#define NV03_FIFO_CMD_JUMP 0x20000000
|
||||
#define NV03_FIFO_CMD_JUMP_OFFSET_MASK 0x1ffffffc
|
||||
#define NV03_FIFO_CMD_REWIND (NV03_FIFO_CMD_JUMP | (0 & NV03_FIFO_CMD_JUMP_OFFSET_MASK))
|
||||
|
||||
|
||||
#define NONINC_METHOD 0x40000000
|
||||
|
||||
28
src/mesa/drivers/dri/nouveau/nouveau_dri.h
Normal file
28
src/mesa/drivers/dri/nouveau/nouveau_dri.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef _NOUVEAU_DRI_
|
||||
#define _NOUVEAU_DRI_
|
||||
|
||||
#include "xf86drm.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drm.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t device_id; /**< \brief PCI device ID */
|
||||
uint32_t width; /**< \brief width in pixels of display */
|
||||
uint32_t height; /**< \brief height in scanlines of display */
|
||||
uint32_t depth; /**< \brief depth of display (8, 15, 16, 24) */
|
||||
uint32_t bpp; /**< \brief bit depth of display (8, 16, 24, 32) */
|
||||
|
||||
uint32_t bus_type; /**< \brief ths bus type */
|
||||
uint32_t bus_mode; /**< \brief bus mode (used for AGP, maybe also for PCI-E ?) */
|
||||
|
||||
uint32_t front_offset; /**< \brief front buffer offset */
|
||||
uint32_t front_pitch; /**< \brief front buffer pitch */
|
||||
uint32_t back_offset; /**< \brief private back buffer offset */
|
||||
uint32_t back_pitch; /**< \brief private back buffer pitch */
|
||||
uint32_t depth_offset; /**< \brief private depth buffer offset */
|
||||
uint32_t depth_pitch; /**< \brief private depth buffer pitch */
|
||||
|
||||
} NOUVEAUDRIRec, *NOUVEAUDRIPtr;
|
||||
|
||||
#endif
|
||||
|
||||
147
src/mesa/drivers/dri/nouveau/nouveau_driver.c
Normal file
147
src/mesa/drivers/dri/nouveau/nouveau_driver.c
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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_context.h"
|
||||
//#include "nouveau_state.h"
|
||||
#include "nouveau_lock.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_driver.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "framebuffer.h"
|
||||
|
||||
#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,
|
||||
GLuint *width, GLuint *height )
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
LOCK_HARDWARE( nmesa );
|
||||
*width = nmesa->driDrawable->w;
|
||||
*height = nmesa->driDrawable->h;
|
||||
UNLOCK_HARDWARE( nmesa );
|
||||
}
|
||||
|
||||
/* glGetString */
|
||||
static const GLubyte *nouveauGetString( GLcontext *ctx, GLenum name )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
static char buffer[128];
|
||||
const char * card_name = "Unknown";
|
||||
GLuint agp_mode = 0;
|
||||
|
||||
switch ( name ) {
|
||||
case GL_VENDOR:
|
||||
return (GLubyte *)DRIVER_AUTHOR;
|
||||
|
||||
case GL_RENDERER:
|
||||
card_name=nmesa->screen->card->name;
|
||||
|
||||
switch(nmesa->screen->bus_type)
|
||||
{
|
||||
case NV_PCI:
|
||||
case NV_PCIE:
|
||||
default:
|
||||
agp_mode=0;
|
||||
break;
|
||||
case NV_AGP:
|
||||
agp_mode=nmesa->screen->agp_mode;
|
||||
break;
|
||||
}
|
||||
driGetRendererString( buffer, card_name, DRIVER_DATE,
|
||||
agp_mode );
|
||||
return (GLubyte *)buffer;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* glFlush */
|
||||
static void nouveauFlush( GLcontext *ctx )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
FIRE_RING();
|
||||
}
|
||||
|
||||
/* glFinish */
|
||||
static void nouveauFinish( GLcontext *ctx )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
nouveauFlush( ctx );
|
||||
nouveauWaitForIdle( nmesa );
|
||||
}
|
||||
|
||||
/* glClear */
|
||||
static void nouveauClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch )
|
||||
{
|
||||
// XXX we really should do something here...
|
||||
}
|
||||
|
||||
void nouveauDriverInitFunctions( struct dd_function_table *functions )
|
||||
{
|
||||
functions->GetBufferSize = nouveauGetBufferSize;
|
||||
functions->ResizeBuffers = _mesa_resize_framebuffer;
|
||||
functions->GetString = nouveauGetString;
|
||||
functions->Flush = nouveauFlush;
|
||||
functions->Finish = nouveauFinish;
|
||||
functions->Clear = nouveauClear;
|
||||
}
|
||||
|
||||
42
src/mesa/drivers/dri/nouveau/nouveau_driver.h
Normal file
42
src/mesa/drivers/dri/nouveau/nouveau_driver.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_DRIVER_H__
|
||||
#define __NOUVEAU_DRIVER_H__
|
||||
|
||||
#define DRIVER_DATE "20060219"
|
||||
#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__ */
|
||||
|
||||
153
src/mesa/drivers/dri/nouveau/nouveau_fifo.c
Normal file
153
src/mesa/drivers/dri/nouveau/nouveau_fifo.c
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 "vblank.h"
|
||||
#include <errno.h>
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
#include "dd.h"
|
||||
#include "swrast/swrast.h"
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_msg.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_lock.h"
|
||||
|
||||
|
||||
#define RING_SKIPS 8
|
||||
|
||||
void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size)
|
||||
{
|
||||
#ifdef NOUVEAU_RING_DEBUG
|
||||
return;
|
||||
#endif
|
||||
u_int32_t fifo_get;
|
||||
while(nmesa->fifo.free < size+1) {
|
||||
fifo_get = NV_FIFO_READ_GET();
|
||||
|
||||
if(nmesa->fifo.put >= fifo_get) {
|
||||
nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current;
|
||||
if(nmesa->fifo.free < size+1) {
|
||||
OUT_RING(NV03_FIFO_CMD_JUMP | nmesa->fifo.put_base);
|
||||
if(fifo_get <= RING_SKIPS) {
|
||||
if(nmesa->fifo.put <= RING_SKIPS) /* corner case - will be idle */
|
||||
NV_FIFO_WRITE_PUT(RING_SKIPS + 1);
|
||||
do { fifo_get = NV_FIFO_READ_GET(); }
|
||||
while(fifo_get <= RING_SKIPS);
|
||||
}
|
||||
NV_FIFO_WRITE_PUT(RING_SKIPS);
|
||||
nmesa->fifo.current = nmesa->fifo.put = RING_SKIPS;
|
||||
nmesa->fifo.free = fifo_get - (RING_SKIPS + 1);
|
||||
}
|
||||
} else
|
||||
nmesa->fifo.free = fifo_get - nmesa->fifo.current - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the card to be idle
|
||||
*/
|
||||
void nouveauWaitForIdleLocked(nouveauContextPtr nmesa)
|
||||
{
|
||||
int i,status;
|
||||
|
||||
FIRE_RING();
|
||||
while(RING_AHEAD()>0);
|
||||
|
||||
for(i=0;i<1000000;i++) /* 1 second */
|
||||
{
|
||||
switch(nmesa->screen->card->type)
|
||||
{
|
||||
case NV_03:
|
||||
status=NV_READ(NV03_STATUS);
|
||||
break;
|
||||
case NV_04:
|
||||
case NV_05:
|
||||
case NV_10:
|
||||
case NV_20:
|
||||
case NV_30:
|
||||
case NV_40:
|
||||
case NV_44:
|
||||
case NV_50:
|
||||
default:
|
||||
status=NV_READ(NV04_STATUS);
|
||||
break;
|
||||
}
|
||||
if (status)
|
||||
return;
|
||||
DO_USLEEP(1);
|
||||
}
|
||||
}
|
||||
|
||||
void nouveauWaitForIdle(nouveauContextPtr nmesa)
|
||||
{
|
||||
LOCK_HARDWARE(nmesa);
|
||||
nouveauWaitForIdleLocked(nmesa);
|
||||
UNLOCK_HARDWARE(nmesa);
|
||||
}
|
||||
|
||||
// here we call the fifo initialization ioctl and fill in stuff accordingly
|
||||
GLboolean nouveauFifoInit(nouveauContextPtr nmesa)
|
||||
{
|
||||
drm_nouveau_fifo_alloc_t fifo_init;
|
||||
int i;
|
||||
|
||||
#ifdef NOUVEAU_RING_DEBUG
|
||||
return GL_TRUE;
|
||||
#endif
|
||||
|
||||
int ret;
|
||||
ret=drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_FIFO_ALLOC, &fifo_init, sizeof(fifo_init));
|
||||
if (ret) {
|
||||
FATAL("Fifo initialization ioctl failed (returned %d)\n",ret);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (drmMap(nmesa->driFd, fifo_init.cmdbuf, fifo_init.cmdbuf_size, &nmesa->fifo.buffer)) {
|
||||
FATAL("Unable to map the fifo\n",ret);
|
||||
return GL_FALSE;
|
||||
}
|
||||
if (drmMap(nmesa->driFd, fifo_init.ctrl, fifo_init.ctrl_size, &nmesa->fifo.mmio)) {
|
||||
FATAL("Unable to map the control regs\n",ret);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Setup our initial FIFO tracking params */
|
||||
nmesa->fifo.put_base = fifo_init.put_base;
|
||||
nmesa->fifo.current = 0;
|
||||
nmesa->fifo.put = 0;
|
||||
nmesa->fifo.max = (fifo_init.cmdbuf_size >> 2) - 1;
|
||||
nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current;
|
||||
|
||||
for (i=0; i<RING_SKIPS; i++)
|
||||
OUT_RING(0);
|
||||
nmesa->fifo.free -= RING_SKIPS;
|
||||
|
||||
MESSAGE("Fifo init ok. Using context %d\n", fifo_init.channel);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
152
src/mesa/drivers/dri/nouveau/nouveau_fifo.h
Normal file
152
src/mesa/drivers/dri/nouveau/nouveau_fifo.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_FIFO_H__
|
||||
#define __NOUVEAU_FIFO_H__
|
||||
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_ctrlreg.h"
|
||||
|
||||
//#define NOUVEAU_RING_DEBUG
|
||||
//#define NOUVEAU_STATE_CACHE_DISABLE
|
||||
|
||||
#define NV_READ(reg) *(volatile u_int32_t *)(nmesa->mmio + (reg))
|
||||
|
||||
#define NV_FIFO_READ(reg) *(volatile u_int32_t *)(nmesa->fifo.mmio + (reg/4))
|
||||
#define NV_FIFO_WRITE(reg,value) *(volatile u_int32_t *)(nmesa->fifo.mmio + (reg/4)) = value;
|
||||
#define NV_FIFO_READ_GET() ((NV_FIFO_READ(NV03_FIFO_REGS_DMAGET) - nmesa->fifo.put_base) >> 2)
|
||||
#define NV_FIFO_WRITE_PUT(val) NV_FIFO_WRITE(NV03_FIFO_REGS_DMAPUT, ((val)<<2) + nmesa->fifo.put_base)
|
||||
|
||||
/*
|
||||
* Ring/fifo interface
|
||||
*
|
||||
* - Begin a ring section with BEGIN_RING_SIZE (if you know the full size in advance)
|
||||
* - Output stuff to the ring with either OUT_RINGp (outputs a raw mem chunk), OUT_RING (1 uint32_t) or OUT_RINGf (1 float)
|
||||
* - RING_AVAILABLE returns the available fifo (in uint32_ts)
|
||||
* - RING_AHEAD returns how much ahead of the last submission point we are
|
||||
* - FIRE_RING fires whatever we have that wasn't fired before
|
||||
* - WAIT_RING waits for size (in uint32_ts) to be available in the fifo
|
||||
*/
|
||||
|
||||
/* Enable for ring debugging. Prints out writes to the ring buffer
|
||||
* but does not actually write to it.
|
||||
*/
|
||||
#ifdef NOUVEAU_RING_DEBUG
|
||||
|
||||
#define OUT_RINGp(ptr,sz) do { \
|
||||
uint32_t* p=(uint32_t*)(ptr); \
|
||||
int i; printf("OUT_RINGp: (size 0x%x dwords)\n",sz); for(i=0;i<sz;i++) printf(" 0x%08x %f\n", *(p+i), *((float*)(p+i))); \
|
||||
}while(0)
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
printf("OUT_RINGn: 0x%08x (%s)\n", n, __func__); \
|
||||
}while(0)
|
||||
|
||||
#define OUT_RINGf(n) do { \
|
||||
printf("OUT_RINGf: %.04f (%s)\n", n, __func__); \
|
||||
}while(0)
|
||||
|
||||
#else
|
||||
|
||||
#define OUT_RINGp(ptr,sz) do{ \
|
||||
memcpy(nmesa->fifo.buffer+nmesa->fifo.current,ptr,(sz)*4); \
|
||||
nmesa->fifo.current+=(sz); \
|
||||
}while(0)
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
nmesa->fifo.buffer[nmesa->fifo.current++]=(n); \
|
||||
}while(0)
|
||||
|
||||
#define OUT_RINGf(n) do { \
|
||||
*((float*)(nmesa->fifo.buffer+nmesa->fifo.current++))=(n); \
|
||||
}while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#define BEGIN_RING_SIZE(subchannel,tag,size) do { \
|
||||
nouveau_state_cache_flush(nmesa); \
|
||||
if (nmesa->fifo.free <= (size)) \
|
||||
WAIT_RING(nmesa,(size)); \
|
||||
OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \
|
||||
nmesa->fifo.free -= ((size) + 1); \
|
||||
}while(0)
|
||||
|
||||
extern void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size);
|
||||
extern void nouveau_state_cache_flush(nouveauContextPtr nmesa);
|
||||
extern void nouveau_state_cache_init(nouveauContextPtr nmesa);
|
||||
|
||||
#ifdef NOUVEAU_STATE_CACHE_DISABLE
|
||||
#define BEGIN_RING_CACHE(subc,tag,size) BEGIN_RING_SIZE((subc), (tag), (size))
|
||||
#define OUT_RING_CACHE(n) OUT_RING((n))
|
||||
#define OUT_RING_CACHEf(n) OUT_RINGf((n))
|
||||
#define OUT_RING_CACHEp(ptr, sz) OUT_RINGp((ptr), (sz))
|
||||
#else
|
||||
#define BEGIN_RING_CACHE(subchannel,tag,size) do { \
|
||||
nmesa->state_cache.dirty=1; \
|
||||
nmesa->state_cache.current_pos=((tag)/4); \
|
||||
}while(0)
|
||||
|
||||
#define OUT_RING_CACHE(n) do { \
|
||||
if (nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value!=(n)) { \
|
||||
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \
|
||||
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value=(n); \
|
||||
} \
|
||||
nmesa->state_cache.current_pos++; \
|
||||
}while(0)
|
||||
|
||||
#define OUT_RING_CACHEf(n) do { \
|
||||
if ((*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))!=(n)){ \
|
||||
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \
|
||||
(*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))=(n);\
|
||||
} \
|
||||
nmesa->state_cache.current_pos++; \
|
||||
}while(0)
|
||||
|
||||
#define OUT_RING_CACHEp(ptr,sz) do { \
|
||||
uint32_t* p=(uint32_t*)(ptr); \
|
||||
int i; for(i=0;i<sz;i++) OUT_RING_CACHE(*(p+i)); \
|
||||
}while(0)
|
||||
#endif
|
||||
|
||||
#define RING_AVAILABLE() (nmesa->fifo.free-1)
|
||||
|
||||
#define RING_AHEAD() ((nmesa->fifo.put<=nmesa->fifo.current)?(nmesa->fifo.current-nmesa->fifo.put):nmesa->fifo.max-nmesa->fifo.put+nmesa->fifo.current)
|
||||
|
||||
#define FIRE_RING() do { \
|
||||
if (nmesa->fifo.current!=nmesa->fifo.put) { \
|
||||
nmesa->fifo.put=nmesa->fifo.current; \
|
||||
NV_FIFO_WRITE_PUT(nmesa->fifo.put); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
extern void nouveauWaitForIdle(nouveauContextPtr nmesa);
|
||||
extern GLboolean nouveauFifoInit(nouveauContextPtr nmesa);
|
||||
|
||||
#endif /* __NOUVEAU_FIFO_H__ */
|
||||
|
||||
|
||||
81
src/mesa/drivers/dri/nouveau/nouveau_lock.c
Normal file
81
src/mesa/drivers/dri/nouveau/nouveau_lock.c
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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_context.h"
|
||||
#include "nouveau_lock.h"
|
||||
|
||||
#include "drirenderbuffer.h"
|
||||
#include "framebuffer.h"
|
||||
|
||||
|
||||
/* Update the hardware state. This is called if another context has
|
||||
* grabbed the hardware lock, which includes the X server. This
|
||||
* function also updates the driver's window state after the X server
|
||||
* moves, resizes or restacks a window -- the change will be reflected
|
||||
* in the drawable position and clip rects. Since the X server grabs
|
||||
* the hardware lock when it changes the window state, this routine will
|
||||
* automatically be called after such a change.
|
||||
*/
|
||||
void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags )
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = nmesa->driDrawable;
|
||||
__DRIscreenPrivate *sPriv = nmesa->driScreen;
|
||||
drm_nouveau_sarea_t *sarea = nmesa->sarea;
|
||||
|
||||
drmGetLock( nmesa->driFd, nmesa->hHWContext, flags );
|
||||
|
||||
/* The window might have moved, so we might need to get new clip
|
||||
* rects.
|
||||
*
|
||||
* NOTE: This releases and regrabs the hw lock to allow the X server
|
||||
* to respond to the DRI protocol request for new drawable info.
|
||||
* Since the hardware state depends on having the latest drawable
|
||||
* clip rects, all state checking must be done _after_ this call.
|
||||
*/
|
||||
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;
|
||||
|
||||
}
|
||||
69
src/mesa/drivers/dri/nouveau/nouveau_lock.h
Normal file
69
src/mesa/drivers/dri/nouveau/nouveau_lock.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_LOCK_H__
|
||||
#define __NOUVEAU_LOCK_H__
|
||||
|
||||
#include "nouveau_context.h"
|
||||
|
||||
extern void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags );
|
||||
|
||||
/*
|
||||
* !!! We may want to separate locks from locks with validation. This
|
||||
* could be used to improve performance for those things commands that
|
||||
* do not do any drawing !!!
|
||||
*/
|
||||
|
||||
/* Lock the hardware and validate our state.
|
||||
*/
|
||||
#define LOCK_HARDWARE( nmesa ) \
|
||||
do { \
|
||||
char __ret = 0; \
|
||||
DEBUG_CHECK_LOCK(); \
|
||||
DRM_CAS( nmesa->driHwLock, nmesa->hHWContext, \
|
||||
(DRM_LOCK_HELD | nmesa->hHWContext), __ret ); \
|
||||
if ( __ret ) \
|
||||
nouveauGetLock( nmesa, 0 ); \
|
||||
DEBUG_LOCK(); \
|
||||
} while (0)
|
||||
|
||||
/* Unlock the hardware.
|
||||
*/
|
||||
#define UNLOCK_HARDWARE( nmesa ) \
|
||||
do { \
|
||||
DRM_UNLOCK( nmesa->driFd, \
|
||||
nmesa->driHwLock, \
|
||||
nmesa->hHWContext ); \
|
||||
DEBUG_RESET(); \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_LOCK()
|
||||
#define DEBUG_RESET()
|
||||
#define DEBUG_CHECK_LOCK()
|
||||
|
||||
|
||||
#endif /* __NOUVEAU_LOCK_H__ */
|
||||
67
src/mesa/drivers/dri/nouveau/nouveau_msg.h
Normal file
67
src/mesa/drivers/dri/nouveau/nouveau_msg.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
|
||||
Copyright 2006 Stephane Marchesin. All Rights Reserved
|
||||
|
||||
The Weather Channel (TM) funded Tungsten Graphics to develop the
|
||||
initial release of the Radeon 8500 driver under the XFree86 license.
|
||||
This notice must be preserved.
|
||||
|
||||
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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Nicolai Haehnle <prefect_@gmx.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_MSG_H__
|
||||
#define __NOUVEAU_MSG_H__
|
||||
|
||||
#define WARN_ONCE(a, ...) do {\
|
||||
static int warn##__LINE__=1;\
|
||||
if(warn##__LINE__){\
|
||||
fprintf(stderr, "*********************************WARN_ONCE*********************************\n");\
|
||||
fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__);\
|
||||
fprintf(stderr, a, ## __VA_ARGS__);\
|
||||
fprintf(stderr, "***************************************************************************\n");\
|
||||
warn##__LINE__=0;\
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#define MESSAGE(a, ...) do{\
|
||||
fprintf(stderr, "************************************INFO***********************************\n");\
|
||||
fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__); \
|
||||
fprintf(stderr, a, ## __VA_ARGS__);\
|
||||
fprintf(stderr, "***************************************************************************\n");\
|
||||
}while(0)
|
||||
|
||||
#define FATAL(a, ...) do{\
|
||||
fprintf(stderr, "***********************************FATAL***********************************\n");\
|
||||
fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__); \
|
||||
fprintf(stderr, a, ## __VA_ARGS__);\
|
||||
fprintf(stderr, "***************************************************************************\n");\
|
||||
}while(0)
|
||||
|
||||
#endif /* __NOUVEAU_MSG_H__ */
|
||||
|
||||
84
src/mesa/drivers/dri/nouveau/nouveau_object.c
Normal file
84
src/mesa/drivers/dri/nouveau/nouveau_object.c
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
#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)
|
||||
{
|
||||
drm_nouveau_object_init_t cto;
|
||||
int ret;
|
||||
|
||||
cto.handle = handle;
|
||||
cto.class = class;
|
||||
cto.flags = flags;
|
||||
cto.dma0= dma_in;
|
||||
cto.dma1= dma_out;
|
||||
cto.dma_notifier = dma_notifier;
|
||||
ret = drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_OBJECT_INIT, &cto, sizeof(cto));
|
||||
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
static GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa,
|
||||
uint32_t handle,
|
||||
uint32_t offset,
|
||||
uint32_t size,
|
||||
int target,
|
||||
int access)
|
||||
{
|
||||
drm_nouveau_dma_object_init_t dma;
|
||||
int ret;
|
||||
|
||||
dma.handle = handle;
|
||||
dma.target = target;
|
||||
dma.access = access;
|
||||
dma.offset = offset;
|
||||
dma.size = size;
|
||||
ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_DMA_OBJECT_INIT,
|
||||
&dma, sizeof(dma));
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle)
|
||||
{
|
||||
BEGIN_RING_SIZE(subchannel, 0, 1);
|
||||
OUT_RING(handle);
|
||||
}
|
||||
|
||||
void nouveauObjectInit(nouveauContextPtr nmesa)
|
||||
{
|
||||
#ifdef NOUVEAU_RING_DEBUG
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* We need to know vram size.. */
|
||||
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);
|
||||
BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_OPERATION, 1);
|
||||
OUT_RING(3); /* SRCCOPY */
|
||||
#endif
|
||||
|
||||
nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
|
||||
}
|
||||
|
||||
|
||||
|
||||
25
src/mesa/drivers/dri/nouveau/nouveau_object.h
Normal file
25
src/mesa/drivers/dri/nouveau/nouveau_object.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef __NOUVEAU_OBJECT_H__
|
||||
#define __NOUVEAU_OBJECT_H__
|
||||
|
||||
#include "nouveau_context.h"
|
||||
|
||||
//#define ALLOW_MULTI_SUBCHANNEL
|
||||
|
||||
void nouveauObjectInit(nouveauContextPtr nmesa);
|
||||
|
||||
enum DMAObjects {
|
||||
Nv3D = 0x80000019,
|
||||
NvCtxSurf2D = 0x80000020,
|
||||
NvImageBlit = 0x80000021,
|
||||
NvDmaFB = 0xD0FB0001,
|
||||
NvDmaAGP = 0xD0AA0001
|
||||
};
|
||||
|
||||
enum DMASubchannel {
|
||||
NvSubCtxSurf2D = 0,
|
||||
NvSubImageBlit = 1,
|
||||
NvSub3D = 7,
|
||||
};
|
||||
|
||||
extern void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle);
|
||||
#endif
|
||||
1297
src/mesa/drivers/dri/nouveau/nouveau_reg.h
Normal file
1297
src/mesa/drivers/dri/nouveau/nouveau_reg.h
Normal file
File diff suppressed because it is too large
Load diff
369
src/mesa/drivers/dri/nouveau/nouveau_screen.c
Normal file
369
src/mesa/drivers/dri/nouveau/nouveau_screen.c
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 "glheader.h"
|
||||
#include "imports.h"
|
||||
#include "mtypes.h"
|
||||
#include "framebuffer.h"
|
||||
#include "renderbuffer.h"
|
||||
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_screen.h"
|
||||
#include "nouveau_object.h"
|
||||
#include "nouveau_span.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "context.h"
|
||||
#include "vblank.h"
|
||||
#include "drirenderbuffer.h"
|
||||
|
||||
#include "GL/internal/dri_interface.h"
|
||||
|
||||
#include "xmlpool.h"
|
||||
|
||||
PUBLIC const char __driConfigOptions[] =
|
||||
DRI_CONF_BEGIN
|
||||
DRI_CONF_SECTION_DEBUG
|
||||
DRI_CONF_NO_RAST(false)
|
||||
DRI_CONF_SECTION_END
|
||||
DRI_CONF_END;
|
||||
static const GLuint __driNConfigOptions = 1;
|
||||
|
||||
extern const struct dri_extension common_extensions[];
|
||||
extern const struct dri_extension nv10_extensions[];
|
||||
extern const struct dri_extension nv20_extensions[];
|
||||
extern const struct dri_extension nv30_extensions[];
|
||||
extern const struct dri_extension nv40_extensions[];
|
||||
extern const struct dri_extension nv50_extensions[];
|
||||
|
||||
static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv)
|
||||
{
|
||||
nouveauScreenPtr screen;
|
||||
NOUVEAUDRIPtr dri_priv=(NOUVEAUDRIPtr)sPriv->pDevPriv;
|
||||
|
||||
/* allocate screen */
|
||||
screen = (nouveauScreenPtr) CALLOC( sizeof(*screen) );
|
||||
if ( !screen ) {
|
||||
__driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* parse information in __driConfigOptions */
|
||||
driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions);
|
||||
|
||||
screen->fbFormat = dri_priv->bpp / 8;
|
||||
screen->frontOffset = dri_priv->front_offset;
|
||||
screen->frontPitch = dri_priv->front_pitch;
|
||||
screen->backOffset = dri_priv->back_offset;
|
||||
screen->backPitch = dri_priv->back_pitch;
|
||||
screen->depthOffset = dri_priv->depth_offset;
|
||||
screen->depthPitch = dri_priv->depth_pitch;
|
||||
|
||||
screen->card=nouveau_card_lookup(dri_priv->device_id);
|
||||
screen->driScreen = sPriv;
|
||||
return screen;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveauDestroyScreen(__DRIscreenPrivate *sPriv)
|
||||
{
|
||||
nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private;
|
||||
|
||||
if (!screen) return;
|
||||
|
||||
/* free all option information */
|
||||
driDestroyOptionInfo (&screen->optionCache);
|
||||
|
||||
FREE(screen);
|
||||
sPriv->private = NULL;
|
||||
}
|
||||
|
||||
static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv)
|
||||
{
|
||||
sPriv->private = (void *) nouveauCreateScreen( sPriv );
|
||||
if ( !sPriv->private ) {
|
||||
nouveauDestroyScreen( sPriv );
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Mesa framebuffer and renderbuffers for a given window/drawable.
|
||||
*
|
||||
* \todo This function (and its interface) will need to be updated to support
|
||||
* pbuffers.
|
||||
*/
|
||||
static GLboolean
|
||||
nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv,
|
||||
__DRIdrawablePrivate *driDrawPriv,
|
||||
const __GLcontextModes *mesaVis,
|
||||
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)
|
||||
return GL_FALSE; /* not implemented */
|
||||
|
||||
fb = _mesa_create_framebuffer(mesaVis);
|
||||
if (!fb)
|
||||
return GL_FALSE;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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 */
|
||||
GL_FALSE, /* depth */
|
||||
swStencil,
|
||||
swAccum,
|
||||
GL_FALSE, /* alpha */
|
||||
GL_FALSE /* aux */);
|
||||
|
||||
driDrawPriv->driverPrivate = (void *) fb;
|
||||
return (driDrawPriv->driverPrivate != NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
|
||||
{
|
||||
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
|
||||
}
|
||||
|
||||
static int
|
||||
nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const struct __DriverAPIRec nouveauAPI = {
|
||||
.InitDriver = nouveauInitDriver,
|
||||
.DestroyScreen = nouveauDestroyScreen,
|
||||
.CreateContext = nouveauCreateContext,
|
||||
.DestroyContext = nouveauDestroyContext,
|
||||
.CreateBuffer = nouveauCreateBuffer,
|
||||
.DestroyBuffer = nouveauDestroyBuffer,
|
||||
.SwapBuffers = nouveauSwapBuffers,
|
||||
.MakeCurrent = nouveauMakeCurrent,
|
||||
.UnbindContext = nouveauUnbindContext,
|
||||
.GetSwapInfo = nouveauGetSwapInfo,
|
||||
.GetMSC = driGetMSC32,
|
||||
.WaitForMSC = driWaitForMSC32,
|
||||
.WaitForSBC = NULL,
|
||||
.SwapBuffersMSC = NULL,
|
||||
.CopySubBuffer = nouveauCopySubBuffer
|
||||
};
|
||||
|
||||
|
||||
static __GLcontextModes *
|
||||
nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits,
|
||||
unsigned stencil_bits, GLboolean have_back_buffer )
|
||||
{
|
||||
__GLcontextModes * modes;
|
||||
__GLcontextModes * m;
|
||||
unsigned num_modes;
|
||||
unsigned depth_buffer_factor;
|
||||
unsigned back_buffer_factor;
|
||||
unsigned fb_format_factor;
|
||||
int i;
|
||||
|
||||
static const struct {
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
} fb_format_array[] = {
|
||||
{ GL_RGB , GL_UNSIGNED_SHORT_5_6_5 },
|
||||
{ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
|
||||
{ GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
|
||||
};
|
||||
|
||||
/* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
|
||||
* support pageflipping at all.
|
||||
*/
|
||||
static const GLenum back_buffer_modes[] = {
|
||||
GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
|
||||
};
|
||||
|
||||
u_int8_t depth_bits_array[4] = { 0, 16, 24, 24 };
|
||||
u_int8_t stencil_bits_array[4] = { 0, 0, 0, 8 };
|
||||
|
||||
depth_buffer_factor = 4;
|
||||
back_buffer_factor = (have_back_buffer) ? 3 : 1;
|
||||
|
||||
num_modes = ((pixel_bits==16) ? 1 : 2) *
|
||||
depth_buffer_factor * back_buffer_factor * 4;
|
||||
modes = (*dri_interface->createContextModes)(num_modes,
|
||||
sizeof(__GLcontextModes));
|
||||
m = modes;
|
||||
|
||||
for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
|
||||
if (!driFillInModes(&m, fb_format_array[i].format,
|
||||
fb_format_array[i].type,
|
||||
depth_bits_array,
|
||||
stencil_bits_array,
|
||||
depth_buffer_factor,
|
||||
back_buffer_modes,
|
||||
back_buffer_factor,
|
||||
GLX_TRUE_COLOR)) {
|
||||
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
|
||||
__func__, __LINE__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!driFillInModes(&m, fb_format_array[i].format,
|
||||
fb_format_array[i].type,
|
||||
depth_bits_array,
|
||||
stencil_bits_array,
|
||||
depth_buffer_factor,
|
||||
back_buffer_modes,
|
||||
back_buffer_factor,
|
||||
GLX_DIRECT_COLOR)) {
|
||||
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
|
||||
__func__, __LINE__ );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is the bootstrap function for the driver. libGL supplies all of the
|
||||
* requisite information about the system, and the driver initializes itself.
|
||||
* This routine also fills in the linked list pointed to by \c driver_modes
|
||||
* with the \c __GLcontextModes that the driver can support for windows or
|
||||
* pbuffers.
|
||||
*
|
||||
* \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
|
||||
* failure.
|
||||
*/
|
||||
PUBLIC
|
||||
void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
|
||||
const __GLcontextModes * modes,
|
||||
const __DRIversion * ddx_version,
|
||||
const __DRIversion * dri_version,
|
||||
const __DRIversion * drm_version,
|
||||
const __DRIframebuffer * frame_buffer,
|
||||
drmAddress pSAREA, int fd,
|
||||
int internal_api_version,
|
||||
const __DRIinterfaceMethods * interface,
|
||||
__GLcontextModes ** driver_modes)
|
||||
|
||||
{
|
||||
__DRIscreenPrivate *psp;
|
||||
static const __DRIversion ddx_expected = { 1, 2, 0 };
|
||||
static const __DRIversion dri_expected = { 4, 0, 0 };
|
||||
static const __DRIversion drm_expected = { 0, 0, 1 };
|
||||
|
||||
dri_interface = interface;
|
||||
|
||||
if (!driCheckDriDdxDrmVersions2("nouveau",
|
||||
dri_version, & dri_expected,
|
||||
ddx_version, & ddx_expected,
|
||||
drm_version, & drm_expected)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// temporary lock step versioning
|
||||
if (drm_expected.patch!=drm_version->patch)
|
||||
return NULL;
|
||||
|
||||
psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
|
||||
ddx_version, dri_version, drm_version,
|
||||
frame_buffer, pSAREA, fd,
|
||||
internal_api_version, &nouveauAPI);
|
||||
if ( psp != NULL ) {
|
||||
NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
|
||||
|
||||
*driver_modes = nouveauFillInModes(dri_priv->bpp,
|
||||
(dri_priv->bpp == 16) ? 16 : 24,
|
||||
(dri_priv->bpp == 16) ? 0 : 8,
|
||||
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
|
||||
* the extensions that *might* be enables are known. This is needed because the
|
||||
* dispatch offsets need to be known when _mesa_context_create is called, but we can't
|
||||
* enable the extensions until we have a context pointer.
|
||||
*
|
||||
* Hello chicken. Hello egg. How are you two today?
|
||||
*/
|
||||
driInitExtensions( NULL, common_extensions, GL_FALSE );
|
||||
driInitExtensions( NULL, nv10_extensions, GL_FALSE );
|
||||
driInitExtensions( NULL, nv10_extensions, GL_FALSE );
|
||||
driInitExtensions( NULL, nv30_extensions, GL_FALSE );
|
||||
driInitExtensions( NULL, nv40_extensions, GL_FALSE );
|
||||
driInitExtensions( NULL, nv50_extensions, GL_FALSE );
|
||||
}
|
||||
|
||||
return (void *) psp;
|
||||
}
|
||||
|
||||
61
src/mesa/drivers/dri/nouveau/nouveau_screen.h
Normal file
61
src/mesa/drivers/dri/nouveau/nouveau_screen.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_SCREEN_H__
|
||||
#define __NOUVEAU_SCREEN_H__
|
||||
|
||||
#include "xmlconfig.h"
|
||||
|
||||
#include "nouveau_dri.h"
|
||||
#include "nouveau_card.h"
|
||||
|
||||
typedef struct {
|
||||
nouveau_card* card;
|
||||
u_int32_t bus_type;
|
||||
u_int32_t agp_mode;
|
||||
|
||||
GLint fbFormat;
|
||||
|
||||
GLuint frontOffset;
|
||||
GLuint frontPitch;
|
||||
GLuint backOffset;
|
||||
GLuint backPitch;
|
||||
|
||||
GLuint depthOffset;
|
||||
GLuint depthPitch;
|
||||
GLuint spanOffset;
|
||||
|
||||
__DRIscreenPrivate *driScreen;
|
||||
unsigned int sarea_priv_offset;
|
||||
|
||||
/* Configuration cache with default values for all contexts */
|
||||
driOptionCache optionCache;
|
||||
|
||||
} nouveauScreenRec, *nouveauScreenPtr;
|
||||
|
||||
|
||||
#endif /* __NOUVEAU_SCREEN_H__ */
|
||||
798
src/mesa/drivers/dri/nouveau/nouveau_shader.c
Normal file
798
src/mesa/drivers/dri/nouveau/nouveau_shader.c
Normal file
|
|
@ -0,0 +1,798 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Ben Skeggs.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Ben Skeggs <darktama@iinet.net.au>
|
||||
*/
|
||||
|
||||
#include "glheader.h"
|
||||
#include "macros.h"
|
||||
#include "enums.h"
|
||||
#include "extensions.h"
|
||||
|
||||
#include "program.h"
|
||||
#include "tnl/tnl.h"
|
||||
#include "shader/arbprogparse.h"
|
||||
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_shader.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Mesa entry points
|
||||
*/
|
||||
static void
|
||||
nouveauBindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog)
|
||||
{
|
||||
}
|
||||
|
||||
static struct gl_program *
|
||||
nouveauNewProgram(GLcontext *ctx, GLenum target, GLuint id)
|
||||
{
|
||||
nouveauShader *nvs;
|
||||
|
||||
nvs = CALLOC_STRUCT(_nouveauShader);
|
||||
switch (target) {
|
||||
case GL_VERTEX_PROGRAM_ARB:
|
||||
return _mesa_init_vertex_program(ctx, &nvs->mesa.vp, target, id);
|
||||
case GL_FRAGMENT_PROGRAM_ARB:
|
||||
return _mesa_init_fragment_program(ctx, &nvs->mesa.fp, target, id);
|
||||
default:
|
||||
_mesa_problem(ctx, "Unsupported shader target");
|
||||
break;
|
||||
}
|
||||
|
||||
FREE(nvs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveauDeleteProgram(GLcontext *ctx, struct gl_program *prog)
|
||||
{
|
||||
nouveauShader *nvs = (nouveauShader *)prog;
|
||||
|
||||
if (nvs->translated)
|
||||
FREE(nvs->program);
|
||||
_mesa_delete_program(ctx, prog);
|
||||
}
|
||||
|
||||
static void
|
||||
nouveauProgramStringNotify(GLcontext *ctx, GLenum target,
|
||||
struct gl_program *prog)
|
||||
{
|
||||
nouveauShader *nvs = (nouveauShader *)prog;
|
||||
|
||||
if (nvs->translated)
|
||||
FREE(nvs->program);
|
||||
nvs->translated = 0;
|
||||
|
||||
_tnl_program_string(ctx, target, prog);
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
nouveauIsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
|
||||
{
|
||||
nouveauShader *nvs = (nouveauShader *)prog;
|
||||
|
||||
return nvs->translated;
|
||||
}
|
||||
|
||||
GLboolean
|
||||
nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
struct gl_program_parameter_list *plist;
|
||||
int i;
|
||||
|
||||
/* Translate to HW format now if necessary */
|
||||
if (!nvs->translated) {
|
||||
/* Mesa ASM shader -> nouveauShader */
|
||||
if (!nouveau_shader_pass0_arb(ctx, nvs))
|
||||
return GL_FALSE;
|
||||
/* Basic dead code elimination + register usage info */
|
||||
if (!nouveau_shader_pass1(nvs))
|
||||
return GL_FALSE;
|
||||
/* nouveauShader -> HW bytecode, HW register alloc */
|
||||
if (!nouveau_shader_pass2(nvs))
|
||||
return GL_FALSE;
|
||||
assert(nvs->translated);
|
||||
assert(nvs->program);
|
||||
}
|
||||
|
||||
/* Update state parameters */
|
||||
plist = nvs->mesa.vp.Base.Parameters;
|
||||
_mesa_load_state_parameters(ctx, plist);
|
||||
for (i=0; i<plist->NumParameters; i++) {
|
||||
if (!nvs->on_hardware) {
|
||||
/* if we've been kicked off the hardware there's no guarantee our
|
||||
* consts are still there.. reupload them all
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Upload program to hardware, this must come after state param update
|
||||
* as >=NV30 fragprogs inline consts into the bytecode.
|
||||
*/
|
||||
if (!nvs->on_hardware) {
|
||||
nouveauShader **current;
|
||||
|
||||
if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB)
|
||||
current = &nmesa->current_vertprog;
|
||||
else
|
||||
current = &nmesa->current_fragprog;
|
||||
if (*current) (*current)->on_hardware = 0;
|
||||
|
||||
nvs->func->UploadToHW(ctx, nvs);
|
||||
nvs->on_hardware = 1;
|
||||
|
||||
*current = nvs;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
nouveauShader *
|
||||
nvsBuildTextShader(GLcontext *ctx, GLenum target, const char *text)
|
||||
{
|
||||
nouveauShader *nvs;
|
||||
|
||||
nvs = CALLOC_STRUCT(_nouveauShader);
|
||||
if (!nvs)
|
||||
return NULL;
|
||||
|
||||
if (target == GL_VERTEX_PROGRAM_ARB) {
|
||||
_mesa_init_vertex_program(ctx, &nvs->mesa.vp, GL_VERTEX_PROGRAM_ARB, 0);
|
||||
_mesa_parse_arb_vertex_program(ctx,
|
||||
GL_VERTEX_PROGRAM_ARB,
|
||||
text,
|
||||
strlen(text),
|
||||
&nvs->mesa.vp);
|
||||
} else if (target == GL_FRAGMENT_PROGRAM_ARB) {
|
||||
_mesa_init_fragment_program(ctx, &nvs->mesa.fp, GL_VERTEX_PROGRAM_ARB, 0);
|
||||
_mesa_parse_arb_fragment_program(ctx,
|
||||
GL_FRAGMENT_PROGRAM_ARB,
|
||||
text,
|
||||
strlen(text),
|
||||
&nvs->mesa.fp);
|
||||
}
|
||||
|
||||
nouveau_shader_pass0_arb(ctx, nvs);
|
||||
nouveau_shader_pass1(nvs);
|
||||
nouveau_shader_pass2(nvs);
|
||||
|
||||
return nvs;
|
||||
}
|
||||
|
||||
static void
|
||||
nvsBuildPassthroughVP(GLcontext *ctx)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
const char *vp_text =
|
||||
"!!ARBvp1.0\n"
|
||||
"OPTION ARB_position_invariant;"
|
||||
""
|
||||
"MOV result.color, vertex.color;\n"
|
||||
"MOV result.texcoord[0], vertex.texcoord[0];\n"
|
||||
"MOV result.texcoord[1], vertex.texcoord[1];\n"
|
||||
"MOV result.texcoord[2], vertex.texcoord[2];\n"
|
||||
"MOV result.texcoord[3], vertex.texcoord[3];\n"
|
||||
"MOV result.texcoord[4], vertex.texcoord[4];\n"
|
||||
"MOV result.texcoord[5], vertex.texcoord[5];\n"
|
||||
"MOV result.texcoord[6], vertex.texcoord[6];\n"
|
||||
"MOV result.texcoord[7], vertex.texcoord[7];\n"
|
||||
"END";
|
||||
|
||||
nmesa->passthrough_vp = nvsBuildTextShader(ctx,
|
||||
GL_VERTEX_PROGRAM_ARB,
|
||||
vp_text);
|
||||
}
|
||||
|
||||
void
|
||||
nouveauShaderInitFuncs(GLcontext * ctx)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
switch (nmesa->screen->card->type) {
|
||||
case NV_20:
|
||||
NV20VPInitShaderFuncs(&nmesa->VPfunc);
|
||||
break;
|
||||
case NV_30:
|
||||
NV30VPInitShaderFuncs(&nmesa->VPfunc);
|
||||
NV30FPInitShaderFuncs(&nmesa->FPfunc);
|
||||
break;
|
||||
case NV_40:
|
||||
case NV_44:
|
||||
NV40VPInitShaderFuncs(&nmesa->VPfunc);
|
||||
NV40FPInitShaderFuncs(&nmesa->FPfunc);
|
||||
break;
|
||||
case NV_50:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build a vertex program that simply passes through all attribs.
|
||||
* Needed to do swtcl on nv40
|
||||
*/
|
||||
if (nmesa->screen->card->type >= NV_40)
|
||||
nvsBuildPassthroughVP(ctx);
|
||||
|
||||
ctx->Const.VertexProgram.MaxNativeInstructions = nmesa->VPfunc.MaxInst;
|
||||
ctx->Const.VertexProgram.MaxNativeAluInstructions = nmesa->VPfunc.MaxInst;
|
||||
ctx->Const.VertexProgram.MaxNativeTexInstructions = nmesa->VPfunc.MaxInst;
|
||||
ctx->Const.VertexProgram.MaxNativeTexIndirections =
|
||||
ctx->Const.VertexProgram.MaxNativeTexInstructions;
|
||||
ctx->Const.VertexProgram.MaxNativeAttribs = nmesa->VPfunc.MaxAttrib;
|
||||
ctx->Const.VertexProgram.MaxNativeTemps = nmesa->VPfunc.MaxTemp;
|
||||
ctx->Const.VertexProgram.MaxNativeAddressRegs = nmesa->VPfunc.MaxAddress;
|
||||
ctx->Const.VertexProgram.MaxNativeParameters = nmesa->VPfunc.MaxConst;
|
||||
|
||||
if (nmesa->screen->card->type >= NV_30) {
|
||||
ctx->Const.FragmentProgram.MaxNativeInstructions = nmesa->FPfunc.MaxInst;
|
||||
ctx->Const.FragmentProgram.MaxNativeAluInstructions = nmesa->FPfunc.MaxInst;
|
||||
ctx->Const.FragmentProgram.MaxNativeTexInstructions = nmesa->FPfunc.MaxInst;
|
||||
ctx->Const.FragmentProgram.MaxNativeTexIndirections =
|
||||
ctx->Const.FragmentProgram.MaxNativeTexInstructions;
|
||||
ctx->Const.FragmentProgram.MaxNativeAttribs = nmesa->FPfunc.MaxAttrib;
|
||||
ctx->Const.FragmentProgram.MaxNativeTemps = nmesa->FPfunc.MaxTemp;
|
||||
ctx->Const.FragmentProgram.MaxNativeAddressRegs = nmesa->FPfunc.MaxAddress;
|
||||
ctx->Const.FragmentProgram.MaxNativeParameters = nmesa->FPfunc.MaxConst;
|
||||
}
|
||||
|
||||
ctx->Driver.NewProgram = nouveauNewProgram;
|
||||
ctx->Driver.BindProgram = nouveauBindProgram;
|
||||
ctx->Driver.DeleteProgram = nouveauDeleteProgram;
|
||||
ctx->Driver.ProgramStringNotify = nouveauProgramStringNotify;
|
||||
ctx->Driver.IsProgramNative = nouveauIsProgramNative;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Disassembly support structs
|
||||
*/
|
||||
#define CHECK_RANGE(idx, arr) ((idx)<sizeof(_##arr)/sizeof(const char *)) \
|
||||
? _##arr[(idx)] : #arr"_OOB"
|
||||
|
||||
#define NODS (1<<0)
|
||||
#define BRANCH_TR (1<<1)
|
||||
#define BRANCH_EL (1<<2)
|
||||
#define BRANCH_EN (1<<3)
|
||||
#define BRANCH_RE (1<<4)
|
||||
#define BRANCH_ALL (BRANCH_TR|BRANCH_EL|BRANCH_EN)
|
||||
#define COUNT_INC (1<<4)
|
||||
#define COUNT_IND (1<<5)
|
||||
#define COUNT_NUM (1<<6)
|
||||
#define COUNT_ALL (COUNT_INC|COUNT_IND|COUNT_NUM)
|
||||
#define TI_UNIT (1<<7)
|
||||
struct _opcode_info
|
||||
{
|
||||
const char *name;
|
||||
int numsrc;
|
||||
int flags;
|
||||
};
|
||||
|
||||
static struct _opcode_info ops[] = {
|
||||
[NVS_OP_ABS] = {"ABS", 1, 0},
|
||||
[NVS_OP_ADD] = {"ADD", 2, 0},
|
||||
[NVS_OP_ARA] = {"ARA", 1, 0},
|
||||
[NVS_OP_ARL] = {"ARL", 1, 0},
|
||||
[NVS_OP_ARR] = {"ARR", 1, 0},
|
||||
[NVS_OP_BRA] = {"BRA", 0, NODS | BRANCH_TR},
|
||||
[NVS_OP_BRK] = {"BRK", 0, NODS},
|
||||
[NVS_OP_CAL] = {"CAL", 0, NODS | BRANCH_TR},
|
||||
[NVS_OP_CMP] = {"CMP", 2, 0},
|
||||
[NVS_OP_COS] = {"COS", 1, 0},
|
||||
[NVS_OP_DIV] = {"DIV", 2, 0},
|
||||
[NVS_OP_DDX] = {"DDX", 1, 0},
|
||||
[NVS_OP_DDY] = {"DDY", 1, 0},
|
||||
[NVS_OP_DP2] = {"DP2", 2, 0},
|
||||
[NVS_OP_DP2A] = {"DP2A", 3, 0},
|
||||
[NVS_OP_DP3] = {"DP3", 2, 0},
|
||||
[NVS_OP_DP4] = {"DP4", 2, 0},
|
||||
[NVS_OP_DPH] = {"DPH", 2, 0},
|
||||
[NVS_OP_DST] = {"DST", 2, 0},
|
||||
[NVS_OP_EX2] = {"EX2", 1, 0},
|
||||
[NVS_OP_EXP] = {"EXP", 1, 0},
|
||||
[NVS_OP_FLR] = {"FLR", 1, 0},
|
||||
[NVS_OP_FRC] = {"FRC", 1, 0},
|
||||
[NVS_OP_IF] = {"IF", 0, NODS | BRANCH_EL | BRANCH_EN},
|
||||
[NVS_OP_KIL] = {"KIL", 1, 0},
|
||||
[NVS_OP_LG2] = {"LG2", 1, 0},
|
||||
[NVS_OP_LIT] = {"LIT", 1, 0},
|
||||
[NVS_OP_LOG] = {"LOG", 1, 0},
|
||||
[NVS_OP_LOOP] = {"LOOP", 0, NODS | COUNT_ALL | BRANCH_EN},
|
||||
[NVS_OP_LRP] = {"LRP", 3, 0},
|
||||
[NVS_OP_MAD] = {"MAD", 3, 0},
|
||||
[NVS_OP_MAX] = {"MAX", 2, 0},
|
||||
[NVS_OP_MIN] = {"MIN", 2, 0},
|
||||
[NVS_OP_MOV] = {"MOV", 1, 0},
|
||||
[NVS_OP_MUL] = {"MUL", 2, 0},
|
||||
[NVS_OP_NRM] = {"NRM", 1, 0},
|
||||
[NVS_OP_PK2H] = {"PK2H", 1, 0},
|
||||
[NVS_OP_PK2US] = {"PK2US", 1, 0},
|
||||
[NVS_OP_PK4B] = {"PK4B", 1, 0},
|
||||
[NVS_OP_PK4UB] = {"PK4UB", 1, 0},
|
||||
[NVS_OP_POW] = {"POW", 2, 0},
|
||||
[NVS_OP_POPA] = {"POPA", 0, 0},
|
||||
[NVS_OP_PUSHA] = {"PUSHA", 1, NODS},
|
||||
[NVS_OP_RCC] = {"RCC", 1, 0},
|
||||
[NVS_OP_RCP] = {"RCP", 1, 0},
|
||||
[NVS_OP_REP] = {"REP", 0, NODS | BRANCH_EN | COUNT_NUM},
|
||||
[NVS_OP_RET] = {"RET", 0, NODS},
|
||||
[NVS_OP_RFL] = {"RFL", 1, 0},
|
||||
[NVS_OP_RSQ] = {"RSQ", 1, 0},
|
||||
[NVS_OP_SCS] = {"SCS", 1, 0},
|
||||
[NVS_OP_SEQ] = {"SEQ", 2, 0},
|
||||
[NVS_OP_SFL] = {"SFL", 2, 0},
|
||||
[NVS_OP_SGE] = {"SGE", 2, 0},
|
||||
[NVS_OP_SGT] = {"SGT", 2, 0},
|
||||
[NVS_OP_SIN] = {"SIN", 1, 0},
|
||||
[NVS_OP_SLE] = {"SLE", 2, 0},
|
||||
[NVS_OP_SLT] = {"SLT", 2, 0},
|
||||
[NVS_OP_SNE] = {"SNE", 2, 0},
|
||||
[NVS_OP_SSG] = {"SSG", 1, 0},
|
||||
[NVS_OP_STR] = {"STR", 2, 0},
|
||||
[NVS_OP_SUB] = {"SUB", 2, 0},
|
||||
[NVS_OP_TEX] = {"TEX", 1, TI_UNIT},
|
||||
[NVS_OP_TXB] = {"TXB", 1, TI_UNIT},
|
||||
[NVS_OP_TXD] = {"TXD", 3, TI_UNIT},
|
||||
[NVS_OP_TXL] = {"TXL", 1, TI_UNIT},
|
||||
[NVS_OP_TXP] = {"TXP", 1, TI_UNIT},
|
||||
[NVS_OP_UP2H] = {"UP2H", 1, 0},
|
||||
[NVS_OP_UP2US] = {"UP2US", 1, 0},
|
||||
[NVS_OP_UP4B] = {"UP4B", 1, 0},
|
||||
[NVS_OP_UP4UB] = {"UP4UB", 1, 0},
|
||||
[NVS_OP_X2D] = {"X2D", 3, 0},
|
||||
[NVS_OP_XPD] = {"XPD", 2, 0},
|
||||
[NVS_OP_NOP] = {"NOP", 0, NODS},
|
||||
};
|
||||
|
||||
static struct _opcode_info *
|
||||
_get_op_info(int op)
|
||||
{
|
||||
if (op >= (sizeof(ops) / sizeof(struct _opcode_info)))
|
||||
return NULL;
|
||||
if (ops[op].name == NULL)
|
||||
return NULL;
|
||||
return &ops[op];
|
||||
}
|
||||
|
||||
static const char *_SFR_STRING[] = {
|
||||
[NVS_FR_POSITION] = "position",
|
||||
[NVS_FR_WEIGHT] = "weight",
|
||||
[NVS_FR_NORMAL] = "normal",
|
||||
[NVS_FR_COL0] = "color",
|
||||
[NVS_FR_COL1] = "color.secondary",
|
||||
[NVS_FR_BFC0] = "bfc",
|
||||
[NVS_FR_BFC1] = "bfc.secondary",
|
||||
[NVS_FR_FOGCOORD] = "fogcoord",
|
||||
[NVS_FR_POINTSZ] = "pointsize",
|
||||
[NVS_FR_TEXCOORD0] = "texcoord[0]",
|
||||
[NVS_FR_TEXCOORD1] = "texcoord[1]",
|
||||
[NVS_FR_TEXCOORD2] = "texcoord[2]",
|
||||
[NVS_FR_TEXCOORD3] = "texcoord[3]",
|
||||
[NVS_FR_TEXCOORD4] = "texcoord[4]",
|
||||
[NVS_FR_TEXCOORD5] = "texcoord[5]",
|
||||
[NVS_FR_TEXCOORD6] = "texcoord[6]",
|
||||
[NVS_FR_TEXCOORD7] = "texcoord[7]",
|
||||
[NVS_FR_FRAGDATA0] = "data[0]",
|
||||
[NVS_FR_FRAGDATA1] = "data[1]",
|
||||
[NVS_FR_FRAGDATA2] = "data[2]",
|
||||
[NVS_FR_FRAGDATA3] = "data[3]",
|
||||
[NVS_FR_CLIP0] = "clip_plane[0]",
|
||||
[NVS_FR_CLIP1] = "clip_plane[1]",
|
||||
[NVS_FR_CLIP2] = "clip_plane[2]",
|
||||
[NVS_FR_CLIP3] = "clip_plane[3]",
|
||||
[NVS_FR_CLIP4] = "clip_plane[4]",
|
||||
[NVS_FR_CLIP5] = "clip_plane[5]",
|
||||
[NVS_FR_CLIP6] = "clip_plane[6]",
|
||||
[NVS_FR_FACING] = "facing",
|
||||
};
|
||||
|
||||
#define SFR_STRING(idx) CHECK_RANGE((idx), SFR_STRING)
|
||||
|
||||
static const char *_SWZ_STRING[] = {
|
||||
[NVS_SWZ_X] = "x",
|
||||
[NVS_SWZ_Y] = "y",
|
||||
[NVS_SWZ_Z] = "z",
|
||||
[NVS_SWZ_W] = "w"
|
||||
};
|
||||
|
||||
#define SWZ_STRING(idx) CHECK_RANGE((idx), SWZ_STRING)
|
||||
|
||||
static const char *_NVS_PREC_STRING[] = {
|
||||
[NVS_PREC_FLOAT32] = "R",
|
||||
[NVS_PREC_FLOAT16] = "H",
|
||||
[NVS_PREC_FIXED12] = "X",
|
||||
[NVS_PREC_UNKNOWN] = "?"
|
||||
};
|
||||
|
||||
#define NVS_PREC_STRING(idx) CHECK_RANGE((idx), NVS_PREC_STRING)
|
||||
|
||||
static const char *_NVS_COND_STRING[] = {
|
||||
[NVS_COND_FL] = "FL",
|
||||
[NVS_COND_LT] = "LT",
|
||||
[NVS_COND_EQ] = "EQ",
|
||||
[NVS_COND_LE] = "LE",
|
||||
[NVS_COND_GT] = "GT",
|
||||
[NVS_COND_NE] = "NE",
|
||||
[NVS_COND_GE] = "GE",
|
||||
[NVS_COND_TR] = "TR",
|
||||
[NVS_COND_UNKNOWN] = "??"
|
||||
};
|
||||
|
||||
#define NVS_COND_STRING(idx) CHECK_RANGE((idx), NVS_COND_STRING)
|
||||
|
||||
/*****************************************************************************
|
||||
* ShaderFragment dumping
|
||||
*/
|
||||
static void
|
||||
nvsDumpIndent(int lvl)
|
||||
{
|
||||
while (lvl--)
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void
|
||||
nvsDumpSwizzle(nvsSwzComp *swz)
|
||||
{
|
||||
printf(".%s%s%s%s",
|
||||
SWZ_STRING(swz[0]),
|
||||
SWZ_STRING(swz[1]), SWZ_STRING(swz[2]), SWZ_STRING(swz[3])
|
||||
);
|
||||
}
|
||||
|
||||
static void
|
||||
nvsDumpReg(nvsInstruction * inst, nvsRegister * reg)
|
||||
{
|
||||
if (reg->negate)
|
||||
printf("-");
|
||||
if (reg->abs)
|
||||
printf("abs(");
|
||||
|
||||
switch (reg->file) {
|
||||
case NVS_FILE_TEMP:
|
||||
printf("R%d", reg->index);
|
||||
nvsDumpSwizzle(reg->swizzle);
|
||||
break;
|
||||
case NVS_FILE_ATTRIB:
|
||||
printf("attrib.%s", SFR_STRING(reg->index));
|
||||
nvsDumpSwizzle(reg->swizzle);
|
||||
break;
|
||||
case NVS_FILE_ADDRESS:
|
||||
printf("A%d", reg->index);
|
||||
break;
|
||||
case NVS_FILE_CONST:
|
||||
if (reg->indexed)
|
||||
printf("const[A%d.%s + %d]",
|
||||
reg->addr_reg, SWZ_STRING(reg->addr_comp), reg->index);
|
||||
else
|
||||
printf("const[%d]", reg->index);
|
||||
nvsDumpSwizzle(reg->swizzle);
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN_FILE");
|
||||
break;
|
||||
}
|
||||
|
||||
if (reg->abs)
|
||||
printf(")");
|
||||
}
|
||||
|
||||
static void
|
||||
nvsDumpInstruction(nvsInstruction * inst, int slot, int lvl)
|
||||
{
|
||||
struct _opcode_info *opr = &ops[inst->op];
|
||||
int i;
|
||||
|
||||
nvsDumpIndent(lvl);
|
||||
printf("%s ", opr->name);
|
||||
|
||||
if (!opr->flags & NODS) {
|
||||
switch (inst->dest.file) {
|
||||
case NVS_FILE_RESULT:
|
||||
printf("result.%s", SFR_STRING(inst->dest.index));
|
||||
break;
|
||||
case NVS_FILE_TEMP:
|
||||
printf("R%d", inst->dest.index);
|
||||
break;
|
||||
case NVS_FILE_ADDRESS:
|
||||
printf("A%d", inst->dest.index);
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN_DST_FILE");
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst->mask != SMASK_ALL) {
|
||||
printf(".");
|
||||
if (inst->mask & SMASK_X)
|
||||
printf("x");
|
||||
if (inst->mask & SMASK_Y)
|
||||
printf("y");
|
||||
if (inst->mask & SMASK_Z)
|
||||
printf("z");
|
||||
if (inst->mask & SMASK_W)
|
||||
printf("w");
|
||||
}
|
||||
|
||||
if (opr->numsrc)
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
for (i = 0; i < opr->numsrc; i++) {
|
||||
nvsDumpReg(inst, &inst->src[i]);
|
||||
if (i != opr->numsrc - 1)
|
||||
printf(", ");
|
||||
}
|
||||
if (opr->flags & TI_UNIT)
|
||||
printf(", texture[%d]", inst->tex_unit);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
nvsDumpFragmentList(nvsFragmentList *f, int lvl)
|
||||
{
|
||||
while (f) {
|
||||
switch (f->fragment->type) {
|
||||
case NVS_INSTRUCTION:
|
||||
nvsDumpInstruction((nvsInstruction*)f->fragment, 0, lvl);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: Only NVS_INSTRUCTION fragments can be in"
|
||||
"nvsFragmentList!\n", __func__);
|
||||
return;
|
||||
}
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* HW shader disassembly
|
||||
*/
|
||||
static void
|
||||
nvsDisasmHWShaderOp(nvsFunc * shader, int merged)
|
||||
{
|
||||
struct _opcode_info *opi;
|
||||
nvsOpcode op;
|
||||
nvsRegFile file;
|
||||
nvsSwzComp swz[4];
|
||||
int i;
|
||||
|
||||
op = shader->GetOpcode(shader, merged);
|
||||
opi = _get_op_info(op);
|
||||
if (!opi) {
|
||||
printf("NO OPINFO!");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s", opi->name);
|
||||
if (shader->GetPrecision &&
|
||||
(!(opi->flags & BRANCH_ALL)) && (!(opi->flags * NODS)) &&
|
||||
(op != NVS_OP_NOP))
|
||||
printf("%s", NVS_PREC_STRING(shader->GetPrecision(shader)));
|
||||
if (shader->SupportsConditional && shader->SupportsConditional(shader)) {
|
||||
if (shader->GetConditionUpdate(shader)) {
|
||||
printf("C%d", shader->GetCondRegID(shader));
|
||||
}
|
||||
}
|
||||
if (shader->GetSaturate && shader->GetSaturate(shader))
|
||||
printf("_SAT");
|
||||
|
||||
if (!(opi->flags & NODS)) {
|
||||
int mask = shader->GetDestMask(shader, merged);
|
||||
|
||||
switch (shader->GetDestFile(shader, merged)) {
|
||||
case NVS_FILE_ADDRESS:
|
||||
printf(" A%d", shader->GetDestID(shader, merged));
|
||||
break;
|
||||
case NVS_FILE_TEMP:
|
||||
printf(" R%d", shader->GetDestID(shader, merged));
|
||||
break;
|
||||
case NVS_FILE_RESULT:
|
||||
printf(" result.%s", (SFR_STRING(shader->GetDestID(shader, merged))));
|
||||
break;
|
||||
default:
|
||||
printf(" BAD_RESULT_FILE");
|
||||
break;
|
||||
}
|
||||
|
||||
if (mask != SMASK_ALL) {
|
||||
printf(".");
|
||||
if (mask & SMASK_X) printf("x");
|
||||
if (mask & SMASK_Y) printf("y");
|
||||
if (mask & SMASK_Z) printf("z");
|
||||
if (mask & SMASK_W) printf("w");
|
||||
}
|
||||
}
|
||||
|
||||
if (shader->SupportsConditional && shader->SupportsConditional(shader) &&
|
||||
shader->GetConditionTest(shader)) {
|
||||
shader->GetCondRegSwizzle(shader, swz);
|
||||
|
||||
printf(" (%s%d.%s%s%s%s)",
|
||||
NVS_COND_STRING(shader->GetCondition(shader)),
|
||||
shader->GetCondRegID(shader),
|
||||
SWZ_STRING(swz[NVS_SWZ_X]),
|
||||
SWZ_STRING(swz[NVS_SWZ_Y]),
|
||||
SWZ_STRING(swz[NVS_SWZ_Z]),
|
||||
SWZ_STRING(swz[NVS_SWZ_W])
|
||||
);
|
||||
}
|
||||
|
||||
/* looping */
|
||||
if (opi->flags & COUNT_ALL) {
|
||||
printf(" { ");
|
||||
if (opi->flags & COUNT_NUM) {
|
||||
printf("%d", shader->GetLoopCount(shader));
|
||||
}
|
||||
if (opi->flags & COUNT_IND) {
|
||||
printf(", %d", shader->GetLoopInitial(shader));
|
||||
}
|
||||
if (opi->flags & COUNT_INC) {
|
||||
printf(", %d", shader->GetLoopIncrement(shader));
|
||||
}
|
||||
printf(" }");
|
||||
}
|
||||
|
||||
/* branching */
|
||||
if (opi->flags & BRANCH_TR)
|
||||
printf(" %d", shader->GetBranch(shader));
|
||||
if (opi->flags & BRANCH_EL)
|
||||
printf(" ELSE %d", shader->GetBranchElse(shader));
|
||||
if (opi->flags & BRANCH_EN)
|
||||
printf(" END %d", shader->GetBranchEnd(shader));
|
||||
|
||||
if (!(opi->flags & NODS) && opi->numsrc)
|
||||
printf(",");
|
||||
printf(" ");
|
||||
|
||||
for (i = 0; i < opi->numsrc; i++) {
|
||||
if (shader->GetSourceAbs(shader, merged, i))
|
||||
printf("abs(");
|
||||
if (shader->GetSourceNegate(shader, merged, i))
|
||||
printf("-");
|
||||
|
||||
file = shader->GetSourceFile(shader, merged, i);
|
||||
switch (file) {
|
||||
case NVS_FILE_TEMP:
|
||||
printf("R%d", shader->GetSourceID(shader, merged, i));
|
||||
break;
|
||||
case NVS_FILE_CONST:
|
||||
if (shader->GetSourceIndexed(shader, merged, i)) {
|
||||
printf("c[A%d.%s + 0x%x]",
|
||||
shader->GetRelAddressRegID(shader),
|
||||
SWZ_STRING(shader->GetRelAddressSwizzle(shader)),
|
||||
shader->GetSourceID(shader, merged, i)
|
||||
);
|
||||
} else {
|
||||
float val[4];
|
||||
|
||||
if (shader->GetSourceConstVal) {
|
||||
shader->GetSourceConstVal(shader, merged, i, val);
|
||||
printf("{ %.02f, %.02f, %.02f, %.02f }",
|
||||
val[0], val[1], val[2], val[3]);
|
||||
} else {
|
||||
printf("c[0x%x]", shader->GetSourceID(shader, merged, i));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NVS_FILE_ATTRIB:
|
||||
if (shader->GetSourceIndexed(shader, merged, i)) {
|
||||
printf("attrib[A%d.%s + %d]",
|
||||
shader->GetRelAddressRegID(shader),
|
||||
SWZ_STRING(shader->GetRelAddressSwizzle(shader)),
|
||||
shader->GetSourceID(shader, merged, i)
|
||||
);
|
||||
}
|
||||
else {
|
||||
printf("attrib.%s",
|
||||
SFR_STRING(shader->GetSourceID(shader, merged, i))
|
||||
);
|
||||
}
|
||||
break;
|
||||
case NVS_FILE_ADDRESS:
|
||||
printf("A%d", shader->GetRelAddressRegID(shader));
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN_SRC_FILE");
|
||||
break;
|
||||
}
|
||||
|
||||
shader->GetSourceSwizzle(shader, merged, i, swz);
|
||||
if (file != NVS_FILE_ADDRESS &&
|
||||
(swz[NVS_SWZ_X] != NVS_SWZ_X || swz[NVS_SWZ_Y] != NVS_SWZ_Y ||
|
||||
swz[NVS_SWZ_Z] != NVS_SWZ_Z || swz[NVS_SWZ_W] != NVS_SWZ_W)) {
|
||||
printf(".%s%s%s%s", SWZ_STRING(swz[NVS_SWZ_X]),
|
||||
SWZ_STRING(swz[NVS_SWZ_Y]),
|
||||
SWZ_STRING(swz[NVS_SWZ_Z]),
|
||||
SWZ_STRING(swz[NVS_SWZ_W]));
|
||||
}
|
||||
|
||||
if (shader->GetSourceAbs(shader, merged, i))
|
||||
printf(")");
|
||||
if (shader->GetSourceScale) {
|
||||
int scale = shader->GetSourceScale(shader, merged, i);
|
||||
if (scale > 1)
|
||||
printf("{scaled %dx}", scale);
|
||||
}
|
||||
if (i < (opi->numsrc - 1))
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
if (shader->IsLastInst(shader))
|
||||
printf(" + END");
|
||||
}
|
||||
|
||||
void
|
||||
nvsDisasmHWShader(nvsPtr nvs)
|
||||
{
|
||||
nvsFunc *shader = nvs->func;
|
||||
unsigned int iaddr = 0;
|
||||
|
||||
if (!nvs->program) {
|
||||
fprintf(stderr, "No HW program present");
|
||||
return;
|
||||
}
|
||||
|
||||
shader->inst = nvs->program;
|
||||
while (1) {
|
||||
if (shader->inst >= (nvs->program + nvs->program_size)) {
|
||||
fprintf(stderr, "Reached end of program, but HW inst has no END");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\t0x%08x:\n", shader->inst[0]);
|
||||
printf("\t0x%08x:\n", shader->inst[1]);
|
||||
printf("\t0x%08x:\n", shader->inst[2]);
|
||||
printf("\t0x%08x:", shader->inst[3]);
|
||||
|
||||
printf("\n\t\tINST %d.0: ", iaddr);
|
||||
nvsDisasmHWShaderOp(shader, 0);
|
||||
if (shader->HasMergedInst(shader)) {
|
||||
printf("\n\t\tINST %d.1: ", iaddr);
|
||||
nvsDisasmHWShaderOp(shader, 1);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (shader->IsLastInst(shader))
|
||||
break;
|
||||
|
||||
shader->inst += shader->GetOffsetNext(shader);
|
||||
iaddr++;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
371
src/mesa/drivers/dri/nouveau/nouveau_shader.h
Normal file
371
src/mesa/drivers/dri/nouveau/nouveau_shader.h
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
#ifndef __SHADER_COMMON_H__
|
||||
#define __SHADER_COMMON_H__
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "nouveau_buffers.h"
|
||||
|
||||
typedef struct _nvsFunc nvsFunc;
|
||||
|
||||
#define NVS_MAX_TEMPS 32
|
||||
#define NVS_MAX_ATTRIBS 16
|
||||
#define NVS_MAX_CONSTS 256
|
||||
#define NVS_MAX_ADDRESS 2
|
||||
#define NVS_MAX_INSNS 4096
|
||||
|
||||
typedef struct {
|
||||
enum {
|
||||
NVS_INSTRUCTION,
|
||||
} type;
|
||||
int position;
|
||||
} nvsFragmentHeader;
|
||||
|
||||
typedef struct _nvs_fragment_list {
|
||||
struct _nvs_fragment_list *prev;
|
||||
struct _nvs_fragment_list *next;
|
||||
nvsFragmentHeader *fragment;
|
||||
} nvsFragmentList;
|
||||
|
||||
typedef struct _nouveauShader {
|
||||
union {
|
||||
struct gl_vertex_program vp;
|
||||
struct gl_fragment_program fp;
|
||||
} mesa;
|
||||
GLcontext *ctx;
|
||||
nvsFunc *func;
|
||||
|
||||
/* State of the final program */
|
||||
GLboolean translated;
|
||||
GLboolean on_hardware;
|
||||
unsigned int *program;
|
||||
unsigned int program_size;
|
||||
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;
|
||||
|
||||
struct {
|
||||
GLfloat *source_val; /* NULL if invariant */
|
||||
float val[4];
|
||||
/* Hardware-specific tracking, currently only nv30_fragprog
|
||||
* makes use of it.
|
||||
*/
|
||||
int *hw_index;
|
||||
int hw_index_cnt;
|
||||
} params[NVS_MAX_CONSTS];
|
||||
|
||||
struct {
|
||||
int last_use;
|
||||
} temps[NVS_MAX_TEMPS];
|
||||
|
||||
/* Pass-private data */
|
||||
void *pass_rec;
|
||||
|
||||
nvsFragmentList *list_head;
|
||||
nvsFragmentList *list_tail;
|
||||
} nouveauShader, *nvsPtr;
|
||||
|
||||
typedef enum {
|
||||
NVS_FILE_NONE,
|
||||
NVS_FILE_TEMP,
|
||||
NVS_FILE_ATTRIB,
|
||||
NVS_FILE_CONST,
|
||||
NVS_FILE_RESULT,
|
||||
NVS_FILE_ADDRESS,
|
||||
NVS_FILE_UNKNOWN
|
||||
} nvsRegFile;
|
||||
|
||||
typedef enum {
|
||||
NVS_OP_UNKNOWN = 0,
|
||||
NVS_OP_NOP,
|
||||
NVS_OP_ABS, NVS_OP_ADD, NVS_OP_ARA, NVS_OP_ARL, NVS_OP_ARR,
|
||||
NVS_OP_BRA, NVS_OP_BRK,
|
||||
NVS_OP_CAL, NVS_OP_CMP, NVS_OP_COS,
|
||||
NVS_OP_DDX, NVS_OP_DDY, NVS_OP_DIV, NVS_OP_DP2, NVS_OP_DP2A, NVS_OP_DP3,
|
||||
NVS_OP_DP4, NVS_OP_DPH, NVS_OP_DST,
|
||||
NVS_OP_EX2, NVS_OP_EXP,
|
||||
NVS_OP_FLR, NVS_OP_FRC,
|
||||
NVS_OP_IF,
|
||||
NVS_OP_KIL,
|
||||
NVS_OP_LG2, NVS_OP_LIT, NVS_OP_LOG, NVS_OP_LOOP, NVS_OP_LRP,
|
||||
NVS_OP_MAD, NVS_OP_MAX, NVS_OP_MIN, NVS_OP_MOV, NVS_OP_MUL,
|
||||
NVS_OP_NRM,
|
||||
NVS_OP_PK2H, NVS_OP_PK2US, NVS_OP_PK4B, NVS_OP_PK4UB, NVS_OP_POW,
|
||||
NVS_OP_POPA, NVS_OP_PUSHA,
|
||||
NVS_OP_RCC, NVS_OP_RCP, NVS_OP_REP, NVS_OP_RET, NVS_OP_RFL, NVS_OP_RSQ,
|
||||
NVS_OP_SCS, NVS_OP_SEQ, NVS_OP_SFL, NVS_OP_SGE, NVS_OP_SGT, NVS_OP_SIN,
|
||||
NVS_OP_SLE, NVS_OP_SLT, NVS_OP_SNE, NVS_OP_SSG, NVS_OP_STR, NVS_OP_SUB,
|
||||
NVS_OP_SWZ,
|
||||
NVS_OP_TEX, NVS_OP_TXB, NVS_OP_TXD, NVS_OP_TXL, NVS_OP_TXP,
|
||||
NVS_OP_UP2H, NVS_OP_UP2US, NVS_OP_UP4B, NVS_OP_UP4UB,
|
||||
NVS_OP_X2D, NVS_OP_XPD,
|
||||
NVS_OP_EMUL
|
||||
} nvsOpcode;
|
||||
|
||||
typedef enum {
|
||||
NVS_PREC_FLOAT32,
|
||||
NVS_PREC_FLOAT16,
|
||||
NVS_PREC_FIXED12,
|
||||
NVS_PREC_UNKNOWN
|
||||
} nvsPrecision;
|
||||
|
||||
typedef enum {
|
||||
NVS_SWZ_X = 0,
|
||||
NVS_SWZ_Y = 1,
|
||||
NVS_SWZ_Z = 2,
|
||||
NVS_SWZ_W = 3
|
||||
} nvsSwzComp;
|
||||
|
||||
typedef enum {
|
||||
NVS_FR_POSITION,
|
||||
NVS_FR_WEIGHT,
|
||||
NVS_FR_NORMAL,
|
||||
NVS_FR_COL0,
|
||||
NVS_FR_COL1,
|
||||
NVS_FR_BFC0,
|
||||
NVS_FR_BFC1,
|
||||
NVS_FR_FOGCOORD,
|
||||
NVS_FR_POINTSZ,
|
||||
NVS_FR_TEXCOORD0,
|
||||
NVS_FR_TEXCOORD1,
|
||||
NVS_FR_TEXCOORD2,
|
||||
NVS_FR_TEXCOORD3,
|
||||
NVS_FR_TEXCOORD4,
|
||||
NVS_FR_TEXCOORD5,
|
||||
NVS_FR_TEXCOORD6,
|
||||
NVS_FR_TEXCOORD7,
|
||||
NVS_FR_FRAGDATA0,
|
||||
NVS_FR_FRAGDATA1,
|
||||
NVS_FR_FRAGDATA2,
|
||||
NVS_FR_FRAGDATA3,
|
||||
NVS_FR_CLIP0,
|
||||
NVS_FR_CLIP1,
|
||||
NVS_FR_CLIP2,
|
||||
NVS_FR_CLIP3,
|
||||
NVS_FR_CLIP4,
|
||||
NVS_FR_CLIP5,
|
||||
NVS_FR_CLIP6,
|
||||
NVS_FR_FACING,
|
||||
NVS_FR_UNKNOWN
|
||||
} nvsFixedReg;
|
||||
|
||||
typedef enum {
|
||||
NVS_COND_FL, NVS_COND_LT, NVS_COND_EQ, NVS_COND_LE, NVS_COND_GT,
|
||||
NVS_COND_NE, NVS_COND_GE, NVS_COND_TR, NVS_COND_UN,
|
||||
NVS_COND_UNKNOWN
|
||||
} nvsCond;
|
||||
|
||||
typedef struct {
|
||||
nvsRegFile file;
|
||||
unsigned int index;
|
||||
|
||||
unsigned int indexed;
|
||||
unsigned int addr_reg;
|
||||
nvsSwzComp addr_comp;
|
||||
|
||||
nvsSwzComp swizzle[4];
|
||||
int negate;
|
||||
int abs;
|
||||
} nvsRegister;
|
||||
|
||||
static const nvsRegister nvr_unused = {
|
||||
.file = NVS_FILE_ATTRIB,
|
||||
.index = 0,
|
||||
.indexed = 0,
|
||||
.addr_reg = 0,
|
||||
.addr_comp = NVS_SWZ_X,
|
||||
.swizzle = {NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W},
|
||||
.negate = 0,
|
||||
.abs = 0,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NVS_TEX_TARGET_1D,
|
||||
NVS_TEX_TARGET_2D,
|
||||
NVS_TEX_TARGET_3D,
|
||||
NVS_TEX_TARGET_CUBE,
|
||||
NVS_TEX_TARGET_RECT,
|
||||
NVS_TEX_TARGET_UNKNOWN = 0
|
||||
} nvsTexTarget;
|
||||
|
||||
typedef struct {
|
||||
nvsFragmentHeader header;
|
||||
|
||||
nvsOpcode op;
|
||||
unsigned int saturate;
|
||||
|
||||
nvsRegister dest;
|
||||
unsigned int mask;
|
||||
|
||||
nvsRegister src[3];
|
||||
|
||||
unsigned int tex_unit;
|
||||
nvsTexTarget tex_target;
|
||||
|
||||
nvsCond cond;
|
||||
nvsSwzComp cond_swizzle[4];
|
||||
int cond_reg;
|
||||
int cond_test;
|
||||
int cond_update;
|
||||
} nvsInstruction;
|
||||
|
||||
#define SMASK_X (1<<0)
|
||||
#define SMASK_Y (1<<1)
|
||||
#define SMASK_Z (1<<2)
|
||||
#define SMASK_W (1<<3)
|
||||
#define SMASK_ALL (SMASK_X|SMASK_Y|SMASK_Z|SMASK_W)
|
||||
|
||||
#define SPOS_ADDRESS 3
|
||||
struct _op_xlat {
|
||||
unsigned int NV;
|
||||
nvsOpcode SOP;
|
||||
int srcpos[3];
|
||||
};
|
||||
#define MOD_OPCODE(t,hw,sop,s0,s1,s2) do { \
|
||||
t[hw].NV = hw; \
|
||||
t[hw].SOP = sop; \
|
||||
t[hw].srcpos[0] = s0; \
|
||||
t[hw].srcpos[1] = s1; \
|
||||
t[hw].srcpos[2] = s2; \
|
||||
} while(0)
|
||||
|
||||
extern unsigned int NVVP_TX_VOP_COUNT;
|
||||
extern unsigned int NVVP_TX_NVS_OP_COUNT;
|
||||
extern struct _op_xlat NVVP_TX_VOP[];
|
||||
extern struct _op_xlat NVVP_TX_SOP[];
|
||||
|
||||
extern unsigned int NVFP_TX_AOP_COUNT;
|
||||
extern unsigned int NVFP_TX_BOP_COUNT;
|
||||
extern struct _op_xlat NVFP_TX_AOP[];
|
||||
extern struct _op_xlat NVFP_TX_BOP[];
|
||||
|
||||
#define SCAP_SRC_ABS (1<<0)
|
||||
|
||||
struct _nvsFunc {
|
||||
unsigned int MaxInst;
|
||||
unsigned int MaxAttrib;
|
||||
unsigned int MaxTemp;
|
||||
unsigned int MaxAddress;
|
||||
unsigned int MaxConst;
|
||||
unsigned int caps;
|
||||
|
||||
unsigned int *inst;
|
||||
void (*UploadToHW) (GLcontext *, nouveauShader *);
|
||||
void (*UpdateConst) (GLcontext *, nouveauShader *, int);
|
||||
|
||||
struct _op_xlat*(*GetOPTXRec) (nvsFunc *, int merged);
|
||||
struct _op_xlat*(*GetOPTXFromSOP) (nvsOpcode, int *id);
|
||||
|
||||
void (*InitInstruction) (nvsFunc *);
|
||||
int (*SupportsOpcode) (nvsFunc *, nvsOpcode);
|
||||
void (*SetOpcode) (nvsFunc *, unsigned int opcode,
|
||||
int slot);
|
||||
void (*SetCCUpdate) (nvsFunc *);
|
||||
void (*SetCondition) (nvsFunc *, int on, nvsCond, int reg,
|
||||
nvsSwzComp *swizzle);
|
||||
void (*SetResult) (nvsFunc *, nvsRegister *,
|
||||
unsigned int mask, int slot);
|
||||
void (*SetSource) (nvsFunc *, nvsRegister *, int pos);
|
||||
void (*SetTexImageUnit) (nvsFunc *, int unit);
|
||||
void (*SetSaturate) (nvsFunc *);
|
||||
void (*SetLastInst) (nvsFunc *);
|
||||
|
||||
int (*HasMergedInst) (nvsFunc *);
|
||||
int (*IsLastInst) (nvsFunc *);
|
||||
int (*GetOffsetNext) (nvsFunc *);
|
||||
|
||||
int (*GetOpcodeSlot) (nvsFunc *, int merged);
|
||||
unsigned int (*GetOpcodeHW) (nvsFunc *, int slot);
|
||||
nvsOpcode (*GetOpcode) (nvsFunc *, int merged);
|
||||
|
||||
nvsPrecision (*GetPrecision) (nvsFunc *);
|
||||
int (*GetSaturate) (nvsFunc *);
|
||||
|
||||
nvsRegFile (*GetDestFile) (nvsFunc *, int merged);
|
||||
unsigned int (*GetDestID) (nvsFunc *, int merged);
|
||||
unsigned int (*GetDestMask) (nvsFunc *, int merged);
|
||||
|
||||
unsigned int (*GetSourceHW) (nvsFunc *, int merged, int pos);
|
||||
nvsRegFile (*GetSourceFile) (nvsFunc *, int merged, int pos);
|
||||
int (*GetSourceID) (nvsFunc *, int merged, int pos);
|
||||
int (*GetTexImageUnit) (nvsFunc *);
|
||||
int (*GetSourceNegate) (nvsFunc *, int merged, int pos);
|
||||
int (*GetSourceAbs) (nvsFunc *, int merged, int pos);
|
||||
void (*GetSourceSwizzle) (nvsFunc *, int merged, int pos,
|
||||
nvsSwzComp *swz);
|
||||
int (*GetSourceIndexed) (nvsFunc *, int merged, int pos);
|
||||
void (*GetSourceConstVal) (nvsFunc *, int merged, int pos,
|
||||
float *val);
|
||||
int (*GetSourceScale) (nvsFunc *, int merged, int pos);
|
||||
|
||||
int (*GetRelAddressRegID) (nvsFunc *);
|
||||
nvsSwzComp (*GetRelAddressSwizzle) (nvsFunc *);
|
||||
|
||||
int (*SupportsConditional) (nvsFunc *);
|
||||
int (*GetConditionUpdate) (nvsFunc *);
|
||||
int (*GetConditionTest) (nvsFunc *);
|
||||
nvsCond (*GetCondition) (nvsFunc *);
|
||||
void (*GetCondRegSwizzle) (nvsFunc *, nvsSwzComp *swz);
|
||||
int (*GetCondRegID) (nvsFunc *);
|
||||
int (*GetBranch) (nvsFunc *);
|
||||
int (*GetBranchElse) (nvsFunc *);
|
||||
int (*GetBranchEnd) (nvsFunc *);
|
||||
|
||||
int (*GetLoopCount) (nvsFunc *);
|
||||
int (*GetLoopInitial) (nvsFunc *);
|
||||
int (*GetLoopIncrement) (nvsFunc *);
|
||||
};
|
||||
|
||||
static inline nvsRegister
|
||||
nvsNegate(nvsRegister reg)
|
||||
{
|
||||
reg.negate = !reg.negate;
|
||||
return reg;
|
||||
}
|
||||
|
||||
static inline nvsRegister
|
||||
nvsAbs(nvsRegister reg)
|
||||
{
|
||||
reg.abs = 1;
|
||||
return reg;
|
||||
}
|
||||
|
||||
static inline nvsRegister
|
||||
nvsSwizzle(nvsRegister reg, nvsSwzComp x, nvsSwzComp y,
|
||||
nvsSwzComp z, nvsSwzComp w)
|
||||
{
|
||||
nvsSwzComp sc[4] = { x, y, z, w };
|
||||
nvsSwzComp oc[4];
|
||||
int i;
|
||||
|
||||
for (i=0;i<4;i++)
|
||||
oc[i] = reg.swizzle[i];
|
||||
for (i=0;i<4;i++)
|
||||
reg.swizzle[i] = oc[sc[i]];
|
||||
return reg;
|
||||
}
|
||||
|
||||
extern GLboolean nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs);
|
||||
extern void nvsDisasmHWShader(nvsPtr);
|
||||
extern void nvsDumpFragmentList(nvsFragmentList *f, int lvl);
|
||||
extern nouveauShader *nvsBuildTextShader(GLcontext *ctx, GLenum target,
|
||||
const char *text);
|
||||
|
||||
extern void NV20VPInitShaderFuncs(nvsFunc *);
|
||||
extern void NV30VPInitShaderFuncs(nvsFunc *);
|
||||
extern void NV40VPInitShaderFuncs(nvsFunc *);
|
||||
|
||||
extern void NV30FPInitShaderFuncs(nvsFunc *);
|
||||
extern void NV40FPInitShaderFuncs(nvsFunc *);
|
||||
|
||||
extern void nouveauShaderInitFuncs(GLcontext *ctx);
|
||||
|
||||
extern GLboolean nouveau_shader_pass0_arb(GLcontext *ctx, nouveauShader *nvs);
|
||||
extern GLboolean nouveau_shader_pass0_slang(GLcontext *ctx, nouveauShader *nvs);
|
||||
extern GLboolean nouveau_shader_pass1(nvsPtr nvs);
|
||||
extern GLboolean nouveau_shader_pass2(nvsPtr nvs);
|
||||
|
||||
#endif
|
||||
|
||||
710
src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c
Normal file
710
src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c
Normal file
|
|
@ -0,0 +1,710 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Ben Skeggs.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Ben Skeggs <darktama@iinet.net.au>
|
||||
*/
|
||||
|
||||
#include "glheader.h"
|
||||
#include "macros.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "program.h"
|
||||
#include "programopt.h"
|
||||
#include "program_instruction.h"
|
||||
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_shader.h"
|
||||
|
||||
static nvsFixedReg _tx_mesa_vp_dst_reg[VERT_RESULT_MAX] = {
|
||||
NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD,
|
||||
NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3,
|
||||
NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7,
|
||||
NVS_FR_POINTSZ, NVS_FR_BFC0, NVS_FR_BFC1, NVS_FR_UNKNOWN /* EDGE */
|
||||
};
|
||||
|
||||
static nvsFixedReg _tx_mesa_fp_dst_reg[FRAG_RESULT_MAX] = {
|
||||
NVS_FR_FRAGDATA0 /* COLR */, NVS_FR_FRAGDATA0 /* COLH */,
|
||||
NVS_FR_UNKNOWN /* DEPR */
|
||||
};
|
||||
|
||||
static nvsFixedReg _tx_mesa_vp_src_reg[VERT_ATTRIB_MAX] = {
|
||||
NVS_FR_POSITION, NVS_FR_WEIGHT, NVS_FR_NORMAL, NVS_FR_COL0, NVS_FR_COL1,
|
||||
NVS_FR_FOGCOORD, NVS_FR_UNKNOWN /* COLOR_INDEX */, NVS_FR_UNKNOWN,
|
||||
NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3,
|
||||
NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7,
|
||||
/* Generic attribs 0-15, aliased to the above */
|
||||
NVS_FR_POSITION, NVS_FR_WEIGHT, NVS_FR_NORMAL, NVS_FR_COL0, NVS_FR_COL1,
|
||||
NVS_FR_FOGCOORD, NVS_FR_UNKNOWN /* COLOR_INDEX */, NVS_FR_UNKNOWN,
|
||||
NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3,
|
||||
NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7
|
||||
};
|
||||
|
||||
static nvsFixedReg _tx_mesa_fp_src_reg[FRAG_ATTRIB_MAX] = {
|
||||
NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD,
|
||||
NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3,
|
||||
NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7
|
||||
};
|
||||
|
||||
static nvsSwzComp _tx_mesa_swizzle[4] = {
|
||||
NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W
|
||||
};
|
||||
|
||||
static nvsOpcode _tx_mesa_opcode[] = {
|
||||
[OPCODE_ABS] = NVS_OP_ABS, [OPCODE_ADD] = NVS_OP_ADD,
|
||||
[OPCODE_ARA] = NVS_OP_ARA, [OPCODE_ARL] = NVS_OP_ARL,
|
||||
[OPCODE_ARL_NV] = NVS_OP_ARL, [OPCODE_ARR] = NVS_OP_ARR,
|
||||
[OPCODE_CMP] = NVS_OP_CMP, [OPCODE_COS] = NVS_OP_COS,
|
||||
[OPCODE_DDX] = NVS_OP_DDX, [OPCODE_DDY] = NVS_OP_DDY,
|
||||
[OPCODE_DP3] = NVS_OP_DP3, [OPCODE_DP4] = NVS_OP_DP4,
|
||||
[OPCODE_DPH] = NVS_OP_DPH, [OPCODE_DST] = NVS_OP_DST,
|
||||
[OPCODE_EX2] = NVS_OP_EX2, [OPCODE_EXP] = NVS_OP_EXP,
|
||||
[OPCODE_FLR] = NVS_OP_FLR, [OPCODE_FRC] = NVS_OP_FRC,
|
||||
[OPCODE_KIL] = NVS_OP_EMUL, [OPCODE_KIL_NV] = NVS_OP_KIL,
|
||||
[OPCODE_LG2] = NVS_OP_LG2, [OPCODE_LIT] = NVS_OP_LIT,
|
||||
[OPCODE_LOG] = NVS_OP_LOG,
|
||||
[OPCODE_LRP] = NVS_OP_LRP,
|
||||
[OPCODE_MAD] = NVS_OP_MAD, [OPCODE_MAX] = NVS_OP_MAX,
|
||||
[OPCODE_MIN] = NVS_OP_MIN, [OPCODE_MOV] = NVS_OP_MOV,
|
||||
[OPCODE_MUL] = NVS_OP_MUL,
|
||||
[OPCODE_PK2H] = NVS_OP_PK2H, [OPCODE_PK2US] = NVS_OP_PK2US,
|
||||
[OPCODE_PK4B] = NVS_OP_PK4B, [OPCODE_PK4UB] = NVS_OP_PK4UB,
|
||||
[OPCODE_POW] = NVS_OP_POW, [OPCODE_POPA] = NVS_OP_POPA,
|
||||
[OPCODE_PUSHA] = NVS_OP_PUSHA,
|
||||
[OPCODE_RCC] = NVS_OP_RCC, [OPCODE_RCP] = NVS_OP_RCP,
|
||||
[OPCODE_RFL] = NVS_OP_RFL, [OPCODE_RSQ] = NVS_OP_RSQ,
|
||||
[OPCODE_SCS] = NVS_OP_SCS, [OPCODE_SEQ] = NVS_OP_SEQ,
|
||||
[OPCODE_SFL] = NVS_OP_SFL, [OPCODE_SGE] = NVS_OP_SGE,
|
||||
[OPCODE_SGT] = NVS_OP_SGT, [OPCODE_SIN] = NVS_OP_SIN,
|
||||
[OPCODE_SLE] = NVS_OP_SLE, [OPCODE_SLT] = NVS_OP_SLT,
|
||||
[OPCODE_SNE] = NVS_OP_SNE, [OPCODE_SSG] = NVS_OP_SSG,
|
||||
[OPCODE_STR] = NVS_OP_STR, [OPCODE_SUB] = NVS_OP_SUB,
|
||||
[OPCODE_SWZ] = NVS_OP_MOV,
|
||||
[OPCODE_TEX] = NVS_OP_TEX, [OPCODE_TXB] = NVS_OP_TXB,
|
||||
[OPCODE_TXD] = NVS_OP_TXD,
|
||||
[OPCODE_TXL] = NVS_OP_TXL, [OPCODE_TXP] = NVS_OP_TXP,
|
||||
[OPCODE_TXP_NV] = NVS_OP_TXP,
|
||||
[OPCODE_UP2H] = NVS_OP_UP2H, [OPCODE_UP2US] = NVS_OP_UP2US,
|
||||
[OPCODE_UP4B] = NVS_OP_UP4B, [OPCODE_UP4UB] = NVS_OP_UP4UB,
|
||||
[OPCODE_X2D] = NVS_OP_X2D,
|
||||
[OPCODE_XPD] = NVS_OP_XPD
|
||||
};
|
||||
|
||||
static nvsCond _tx_mesa_condmask[] = {
|
||||
NVS_COND_UNKNOWN, NVS_COND_GT, NVS_COND_LT, NVS_COND_UN, NVS_COND_GE,
|
||||
NVS_COND_LE, NVS_COND_NE, NVS_COND_NE, NVS_COND_TR, NVS_COND_FL
|
||||
};
|
||||
|
||||
struct pass0_rec {
|
||||
int nvs_ipos;
|
||||
int next_temp;
|
||||
int swzconst_done;
|
||||
int swzconst_id;
|
||||
nvsRegister const_half;
|
||||
};
|
||||
|
||||
#define X NVS_SWZ_X
|
||||
#define Y NVS_SWZ_Y
|
||||
#define Z NVS_SWZ_Z
|
||||
#define W NVS_SWZ_W
|
||||
|
||||
static void
|
||||
pass0_append_fragment(nouveauShader *nvs, nvsFragmentHeader *fragment)
|
||||
{
|
||||
nvsFragmentList *list = calloc(1, sizeof(nvsFragmentList));
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
list->fragment = fragment;
|
||||
list->prev = nvs->list_tail;
|
||||
if ( nvs->list_tail)
|
||||
nvs->list_tail->next = list;
|
||||
if (!nvs->list_head)
|
||||
nvs->list_head = list;
|
||||
nvs->list_tail = list;
|
||||
|
||||
nvs->inst_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
pass0_make_reg(nouveauShader *nvs, nvsRegister *reg,
|
||||
nvsRegFile file, unsigned int index)
|
||||
{
|
||||
struct pass0_rec *rec = nvs->pass_rec;
|
||||
|
||||
/* defaults */
|
||||
*reg = nvr_unused;
|
||||
/* -1 == quick-and-dirty temp alloc */
|
||||
if (file == NVS_FILE_TEMP && index == -1) {
|
||||
index = rec->next_temp++;
|
||||
assert(index < NVS_MAX_TEMPS);
|
||||
}
|
||||
reg->file = file;
|
||||
reg->index = index;
|
||||
}
|
||||
|
||||
static void
|
||||
pass0_make_swizzle(nvsSwzComp *swz, unsigned int mesa)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<4;i++)
|
||||
swz[i] = _tx_mesa_swizzle[GET_SWZ(mesa, i)];
|
||||
}
|
||||
|
||||
static nvsOpcode
|
||||
pass0_make_opcode(enum prog_opcode op)
|
||||
{
|
||||
if (op > MAX_OPCODE)
|
||||
return NVS_OP_UNKNOWN;
|
||||
return _tx_mesa_opcode[op];
|
||||
}
|
||||
|
||||
static nvsCond
|
||||
pass0_make_condmask(GLuint mesa)
|
||||
{
|
||||
if (mesa > COND_FL)
|
||||
return NVS_COND_UNKNOWN;
|
||||
return _tx_mesa_condmask[mesa];
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
pass0_make_mask(GLuint mesa_mask)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (mesa_mask & WRITEMASK_X) mask |= SMASK_X;
|
||||
if (mesa_mask & WRITEMASK_Y) mask |= SMASK_Y;
|
||||
if (mesa_mask & WRITEMASK_Z) mask |= SMASK_Z;
|
||||
if (mesa_mask & WRITEMASK_W) mask |= SMASK_W;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static nvsTexTarget
|
||||
pass0_make_tex_target(GLuint mesa)
|
||||
{
|
||||
switch (mesa) {
|
||||
case TEXTURE_1D_INDEX: return NVS_TEX_TARGET_1D;
|
||||
case TEXTURE_2D_INDEX: return NVS_TEX_TARGET_2D;
|
||||
case TEXTURE_3D_INDEX: return NVS_TEX_TARGET_3D;
|
||||
case TEXTURE_CUBE_INDEX: return NVS_TEX_TARGET_CUBE;
|
||||
case TEXTURE_RECT_INDEX: return NVS_TEX_TARGET_RECT;
|
||||
default:
|
||||
return NVS_TEX_TARGET_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pass0_make_dst_reg(nvsPtr nvs, nvsRegister *reg,
|
||||
struct prog_dst_register *dst)
|
||||
{
|
||||
struct gl_program *mesa = (struct gl_program*)&nvs->mesa.vp;
|
||||
nvsFixedReg sfr;
|
||||
|
||||
switch (dst->File) {
|
||||
case PROGRAM_OUTPUT:
|
||||
if (mesa->Target == GL_VERTEX_PROGRAM_ARB) {
|
||||
sfr = (dst->Index < VERT_RESULT_MAX) ?
|
||||
_tx_mesa_vp_dst_reg[dst->Index] : NVS_FR_UNKNOWN;
|
||||
} else {
|
||||
sfr = (dst->Index < FRAG_RESULT_MAX) ?
|
||||
_tx_mesa_fp_dst_reg[dst->Index] : NVS_FR_UNKNOWN;
|
||||
}
|
||||
pass0_make_reg(nvs, reg, NVS_FILE_RESULT, sfr);
|
||||
break;
|
||||
case PROGRAM_TEMPORARY:
|
||||
pass0_make_reg(nvs, reg, NVS_FILE_TEMP, dst->Index);
|
||||
break;
|
||||
case PROGRAM_ADDRESS:
|
||||
pass0_make_reg(nvs, reg, NVS_FILE_ADDRESS, dst->Index);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown dest file %d\n", dst->File);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src)
|
||||
{
|
||||
struct gl_program *mesa = (struct gl_program *)&nvs->mesa.vp.Base;
|
||||
struct gl_program_parameter_list *p = mesa->Parameters;
|
||||
|
||||
*reg = nvr_unused;
|
||||
|
||||
switch (src->File) {
|
||||
case PROGRAM_INPUT:
|
||||
reg->file = NVS_FILE_ATTRIB;
|
||||
if (mesa->Target == GL_VERTEX_PROGRAM_ARB) {
|
||||
reg->index = (src->Index < VERT_ATTRIB_MAX) ?
|
||||
_tx_mesa_vp_src_reg[src->Index] : NVS_FR_UNKNOWN;
|
||||
} else {
|
||||
reg->index = (src->Index < FRAG_ATTRIB_MAX) ?
|
||||
_tx_mesa_fp_src_reg[src->Index] : NVS_FR_UNKNOWN;
|
||||
}
|
||||
break;
|
||||
/* All const types seem to get shoved into here, not really sure why */
|
||||
case PROGRAM_STATE_VAR:
|
||||
switch (p->Parameters[src->Index].Type) {
|
||||
case PROGRAM_NAMED_PARAM:
|
||||
case PROGRAM_CONSTANT:
|
||||
nvs->params[src->Index].source_val = NULL;
|
||||
COPY_4V(nvs->params[src->Index].val, p->ParameterValues[src->Index]);
|
||||
break;
|
||||
case PROGRAM_STATE_VAR:
|
||||
nvs->params[src->Index].source_val = p->ParameterValues[src->Index];
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown parameter type %d\n",
|
||||
p->Parameters[src->Index].Type);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (src->RelAddr) {
|
||||
reg->indexed = 1;
|
||||
reg->addr_reg = 0;
|
||||
reg->addr_comp = NVS_SWZ_X;
|
||||
} else
|
||||
reg->indexed = 0;
|
||||
reg->file = NVS_FILE_CONST;
|
||||
reg->index = src->Index;
|
||||
break;
|
||||
case PROGRAM_TEMPORARY:
|
||||
reg->file = NVS_FILE_TEMP;
|
||||
reg->index = src->Index;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown source type %d\n", src->File);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* per-component negate handled elsewhere */
|
||||
reg->negate = src->NegateBase != 0;
|
||||
reg->abs = src->Abs;
|
||||
pass0_make_swizzle(reg->swizzle, src->Swizzle);
|
||||
}
|
||||
|
||||
static nvsInstruction *
|
||||
pass0_emit(nouveauShader *nvs, nvsOpcode op, nvsRegister dst,
|
||||
unsigned int mask, int saturate,
|
||||
nvsRegister src0, nvsRegister src1, nvsRegister src2)
|
||||
{
|
||||
struct pass0_rec *rec = nvs->pass_rec;
|
||||
nvsInstruction *sif = NULL;
|
||||
|
||||
/* Seems mesa doesn't explicitly 0 this.. */
|
||||
if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB)
|
||||
saturate = 0;
|
||||
|
||||
sif = calloc(1, sizeof(nvsInstruction));
|
||||
if (sif) {
|
||||
sif->header.type = NVS_INSTRUCTION;
|
||||
sif->header.position = rec->nvs_ipos++;
|
||||
sif->op = op;
|
||||
sif->saturate = saturate;
|
||||
sif->dest = dst;
|
||||
sif->mask = mask;
|
||||
sif->src[0] = src0;
|
||||
sif->src[1] = src1;
|
||||
sif->src[2] = src2;
|
||||
sif->cond = COND_TR;
|
||||
sif->cond_reg = 0;
|
||||
sif->cond_test = 0;
|
||||
sif->cond_update = 0;
|
||||
pass0_make_swizzle(sif->cond_swizzle, SWIZZLE_NOOP);
|
||||
pass0_append_fragment(nvs, (nvsFragmentHeader *)sif);
|
||||
}
|
||||
|
||||
return sif;
|
||||
}
|
||||
|
||||
static void
|
||||
pass0_fixup_swizzle(nvsPtr nvs,
|
||||
struct prog_src_register *src,
|
||||
unsigned int sm1,
|
||||
unsigned int sm2)
|
||||
{
|
||||
static const float sc[4] = { 1.0, 0.0, -1.0, 0.0 };
|
||||
struct pass0_rec *rec = nvs->pass_rec;
|
||||
int fixup_1, fixup_2;
|
||||
nvsRegister sr, dr = nvr_unused;
|
||||
nvsRegister sm1const, sm2const;
|
||||
|
||||
if (!rec->swzconst_done) {
|
||||
struct gl_program *prog = &nvs->mesa.vp.Base;
|
||||
rec->swzconst_id = _mesa_add_unnamed_constant(prog->Parameters, sc, 4);
|
||||
rec->swzconst_done = 1;
|
||||
COPY_4V(nvs->params[rec->swzconst_id].val, sc);
|
||||
}
|
||||
|
||||
fixup_1 = (sm1 != MAKE_SWIZZLE4(0,0,0,0) && sm2 != MAKE_SWIZZLE4(2,2,2,2));
|
||||
fixup_2 = (sm2 != MAKE_SWIZZLE4(2,2,2,2));
|
||||
|
||||
if (src->File != PROGRAM_TEMPORARY && src->File != PROGRAM_INPUT) {
|
||||
/* We can't use more than one const in an instruction, so move the const
|
||||
* into a temp, and swizzle from there.
|
||||
*TODO: should just emit the swizzled const, instead of swizzling it
|
||||
* in the shader.. would need to reswizzle any state params when they
|
||||
* change however..
|
||||
*/
|
||||
pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1);
|
||||
pass0_make_src_reg(nvs, &sr, src);
|
||||
pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused);
|
||||
pass0_make_reg(nvs, &sr, NVS_FILE_TEMP, dr.index);
|
||||
} else {
|
||||
if (fixup_1)
|
||||
src->NegateBase = 0;
|
||||
pass0_make_src_reg(nvs, &sr, src);
|
||||
pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1);
|
||||
}
|
||||
|
||||
pass0_make_reg(nvs, &sm1const, NVS_FILE_CONST, rec->swzconst_id);
|
||||
pass0_make_swizzle(sm1const.swizzle, sm1);
|
||||
if (fixup_1 && fixup_2) {
|
||||
/* Any combination with SWIZZLE_ONE */
|
||||
pass0_make_reg(nvs, &sm2const, NVS_FILE_CONST, rec->swzconst_id);
|
||||
pass0_make_swizzle(sm2const.swizzle, sm2);
|
||||
pass0_emit(nvs, NVS_OP_MAD, dr, SMASK_ALL, 0, sr, sm1const, sm2const);
|
||||
} else {
|
||||
/* SWIZZLE_ZERO || arbitrary negate */
|
||||
pass0_emit(nvs, NVS_OP_MUL, dr, SMASK_ALL, 0, sr, sm1const, nvr_unused);
|
||||
}
|
||||
|
||||
src->File = PROGRAM_TEMPORARY;
|
||||
src->Index = dr.index;
|
||||
src->Swizzle = SWIZZLE_NOOP;
|
||||
}
|
||||
|
||||
#define SET_SWZ(fs, cp, c) fs = (fs & ~(0x7<<(cp*3))) | (c<<(cp*3))
|
||||
static void
|
||||
pass0_check_sources(nvsPtr nvs, struct prog_instruction *inst)
|
||||
{
|
||||
unsigned int insrc = -1, constsrc = -1;
|
||||
int i;
|
||||
|
||||
for (i=0;i<_mesa_num_inst_src_regs(inst->Opcode);i++) {
|
||||
struct prog_src_register *src = &inst->SrcReg[i];
|
||||
unsigned int sm_1 = 0, sm_2 = 0;
|
||||
nvsRegister sr, dr;
|
||||
int do_mov = 0, c;
|
||||
|
||||
/* Build up swizzle masks as if we were going to use
|
||||
* "MAD new, src, const1, const2" to support arbitrary negation
|
||||
* and SWIZZLE_ZERO/SWIZZLE_ONE.
|
||||
*/
|
||||
for (c=0;c<4;c++) {
|
||||
if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ZERO) {
|
||||
SET_SWZ(sm_1, c, SWIZZLE_Y); /* 0.0 */
|
||||
SET_SWZ(sm_2, c, SWIZZLE_Y);
|
||||
SET_SWZ(src->Swizzle, c, SWIZZLE_X);
|
||||
} else if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ONE) {
|
||||
SET_SWZ(sm_1, c, SWIZZLE_Y);
|
||||
if (src->NegateBase & (1<<c))
|
||||
SET_SWZ(sm_2, c, SWIZZLE_Z); /* -1.0 */
|
||||
else
|
||||
SET_SWZ(sm_2, c, SWIZZLE_X); /* 1.0 */
|
||||
SET_SWZ(src->Swizzle, c, SWIZZLE_X);
|
||||
} else {
|
||||
if (src->NegateBase & (1<<c))
|
||||
SET_SWZ(sm_1, c, SWIZZLE_Z); /* -[xyzw] */
|
||||
else
|
||||
SET_SWZ(sm_1, c, SWIZZLE_X); /* [xyzw] */
|
||||
SET_SWZ(sm_2, c, SWIZZLE_Y);
|
||||
}
|
||||
}
|
||||
/* Unless we're multiplying by 1.0 or -1.0 on all components, and we're
|
||||
* adding nothing to any component we have to emulate the swizzle.
|
||||
*/
|
||||
if ((sm_1 != MAKE_SWIZZLE4(0,0,0,0) && sm_1 != MAKE_SWIZZLE4(2,2,2,2)) ||
|
||||
sm_2 != MAKE_SWIZZLE4(1,1,1,1)) {
|
||||
pass0_fixup_swizzle(nvs, src, sm_1, sm_2);
|
||||
/* The source is definitely in a temp now, so don't bother checking
|
||||
* for multiple ATTRIB/CONST regs.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/* HW can't use more than one ATTRIB or PARAM in a single instruction */
|
||||
switch (src->File) {
|
||||
case PROGRAM_INPUT:
|
||||
if (insrc != -1 && insrc != src->Index)
|
||||
do_mov = 1;
|
||||
else insrc = src->Index;
|
||||
break;
|
||||
case PROGRAM_STATE_VAR:
|
||||
if (constsrc != -1 && constsrc != src->Index)
|
||||
do_mov = 1;
|
||||
else constsrc = src->Index;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Emit any extra ATTRIB/CONST to a temp, and modify the Mesa instruction
|
||||
* to point at the temp.
|
||||
*/
|
||||
if (do_mov) {
|
||||
pass0_make_src_reg(nvs, &sr, src);
|
||||
pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1);
|
||||
pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0,
|
||||
sr, nvr_unused, nvr_unused);
|
||||
|
||||
src->File = PROGRAM_TEMPORARY;
|
||||
src->Index = dr.index;
|
||||
src->Swizzle= SWIZZLE_NOOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst)
|
||||
{
|
||||
nvsFunc *shader = nvs->func;
|
||||
nvsRegister src[3], dest, temp;
|
||||
nvsInstruction *nvsinst;
|
||||
struct pass0_rec *rec = nvs->pass_rec;
|
||||
unsigned int mask = pass0_make_mask(inst->DstReg.WriteMask);
|
||||
int i, sat;
|
||||
|
||||
sat = (inst->SaturateMode == SATURATE_ZERO_ONE);
|
||||
|
||||
/* Build all the "real" regs for the instruction */
|
||||
for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++)
|
||||
pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]);
|
||||
if (inst->Opcode != OPCODE_KIL)
|
||||
pass0_make_dst_reg(nvs, &dest, &inst->DstReg);
|
||||
|
||||
switch (inst->Opcode) {
|
||||
case OPCODE_ABS:
|
||||
if (shader->caps & SCAP_SRC_ABS)
|
||||
pass0_emit(nvs, NVS_OP_MOV, dest, mask, sat,
|
||||
nvsAbs(src[0]), nvr_unused, nvr_unused);
|
||||
else
|
||||
pass0_emit(nvs, NVS_OP_MAX, dest, mask, sat,
|
||||
src[0], nvsNegate(src[0]), nvr_unused);
|
||||
break;
|
||||
case OPCODE_KIL:
|
||||
/* This is only in ARB shaders, so we don't have to worry
|
||||
* about clobbering a CC reg as they aren't supported anyway.
|
||||
*/
|
||||
/* MOVC0 temp, src */
|
||||
pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
|
||||
nvsinst = pass0_emit(nvs, NVS_OP_MOV, temp, SMASK_ALL, 0,
|
||||
src[0], nvr_unused, nvr_unused);
|
||||
nvsinst->cond_update = 1;
|
||||
nvsinst->cond_reg = 0;
|
||||
/* KIL_NV (LT0.xyzw) temp */
|
||||
nvsinst = pass0_emit(nvs, NVS_OP_KIL, nvr_unused, 0, 0,
|
||||
nvr_unused, nvr_unused, nvr_unused);
|
||||
nvsinst->cond = COND_LT;
|
||||
nvsinst->cond_reg = 0;
|
||||
nvsinst->cond_test = 1;
|
||||
pass0_make_swizzle(nvsinst->cond_swizzle, MAKE_SWIZZLE4(0,1,2,3));
|
||||
break;
|
||||
case OPCODE_LIT:
|
||||
break;
|
||||
case OPCODE_LRP:
|
||||
pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
|
||||
pass0_emit(nvs, NVS_OP_MAD, temp, mask, 0,
|
||||
nvsNegate(src[0]), src[2], src[2]);
|
||||
pass0_emit(nvs, NVS_OP_MAD, dest, mask, sat,
|
||||
src[0], src[1], temp);
|
||||
break;
|
||||
case OPCODE_POW:
|
||||
if (shader->SupportsOpcode(shader, NVS_OP_LG2) &&
|
||||
shader->SupportsOpcode(shader, NVS_OP_EX2)) {
|
||||
pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
|
||||
/* LG2 temp.x, src0.c */
|
||||
pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0,
|
||||
nvsSwizzle(src[0], X, X, X, X),
|
||||
nvr_unused,
|
||||
nvr_unused);
|
||||
/* MUL temp.x, temp.x, src1.c */
|
||||
pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0,
|
||||
nvsSwizzle(temp, X, X, X, X),
|
||||
nvsSwizzle(src[1], X, X, X, X),
|
||||
nvr_unused);
|
||||
/* EX2 dest, temp.x */
|
||||
pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat,
|
||||
nvsSwizzle(temp, X, X, X, X),
|
||||
nvr_unused,
|
||||
nvr_unused);
|
||||
} else {
|
||||
/* can we use EXP/LOG instead of EX2/LG2?? */
|
||||
fprintf(stderr, "Implement POW for NV20 vtxprog!\n");
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
case OPCODE_RSQ:
|
||||
if (rec->const_half.file != NVS_FILE_CONST) {
|
||||
GLfloat const_half[4] = { 0.5, 0.0, 0.0, 0.0 };
|
||||
pass0_make_reg(nvs, &rec->const_half, NVS_FILE_CONST,
|
||||
_mesa_add_unnamed_constant(nvs->mesa.vp.Base.Parameters,
|
||||
const_half, 4));
|
||||
COPY_4V(nvs->params[rec->const_half.index].val, const_half);
|
||||
}
|
||||
pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
|
||||
pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0,
|
||||
nvsAbs(nvsSwizzle(src[0], X, X, X, X)),
|
||||
nvr_unused,
|
||||
nvr_unused);
|
||||
pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0,
|
||||
nvsSwizzle(temp, X, X, X, X),
|
||||
nvsNegate(rec->const_half),
|
||||
nvr_unused);
|
||||
pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat,
|
||||
nvsSwizzle(temp, X, X, X, X),
|
||||
nvr_unused,
|
||||
nvr_unused);
|
||||
break;
|
||||
case OPCODE_SCS:
|
||||
if (mask & SMASK_X)
|
||||
pass0_emit(nvs, NVS_OP_COS, dest, SMASK_X, sat,
|
||||
nvsSwizzle(src[0], X, X, X, X),
|
||||
nvr_unused,
|
||||
nvr_unused);
|
||||
if (mask & SMASK_Y)
|
||||
pass0_emit(nvs, NVS_OP_SIN, dest, SMASK_Y, sat,
|
||||
nvsSwizzle(src[0], X, X, X, X),
|
||||
nvr_unused,
|
||||
nvr_unused);
|
||||
break;
|
||||
case OPCODE_SUB:
|
||||
pass0_emit(nvs, NVS_OP_ADD, dest, mask, sat,
|
||||
src[0], nvsNegate(src[1]), nvr_unused);
|
||||
break;
|
||||
case OPCODE_XPD:
|
||||
pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
|
||||
pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_ALL, 0,
|
||||
nvsSwizzle(src[0], Z, X, Y, Y),
|
||||
nvsSwizzle(src[1], Y, Z, X, X),
|
||||
nvr_unused);
|
||||
pass0_emit(nvs, NVS_OP_MAD, dest, (mask & ~SMASK_W), sat,
|
||||
nvsSwizzle(src[0], Y, Z, X, X),
|
||||
nvsSwizzle(src[1], Z, X, Y, Y),
|
||||
nvsNegate(temp));
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "hw doesn't support opcode \"%s\", and no emulation found\n",
|
||||
_mesa_opcode_string(inst->Opcode));
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
pass0_translate_instructions(nouveauShader *nvs)
|
||||
{
|
||||
struct gl_program *prog = (struct gl_program *)&nvs->mesa.vp;
|
||||
nvsFunc *shader = nvs->func;
|
||||
int ipos;
|
||||
|
||||
for (ipos=0; ipos<prog->NumInstructions; ipos++) {
|
||||
struct prog_instruction *inst = &prog->Instructions[ipos];
|
||||
|
||||
if (inst->Opcode == OPCODE_END)
|
||||
break;
|
||||
|
||||
/* Deal with multiple ATTRIB/PARAM in a single instruction */
|
||||
pass0_check_sources(nvs, inst);
|
||||
|
||||
/* Now it's safe to do the prog_instruction->nvsInstruction conversion */
|
||||
if (shader->SupportsOpcode(shader, pass0_make_opcode(inst->Opcode))) {
|
||||
nvsInstruction *nvsinst;
|
||||
nvsRegister src[3], dest;
|
||||
int i;
|
||||
|
||||
for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++)
|
||||
pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]);
|
||||
pass0_make_dst_reg(nvs, &dest, &inst->DstReg);
|
||||
|
||||
nvsinst = pass0_emit(nvs,
|
||||
pass0_make_opcode(inst->Opcode),
|
||||
dest,
|
||||
pass0_make_mask(inst->DstReg.WriteMask),
|
||||
(inst->SaturateMode != SATURATE_OFF),
|
||||
src[0], src[1], src[2]);
|
||||
nvsinst->tex_unit = inst->TexSrcUnit;
|
||||
nvsinst->tex_target = pass0_make_tex_target(inst->TexSrcTarget);
|
||||
/* TODO when NV_fp/vp is implemented */
|
||||
nvsinst->cond = COND_TR;
|
||||
} else {
|
||||
if (!pass0_emulate_instruction(nvs, inst))
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
GLboolean
|
||||
nouveau_shader_pass0_arb(GLcontext *ctx, nouveauShader *nvs)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
struct gl_program *prog = (struct gl_program*)nvs;
|
||||
struct gl_vertex_program *vp = (struct gl_vertex_program *)prog;
|
||||
struct gl_fragment_program *fp = (struct gl_fragment_program *)prog;
|
||||
struct pass0_rec *rec;
|
||||
int ret;
|
||||
|
||||
switch (prog->Target) {
|
||||
case GL_VERTEX_PROGRAM_ARB:
|
||||
nvs->func = &nmesa->VPfunc;
|
||||
if (vp->IsPositionInvariant)
|
||||
_mesa_insert_mvp_code(ctx, vp);
|
||||
#if 0
|
||||
if (IS_FIXEDFUNCTION_PROG && CLIP_PLANES_USED)
|
||||
pass0_insert_ff_clip_planes();
|
||||
#endif
|
||||
break;
|
||||
case GL_FRAGMENT_PROGRAM_ARB:
|
||||
nvs->func = &nmesa->FPfunc;
|
||||
if (fp->FogOption != GL_NONE)
|
||||
_mesa_append_fog_code(ctx, fp);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown program type %d", prog->Target);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
rec = calloc(1, sizeof(struct pass0_rec));
|
||||
rec->next_temp = prog->NumTemporaries;
|
||||
nvs->pass_rec = rec;
|
||||
|
||||
ret = pass0_translate_instructions(nvs);
|
||||
if (!ret) {
|
||||
/* DESTROY list */
|
||||
}
|
||||
|
||||
free(nvs->pass_rec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
318
src/mesa/drivers/dri/nouveau/nouveau_shader_1.c
Normal file
318
src/mesa/drivers/dri/nouveau/nouveau_shader_1.c
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Ben Skeggs.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Ben Skeggs <darktama@iinet.net.au>
|
||||
*/
|
||||
|
||||
#include "glheader.h"
|
||||
#include "macros.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "nouveau_shader.h"
|
||||
|
||||
#define PASS1_OK 0
|
||||
#define PASS1_KILL 1
|
||||
#define PASS1_FAIL 2
|
||||
|
||||
struct pass1_rec {
|
||||
unsigned int temp[NVS_MAX_TEMPS];
|
||||
unsigned int result[NVS_MAX_ATTRIBS];
|
||||
unsigned int address[NVS_MAX_ADDRESS];
|
||||
unsigned int cc[2];
|
||||
};
|
||||
|
||||
static void
|
||||
pass1_remove_fragment(nvsPtr nvs, nvsFragmentList *item)
|
||||
{
|
||||
if (item->prev) item->prev->next = item->next;
|
||||
if (item->next) item->next->prev = item->prev;
|
||||
if (nvs->list_head == item) nvs->list_head = item->next;
|
||||
if (nvs->list_tail == item) nvs->list_tail = item->prev;
|
||||
|
||||
nvs->inst_count--;
|
||||
}
|
||||
|
||||
static int
|
||||
pass1_result_needed(struct pass1_rec *rec, nvsInstruction *inst)
|
||||
{
|
||||
if (inst->cond_update && rec->cc[inst->cond_reg])
|
||||
return 1;
|
||||
/* Only write components that are read later */
|
||||
if (inst->dest.file == NVS_FILE_TEMP)
|
||||
return (inst->mask & rec->temp[inst->dest.index]);
|
||||
if (inst->dest.file == NVS_FILE_ADDRESS)
|
||||
return (inst->mask & rec->address[inst->dest.index]);
|
||||
/* No point writing result components that are written later */
|
||||
if (inst->dest.file == NVS_FILE_RESULT)
|
||||
return (inst->mask & ~rec->result[inst->dest.index]);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static void
|
||||
pass1_track_result(struct pass1_rec *rec, nvsInstruction *inst)
|
||||
{
|
||||
if (inst->cond_test)
|
||||
rec->cc[inst->cond_reg] = 1;
|
||||
if (inst->dest.file == NVS_FILE_TEMP) {
|
||||
inst->mask &= rec->temp[inst->dest.index];
|
||||
} else if (inst->dest.file == NVS_FILE_RESULT) {
|
||||
inst->mask &= ~rec->result[inst->dest.index];
|
||||
rec->result[inst->dest.index] |= inst->mask;
|
||||
} else if (inst->dest.file == NVS_FILE_ADDRESS) {
|
||||
inst->mask &= rec->address[inst->dest.index];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pass1_track_source(nouveauShader *nvs, nvsInstruction *inst, int pos,
|
||||
unsigned int read)
|
||||
{
|
||||
struct pass1_rec *rec = nvs->pass_rec;
|
||||
nvsRegister *src = &inst->src[pos];
|
||||
unsigned int really_read = 0;
|
||||
int i,sc;
|
||||
|
||||
/* Account for swizzling */
|
||||
for (i=0; i<4; i++)
|
||||
if (read & (1<<i)) really_read |= (1 << src->swizzle[i]);
|
||||
|
||||
/* Track register reads */
|
||||
if (src->file == NVS_FILE_TEMP) {
|
||||
if (nvs->temps[src->index].last_use == -1)
|
||||
nvs->temps[src->index].last_use = inst->header.position;
|
||||
rec->temp [src->index] |= really_read;
|
||||
} else if (src->indexed) {
|
||||
rec->address[src->addr_reg] |= (1<<src->addr_comp);
|
||||
}
|
||||
|
||||
/* Modify swizzle to only access read components */
|
||||
/* Find a component that is used.. */
|
||||
for (sc=0;sc<4;sc++)
|
||||
if (really_read & (1<<sc))
|
||||
break;
|
||||
/* Now set all unused components to that value */
|
||||
for (i=0;i<4;i++)
|
||||
if (!(read & (1<<i))) src->swizzle[i] = sc;
|
||||
}
|
||||
|
||||
static int
|
||||
pass1_check_instruction(nouveauShader *nvs, nvsInstruction *inst)
|
||||
{
|
||||
struct pass1_rec *rec = nvs->pass_rec;
|
||||
unsigned int read0, read1, read2;
|
||||
|
||||
if (inst->op != NVS_OP_KIL) {
|
||||
if (!pass1_result_needed(rec, inst))
|
||||
return PASS1_KILL;
|
||||
}
|
||||
pass1_track_result(rec, inst);
|
||||
|
||||
read0 = read1 = read2 = 0;
|
||||
|
||||
switch (inst->op) {
|
||||
case NVS_OP_FLR:
|
||||
case NVS_OP_FRC:
|
||||
case NVS_OP_MOV:
|
||||
case NVS_OP_SSG:
|
||||
case NVS_OP_ARL:
|
||||
read0 = inst->mask;
|
||||
break;
|
||||
case NVS_OP_ADD:
|
||||
case NVS_OP_MAX:
|
||||
case NVS_OP_MIN:
|
||||
case NVS_OP_MUL:
|
||||
case NVS_OP_SEQ:
|
||||
case NVS_OP_SFL:
|
||||
case NVS_OP_SGE:
|
||||
case NVS_OP_SGT:
|
||||
case NVS_OP_SLE:
|
||||
case NVS_OP_SLT:
|
||||
case NVS_OP_SNE:
|
||||
case NVS_OP_STR:
|
||||
case NVS_OP_SUB:
|
||||
read0 = inst->mask;
|
||||
read1 = inst->mask;
|
||||
break;
|
||||
case NVS_OP_CMP:
|
||||
case NVS_OP_LRP:
|
||||
case NVS_OP_MAD:
|
||||
read0 = inst->mask;
|
||||
read1 = inst->mask;
|
||||
read2 = inst->mask;
|
||||
break;
|
||||
case NVS_OP_XPD:
|
||||
if (inst->mask & SMASK_X) read0 |= SMASK_Y|SMASK_Z;
|
||||
if (inst->mask & SMASK_Y) read0 |= SMASK_X|SMASK_Z;
|
||||
if (inst->mask & SMASK_Z) read0 |= SMASK_X|SMASK_Y;
|
||||
read1 = read0;
|
||||
break;
|
||||
case NVS_OP_COS:
|
||||
case NVS_OP_EX2:
|
||||
case NVS_OP_EXP:
|
||||
case NVS_OP_LG2:
|
||||
case NVS_OP_LOG:
|
||||
case NVS_OP_RCC:
|
||||
case NVS_OP_RCP:
|
||||
case NVS_OP_RSQ:
|
||||
case NVS_OP_SCS:
|
||||
case NVS_OP_SIN:
|
||||
read0 = SMASK_X;
|
||||
break;
|
||||
case NVS_OP_POW:
|
||||
read0 = SMASK_X;
|
||||
read1 = SMASK_X;
|
||||
break;
|
||||
case NVS_OP_DIV:
|
||||
read0 = inst->mask;
|
||||
read1 = SMASK_X;
|
||||
break;
|
||||
case NVS_OP_DP2:
|
||||
read0 = SMASK_X|SMASK_Y;
|
||||
read1 = SMASK_X|SMASK_Y;
|
||||
break;
|
||||
case NVS_OP_DP3:
|
||||
case NVS_OP_RFL:
|
||||
read0 = SMASK_X|SMASK_Y|SMASK_Z;
|
||||
read1 = SMASK_X|SMASK_Y|SMASK_Z;
|
||||
break;
|
||||
case NVS_OP_DP4:
|
||||
read0 = SMASK_ALL;
|
||||
read1 = SMASK_ALL;
|
||||
break;
|
||||
case NVS_OP_DPH:
|
||||
read0 = SMASK_X|SMASK_Y|SMASK_Z;
|
||||
read1 = SMASK_ALL;
|
||||
break;
|
||||
case NVS_OP_DST:
|
||||
if (inst->mask & SMASK_Y) read0 = read1 = SMASK_Y;
|
||||
if (inst->mask & SMASK_Z) read0 |= SMASK_Z;
|
||||
if (inst->mask & SMASK_W) read1 |= SMASK_W;
|
||||
break;
|
||||
case NVS_OP_NRM:
|
||||
read0 = SMASK_X|SMASK_Y|SMASK_Z;
|
||||
break;
|
||||
case NVS_OP_PK2H:
|
||||
case NVS_OP_PK2US:
|
||||
read0 = SMASK_X|SMASK_Y;
|
||||
break;
|
||||
case NVS_OP_DDX:
|
||||
case NVS_OP_DDY:
|
||||
case NVS_OP_UP2H:
|
||||
case NVS_OP_UP2US:
|
||||
case NVS_OP_PK4B:
|
||||
case NVS_OP_PK4UB:
|
||||
case NVS_OP_UP4B:
|
||||
case NVS_OP_UP4UB:
|
||||
read0 = SMASK_ALL;
|
||||
break;
|
||||
case NVS_OP_X2D:
|
||||
read1 = SMASK_X|SMASK_Y;
|
||||
if (inst->mask & (SMASK_X|SMASK_Z)) {
|
||||
read0 |= SMASK_X;
|
||||
read2 |= SMASK_X|SMASK_Y;
|
||||
}
|
||||
if (inst->mask & (SMASK_Y|SMASK_W)) {
|
||||
read0 |= SMASK_Y;
|
||||
read2 |= SMASK_Z|SMASK_W;
|
||||
}
|
||||
break;
|
||||
case NVS_OP_LIT:
|
||||
read0 |= SMASK_X|SMASK_Y|SMASK_W;
|
||||
break;
|
||||
case NVS_OP_TEX:
|
||||
case NVS_OP_TXP:
|
||||
case NVS_OP_TXL:
|
||||
case NVS_OP_TXB:
|
||||
read0 = SMASK_ALL;
|
||||
break;
|
||||
case NVS_OP_TXD:
|
||||
read0 = SMASK_ALL;
|
||||
read1 = SMASK_ALL;
|
||||
read2 = SMASK_ALL;
|
||||
break;
|
||||
case NVS_OP_KIL:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown sop=%d", inst->op);
|
||||
return PASS1_FAIL;
|
||||
}
|
||||
|
||||
/* Any values that are written by this inst can't have been read further up */
|
||||
if (inst->dest.file == NVS_FILE_TEMP)
|
||||
rec->temp[inst->dest.index] &= ~inst->mask;
|
||||
|
||||
if (read0) pass1_track_source(nvs, inst, 0, read0);
|
||||
if (read1) pass1_track_source(nvs, inst, 1, read1);
|
||||
if (read2) pass1_track_source(nvs, inst, 2, read2);
|
||||
|
||||
return PASS1_OK;
|
||||
}
|
||||
|
||||
/* Some basic dead code elimination
|
||||
* - Remove unused instructions
|
||||
* - Don't write unused register components
|
||||
* - Modify swizzles to not reference unneeded components.
|
||||
*/
|
||||
GLboolean
|
||||
nouveau_shader_pass1(nvsPtr nvs)
|
||||
{
|
||||
nvsFragmentList *list = nvs->list_tail;
|
||||
int i;
|
||||
|
||||
for (i=0; i<NVS_MAX_TEMPS; i++)
|
||||
nvs->temps[i].last_use = -1;
|
||||
|
||||
nvs->pass_rec = calloc(1, sizeof(struct pass1_rec));
|
||||
|
||||
while (list) {
|
||||
assert(list->fragment->type == NVS_INSTRUCTION);
|
||||
|
||||
switch(pass1_check_instruction(nvs, (nvsInstruction *)list->fragment)) {
|
||||
case PASS1_OK:
|
||||
break;
|
||||
case PASS1_KILL:
|
||||
pass1_remove_fragment(nvs, list);
|
||||
break;
|
||||
case PASS1_FAIL:
|
||||
default:
|
||||
free(nvs->pass_rec);
|
||||
nvs->pass_rec = NULL;
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
list = list->prev;
|
||||
}
|
||||
|
||||
free(nvs->pass_rec);
|
||||
nvs->pass_rec = NULL;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
240
src/mesa/drivers/dri/nouveau/nouveau_shader_2.c
Normal file
240
src/mesa/drivers/dri/nouveau/nouveau_shader_2.c
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Ben Skeggs.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Ben Skeggs <darktama@iinet.net.au>
|
||||
*/
|
||||
|
||||
#include "glheader.h"
|
||||
#include "macros.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "program.h"
|
||||
|
||||
#include "nouveau_shader.h"
|
||||
|
||||
struct pass2_rec {
|
||||
/* Map nvsRegister temp ID onto hw temp ID */
|
||||
unsigned int temps[NVS_MAX_TEMPS];
|
||||
/* Track free hw registers */
|
||||
unsigned int hw_temps[NVS_MAX_TEMPS];
|
||||
};
|
||||
|
||||
static int
|
||||
pass2_alloc_hw_temp(nvsPtr nvs)
|
||||
{
|
||||
struct pass2_rec *rec = nvs->pass_rec;
|
||||
int i;
|
||||
|
||||
for (i=0; i<nvs->func->MaxTemp; i++) {
|
||||
/* This is a *horrible* hack.. R0 is both temp0 and result.color
|
||||
* in NV30/40 fragprogs, we can use R0 as a temp before result is
|
||||
* written however..
|
||||
*/
|
||||
if (nvs->mesa.vp.Base.Target == GL_FRAGMENT_PROGRAM_ARB && i==0)
|
||||
continue;
|
||||
|
||||
if (rec->hw_temps[i] == 0) {
|
||||
rec->hw_temps[i] = 1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
pass2_free_hw_temp(nvsPtr nvs, int reg)
|
||||
{
|
||||
struct pass2_rec *rec = nvs->pass_rec;
|
||||
rec->hw_temps[reg] = 0;
|
||||
}
|
||||
|
||||
static nvsRegister
|
||||
pass2_mangle_reg(nvsPtr nvs, nvsInstruction *inst, nvsRegister reg)
|
||||
{
|
||||
struct pass2_rec *rec = nvs->pass_rec;
|
||||
|
||||
if (reg.file == NVS_FILE_TEMP) {
|
||||
int hwidx;
|
||||
|
||||
if (rec->temps[reg.index] == -1)
|
||||
rec->temps[reg.index] = pass2_alloc_hw_temp(nvs);
|
||||
hwidx = rec->temps[reg.index];
|
||||
|
||||
if (nvs->temps[reg.index].last_use <= inst->header.position)
|
||||
pass2_free_hw_temp(nvs, hwidx);
|
||||
|
||||
reg.index = hwidx;
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
static void
|
||||
pass2_add_instruction(nvsPtr nvs, nvsInstruction *inst,
|
||||
struct _op_xlat *op, int slot)
|
||||
{
|
||||
nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
|
||||
nvsFunc *shader = nvs->func;
|
||||
nvsRegister reg;
|
||||
int i;
|
||||
|
||||
shader->SetOpcode(shader, op->NV, slot);
|
||||
if (inst->saturate ) shader->SetSaturate(shader);
|
||||
if (inst->cond_update) shader->SetCCUpdate(shader);
|
||||
if (inst->cond_test ) shader->SetCondition(shader, 1, inst->cond,
|
||||
inst->cond_reg,
|
||||
inst->cond_swizzle);
|
||||
else shader->SetCondition(shader, 0, NVS_COND_TR,
|
||||
0,
|
||||
default_swz);
|
||||
switch (inst->op) {
|
||||
case NVS_OP_TEX:
|
||||
case NVS_OP_TXB:
|
||||
case NVS_OP_TXL:
|
||||
case NVS_OP_TXP:
|
||||
case NVS_OP_TXD:
|
||||
shader->SetTexImageUnit(shader, inst->tex_unit);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (op->srcpos[i] != -1) {
|
||||
reg = pass2_mangle_reg(nvs, inst, inst->src[i]);
|
||||
if (reg.file == NVS_FILE_ATTRIB)
|
||||
nvs->inputs_read |= (1 << reg.index);
|
||||
shader->SetSource(shader, ®, op->srcpos[i]);
|
||||
if (reg.file == NVS_FILE_CONST && shader->GetSourceConstVal) {
|
||||
int idx_slot = nvs->params[reg.index].hw_index_cnt++;
|
||||
nvs->params[reg.index].hw_index = realloc(
|
||||
nvs->params[reg.index].hw_index, sizeof(int) * idx_slot+1);
|
||||
nvs->params[reg.index].hw_index[idx_slot] = nvs->program_current + 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reg = pass2_mangle_reg(nvs, inst, inst->dest);
|
||||
if (reg.file == NVS_FILE_RESULT)
|
||||
nvs->outputs_written |= (1 << reg.index);
|
||||
shader->SetResult(shader, ®, inst->mask, slot);
|
||||
}
|
||||
|
||||
static int
|
||||
pass2_assemble_instruction(nvsPtr nvs, nvsInstruction *inst, int last)
|
||||
{
|
||||
nvsFunc *shader = nvs->func;
|
||||
struct _op_xlat *op;
|
||||
unsigned int hw_inst[8];
|
||||
int slot;
|
||||
int instsz;
|
||||
int i;
|
||||
|
||||
shader->inst = hw_inst;
|
||||
|
||||
/* Assemble this instruction */
|
||||
if (!(op = shader->GetOPTXFromSOP(inst->op, &slot)))
|
||||
return 0;
|
||||
shader->InitInstruction(shader);
|
||||
pass2_add_instruction(nvs, inst, op, slot);
|
||||
if (last)
|
||||
shader->SetLastInst(shader);
|
||||
|
||||
instsz = shader->GetOffsetNext(nvs->func);
|
||||
if (nvs->program_size + instsz >= nvs->program_alloc_size) {
|
||||
nvs->program_alloc_size *= 2;
|
||||
nvs->program = realloc(nvs->program,
|
||||
nvs->program_alloc_size * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
for (i=0; i<instsz; i++)
|
||||
nvs->program[nvs->program_current++] = hw_inst[i];
|
||||
nvs->program_size = nvs->program_current;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Translate program into hardware format */
|
||||
GLboolean
|
||||
nouveau_shader_pass2(nvsPtr nvs)
|
||||
{
|
||||
nvsFragmentList *list = nvs->list_head;
|
||||
struct pass2_rec *rec;
|
||||
int i;
|
||||
|
||||
rec = calloc(1, sizeof(struct pass2_rec));
|
||||
for (i=0; i<NVS_MAX_TEMPS; i++)
|
||||
rec->temps[i] = -1;
|
||||
nvs->pass_rec = rec;
|
||||
|
||||
/* Start off with allocating 4 uint32_t's for each inst, will be grown
|
||||
* if necessary..
|
||||
*/
|
||||
nvs->program_alloc_size = nvs->inst_count * 4;
|
||||
nvs->program = calloc(nvs->program_alloc_size, sizeof(uint32_t));
|
||||
nvs->program_size = 0;
|
||||
nvs->program_current = 0;
|
||||
|
||||
while (list) {
|
||||
assert(list->fragment->type == NVS_INSTRUCTION);
|
||||
|
||||
if (!pass2_assemble_instruction(nvs, (nvsInstruction *)list->fragment, list->next ? 0 : 1)) {
|
||||
free(nvs->program);
|
||||
nvs->program = NULL;
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
/* Shrink allocated memory to only what we need */
|
||||
nvs->program = realloc(nvs->program, nvs->program_size * sizeof(uint32_t));
|
||||
nvs->program_alloc_size = nvs->program_size;
|
||||
|
||||
nvs->translated = 1;
|
||||
nvs->on_hardware = 0;
|
||||
|
||||
#if 1
|
||||
fflush(stdout); fflush(stderr);
|
||||
fprintf(stderr, "----------------MESA PROGRAM\n");
|
||||
fflush(stdout); fflush(stderr);
|
||||
_mesa_print_program(&nvs->mesa.vp.Base);
|
||||
fflush(stdout); fflush(stderr);
|
||||
fprintf(stderr, "^^^^^^^^^^^^^^^^MESA PROGRAM\n");
|
||||
fflush(stdout); fflush(stderr);
|
||||
fprintf(stderr, "----------------NV40 PROGRAM\n");
|
||||
fflush(stdout); fflush(stderr);
|
||||
nvsDisasmHWShader(nvs);
|
||||
fflush(stdout); fflush(stderr);
|
||||
fprintf(stderr, "^^^^^^^^^^^^^^^^NV40 PROGRAM\n");
|
||||
fflush(stdout); fflush(stderr);
|
||||
#endif
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
118
src/mesa/drivers/dri/nouveau/nouveau_span.c
Normal file
118
src/mesa/drivers/dri/nouveau/nouveau_span.c
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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_context.h"
|
||||
#include "nouveau_span.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_lock.h"
|
||||
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
#define HAVE_HW_DEPTH_SPANS 0
|
||||
#define HAVE_HW_DEPTH_PIXELS 0
|
||||
#define HAVE_HW_STENCIL_SPANS 0
|
||||
#define HAVE_HW_STENCIL_PIXELS 0
|
||||
|
||||
#define LOCAL_VARS \
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); \
|
||||
__DRIscreenPrivate *sPriv = nmesa->driScreen; \
|
||||
__DRIdrawablePrivate *dPriv = nmesa->driDrawable; \
|
||||
driRenderbuffer *drb = (driRenderbuffer *) rb; \
|
||||
GLuint height = dPriv->h; \
|
||||
GLuint p; \
|
||||
(void) p;
|
||||
|
||||
#define Y_FLIP( _y ) (height - _y - 1)
|
||||
|
||||
#define HW_LOCK()
|
||||
|
||||
#define HW_UNLOCK()
|
||||
|
||||
|
||||
|
||||
/* ================================================================
|
||||
* Color buffers
|
||||
*/
|
||||
|
||||
/* RGB565 */
|
||||
#define SPANTMP_PIXEL_FMT GL_RGB
|
||||
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
|
||||
|
||||
#define TAG(x) nouveau##x##_RGB565
|
||||
#define TAG2(x,y) nouveau##x##_RGB565##y
|
||||
#define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
|
||||
+ ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
|
||||
#include "spantmp2.h"
|
||||
|
||||
|
||||
/* ARGB8888 */
|
||||
#define SPANTMP_PIXEL_FMT GL_BGRA
|
||||
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
|
||||
#define TAG(x) nouveau##x##_ARGB8888
|
||||
#define TAG2(x,y) nouveau##x##_ARGB8888##y
|
||||
#define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
|
||||
+ ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
|
||||
#include "spantmp2.h"
|
||||
|
||||
static void
|
||||
nouveauSpanRenderStart( GLcontext *ctx )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
FIRE_RING();
|
||||
LOCK_HARDWARE(nmesa);
|
||||
nouveauWaitForIdleLocked( nmesa );
|
||||
}
|
||||
|
||||
static void
|
||||
nouveauSpanRenderFinish( GLcontext *ctx )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
_swrast_flush( ctx );
|
||||
nouveauWaitForIdleLocked( nmesa );
|
||||
UNLOCK_HARDWARE( nmesa );
|
||||
}
|
||||
|
||||
void nouveauSpanInitFunctions( GLcontext *ctx )
|
||||
{
|
||||
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
|
||||
swdd->SpanRenderStart = nouveauSpanRenderStart;
|
||||
swdd->SpanRenderFinish = nouveauSpanRenderFinish;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Plug in the Get/Put routines for the given driRenderbuffer.
|
||||
*/
|
||||
void
|
||||
nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis)
|
||||
{
|
||||
if (nrb->mesa._ActualFormat == GL_RGBA8)
|
||||
nouveauInitPointers_ARGB8888(&nrb->mesa);
|
||||
else if (nrb->mesa._ActualFormat == GL_RGB5)
|
||||
nouveauInitPointers_RGB565(&nrb->mesa);
|
||||
}
|
||||
39
src/mesa/drivers/dri/nouveau/nouveau_span.h
Normal file
39
src/mesa/drivers/dri/nouveau/nouveau_span.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_SPAN_H__
|
||||
#define __NOUVEAU_SPAN_H__
|
||||
|
||||
#include "drirenderbuffer.h"
|
||||
#include "nouveau_buffers.h"
|
||||
|
||||
extern void nouveauSpanInitFunctions( GLcontext *ctx );
|
||||
extern void nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis);
|
||||
|
||||
#endif /* __NOUVEAU_SPAN_H__ */
|
||||
|
||||
355
src/mesa/drivers/dri/nouveau/nouveau_state.c
Normal file
355
src/mesa/drivers/dri/nouveau/nouveau_state.c
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Jeremy Kolb
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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_context.h"
|
||||
#include "nouveau_state.h"
|
||||
#include "nouveau_swtcl.h"
|
||||
#include "nouveau_fifo.h"
|
||||
|
||||
#include "swrast/swrast.h"
|
||||
#include "array_cache/acache.h"
|
||||
#include "tnl/tnl.h"
|
||||
#include "swrast_setup/swrast_setup.h"
|
||||
|
||||
#include "tnl/t_pipeline.h"
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "colormac.h"
|
||||
|
||||
static __inline__ GLuint nouveauPackColor(GLuint format,
|
||||
GLubyte r, GLubyte g,
|
||||
GLubyte b, GLubyte a)
|
||||
{
|
||||
switch (format) {
|
||||
case 2:
|
||||
return PACK_COLOR_565( r, g, b );
|
||||
case 4:
|
||||
return PACK_COLOR_8888( r, g, b, a);
|
||||
default:
|
||||
fprintf(stderr, "unknown format %d\n", (int)format);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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] + xoffset + SUBPIXEL_X;
|
||||
m[MAT_SY] = - v[MAT_SY];
|
||||
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)
|
||||
{
|
||||
/*
|
||||
* Need to send (at least on an nv35 the following:
|
||||
* cons = 4 (this may be bytes per pixel)
|
||||
*
|
||||
* The viewport:
|
||||
* 445 0x0000bee0 {size: 0x0 channel: 0x1 cmd: 0x00009ee0} <-- VIEWPORT_SETUP/HEADER ?
|
||||
* 446 0x00000000 {size: 0x0 channel: 0x0 cmd: 0x00000000} <-- x * cons
|
||||
* 447 0x00000c80 {size: 0x0 channel: 0x0 cmd: 0x00000c80} <-- (height + x) * cons
|
||||
* 448 0x00000000 {size: 0x0 channel: 0x0 cmd: 0x00000000} <-- y * cons
|
||||
* 449 0x00000960 {size: 0x0 channel: 0x0 cmd: 0x00000960} <-- (width + y) * cons
|
||||
* 44a 0x00082a00 {size: 0x2 channel: 0x1 cmd: 0x00000a00} <-- VIEWPORT_DIMS
|
||||
* 44b 0x04000000 <-- (Width_from_glViewport << 16) | x
|
||||
* 44c 0x03000000 <-- (Height_from_glViewport << 16) | (win_height - height - y)
|
||||
*
|
||||
*/
|
||||
|
||||
nouveauCalcViewport(ctx);
|
||||
}
|
||||
|
||||
static void nouveauDepthRange(GLcontext *ctx, GLclampd near, GLclampd far)
|
||||
{
|
||||
nouveauCalcViewport(ctx);
|
||||
}
|
||||
|
||||
static void nouveauDDUpdateHWState(GLcontext *ctx)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
int new_state = nmesa->new_state;
|
||||
|
||||
if ( new_state || nmesa->new_render_state & _NEW_TEXTURE )
|
||||
{
|
||||
nmesa->new_state = 0;
|
||||
|
||||
/* Update the various parts of the context's state.
|
||||
*/
|
||||
/*
|
||||
if ( new_state & NOUVEAU_NEW_ALPHA )
|
||||
nouveauUpdateAlphaMode( ctx );
|
||||
|
||||
if ( new_state & NOUVEAU_NEW_DEPTH )
|
||||
nouveauUpdateZMode( ctx );
|
||||
|
||||
if ( new_state & NOUVEAU_NEW_FOG )
|
||||
nouveauUpdateFogAttrib( ctx );
|
||||
|
||||
if ( new_state & NOUVEAU_NEW_CLIP )
|
||||
nouveauUpdateClipping( ctx );
|
||||
|
||||
if ( new_state & NOUVEAU_NEW_CULL )
|
||||
nouveauUpdateCull( ctx );
|
||||
|
||||
if ( new_state & NOUVEAU_NEW_MASKS )
|
||||
nouveauUpdateMasks( ctx );
|
||||
|
||||
if ( new_state & NOUVEAU_NEW_WINDOW )
|
||||
nouveauUpdateWindow( ctx );
|
||||
|
||||
if ( nmesa->new_render_state & _NEW_TEXTURE ) {
|
||||
nouveauUpdateTextureState( ctx );
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
static void nouveauDDInvalidateState(GLcontext *ctx, GLuint new_state)
|
||||
{
|
||||
_swrast_InvalidateState( ctx, new_state );
|
||||
_swsetup_InvalidateState( ctx, new_state );
|
||||
_ac_InvalidateState( ctx, new_state );
|
||||
_tnl_InvalidateState( ctx, new_state );
|
||||
NOUVEAU_CONTEXT(ctx)->new_render_state |= new_state;
|
||||
}
|
||||
|
||||
/* Initialize the context's hardware state. */
|
||||
void nouveauDDInitState(nouveauContextPtr nmesa)
|
||||
{
|
||||
uint32_t type = nmesa->screen->card->type;
|
||||
switch(type)
|
||||
{
|
||||
case NV_03:
|
||||
case NV_04:
|
||||
case NV_05:
|
||||
/* No TCL engines for these ones */
|
||||
break;
|
||||
case NV_10:
|
||||
nv10InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
|
||||
break;
|
||||
case NV_20:
|
||||
nv20InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
|
||||
break;
|
||||
case NV_30:
|
||||
case NV_40:
|
||||
case NV_44:
|
||||
case NV_50:
|
||||
nv30InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nouveau_state_cache_init(nmesa);
|
||||
}
|
||||
|
||||
/* Initialize the driver's state functions */
|
||||
void nouveauDDInitStateFuncs(GLcontext *ctx)
|
||||
{
|
||||
ctx->Driver.UpdateState = nouveauDDInvalidateState;
|
||||
|
||||
ctx->Driver.ClearIndex = NULL;
|
||||
ctx->Driver.ClearColor = NULL; //nouveauDDClearColor;
|
||||
ctx->Driver.ClearStencil = NULL; //nouveauDDClearStencil;
|
||||
ctx->Driver.DrawBuffer = NULL; //nouveauDDDrawBuffer;
|
||||
ctx->Driver.ReadBuffer = NULL; //nouveauDDReadBuffer;
|
||||
|
||||
ctx->Driver.IndexMask = NULL;
|
||||
ctx->Driver.ColorMask = NULL; //nouveauDDColorMask;
|
||||
ctx->Driver.AlphaFunc = NULL; //nouveauDDAlphaFunc;
|
||||
ctx->Driver.BlendEquationSeparate = NULL; //nouveauDDBlendEquationSeparate;
|
||||
ctx->Driver.BlendFuncSeparate = NULL; //nouveauDDBlendFuncSeparate;
|
||||
ctx->Driver.ClearDepth = NULL; //nouveauDDClearDepth;
|
||||
ctx->Driver.CullFace = NULL; //nouveauDDCullFace;
|
||||
ctx->Driver.FrontFace = NULL; //nouveauDDFrontFace;
|
||||
ctx->Driver.DepthFunc = NULL; //nouveauDDDepthFunc;
|
||||
ctx->Driver.DepthMask = NULL; //nouveauDDDepthMask;
|
||||
ctx->Driver.Enable = NULL; //nouveauDDEnable;
|
||||
ctx->Driver.Fogfv = NULL; //nouveauDDFogfv;
|
||||
ctx->Driver.Hint = NULL;
|
||||
ctx->Driver.Lightfv = NULL;
|
||||
ctx->Driver.LightModelfv = NULL; //nouveauDDLightModelfv;
|
||||
ctx->Driver.LogicOpcode = NULL; //nouveauDDLogicOpCode;
|
||||
ctx->Driver.PolygonMode = NULL;
|
||||
ctx->Driver.PolygonStipple = NULL; //nouveauDDPolygonStipple;
|
||||
ctx->Driver.RenderMode = NULL; //nouveauDDRenderMode;
|
||||
ctx->Driver.Scissor = NULL; //nouveauDDScissor;
|
||||
ctx->Driver.ShadeModel = NULL; //nouveauDDShadeModel;
|
||||
ctx->Driver.StencilFuncSeparate = NULL; //nouveauDDStencilFuncSeparate;
|
||||
ctx->Driver.StencilMaskSeparate = NULL; //nouveauDDStencilMaskSeparate;
|
||||
ctx->Driver.StencilOpSeparate = NULL; //nouveauDDStencilOpSeparate;
|
||||
|
||||
ctx->Driver.DepthRange = nouveauDepthRange;
|
||||
ctx->Driver.Viewport = nouveauViewport;
|
||||
|
||||
/* Pixel path fallbacks.
|
||||
*/
|
||||
ctx->Driver.Accum = _swrast_Accum;
|
||||
ctx->Driver.Bitmap = _swrast_Bitmap;
|
||||
ctx->Driver.CopyPixels = _swrast_CopyPixels;
|
||||
ctx->Driver.DrawPixels = _swrast_DrawPixels;
|
||||
ctx->Driver.ReadPixels = _swrast_ReadPixels;
|
||||
|
||||
/* Swrast hooks for imaging extensions:
|
||||
*/
|
||||
ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
|
||||
ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
|
||||
ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
|
||||
ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
|
||||
}
|
||||
|
||||
#define STATE_INIT(a) if (ctx->Driver.a) ctx->Driver.a
|
||||
|
||||
void nouveauInitState(GLcontext *ctx)
|
||||
{
|
||||
/*
|
||||
* Mesa should do this for us:
|
||||
*/
|
||||
|
||||
STATE_INIT(AlphaFunc)( ctx,
|
||||
ctx->Color.AlphaFunc,
|
||||
ctx->Color.AlphaRef);
|
||||
|
||||
STATE_INIT(BlendColor)( ctx,
|
||||
ctx->Color.BlendColor );
|
||||
|
||||
STATE_INIT(BlendEquationSeparate)( ctx,
|
||||
ctx->Color.BlendEquationRGB,
|
||||
ctx->Color.BlendEquationA);
|
||||
|
||||
STATE_INIT(BlendFuncSeparate)( ctx,
|
||||
ctx->Color.BlendSrcRGB,
|
||||
ctx->Color.BlendDstRGB,
|
||||
ctx->Color.BlendSrcA,
|
||||
ctx->Color.BlendDstA);
|
||||
|
||||
STATE_INIT(ClearColor)( ctx, ctx->Color.ClearColor);
|
||||
STATE_INIT(ClearDepth)( ctx, ctx->Depth.Clear);
|
||||
STATE_INIT(ClearStencil)( ctx, ctx->Stencil.Clear);
|
||||
|
||||
STATE_INIT(ColorMask)( ctx,
|
||||
ctx->Color.ColorMask[RCOMP],
|
||||
ctx->Color.ColorMask[GCOMP],
|
||||
ctx->Color.ColorMask[BCOMP],
|
||||
ctx->Color.ColorMask[ACOMP]);
|
||||
|
||||
STATE_INIT(CullFace)( ctx, ctx->Polygon.CullFaceMode );
|
||||
STATE_INIT(DepthFunc)( ctx, ctx->Depth.Func );
|
||||
STATE_INIT(DepthMask)( ctx, ctx->Depth.Mask );
|
||||
|
||||
STATE_INIT(Enable)( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
|
||||
STATE_INIT(Enable)( ctx, GL_BLEND, ctx->Color.BlendEnabled );
|
||||
STATE_INIT(Enable)( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
|
||||
STATE_INIT(Enable)( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
|
||||
STATE_INIT(Enable)( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
|
||||
STATE_INIT(Enable)( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
|
||||
STATE_INIT(Enable)( ctx, GL_DITHER, ctx->Color.DitherFlag );
|
||||
STATE_INIT(Enable)( ctx, GL_FOG, ctx->Fog.Enabled );
|
||||
STATE_INIT(Enable)( ctx, GL_LIGHTING, ctx->Light.Enabled );
|
||||
STATE_INIT(Enable)( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
|
||||
STATE_INIT(Enable)( ctx, GL_LINE_STIPPLE, ctx->Line.StippleFlag );
|
||||
STATE_INIT(Enable)( ctx, GL_POINT_SMOOTH, ctx->Point.SmoothFlag );
|
||||
STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill);
|
||||
STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_LINE, ctx->Polygon.OffsetLine);
|
||||
STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_POINT, ctx->Polygon.OffsetPoint);
|
||||
STATE_INIT(Enable)( ctx, GL_POLYGON_SMOOTH, ctx->Polygon.SmoothFlag );
|
||||
STATE_INIT(Enable)( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
|
||||
STATE_INIT(Enable)( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
|
||||
STATE_INIT(Enable)( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
|
||||
STATE_INIT(Enable)( ctx, GL_TEXTURE_1D, GL_FALSE );
|
||||
STATE_INIT(Enable)( ctx, GL_TEXTURE_2D, GL_FALSE );
|
||||
STATE_INIT(Enable)( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
|
||||
STATE_INIT(Enable)( ctx, GL_TEXTURE_3D, GL_FALSE );
|
||||
STATE_INIT(Enable)( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
|
||||
|
||||
STATE_INIT(Fogfv)( ctx, GL_FOG_COLOR, ctx->Fog.Color );
|
||||
STATE_INIT(Fogfv)( ctx, GL_FOG_MODE, 0 );
|
||||
STATE_INIT(Fogfv)( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
|
||||
STATE_INIT(Fogfv)( ctx, GL_FOG_START, &ctx->Fog.Start );
|
||||
STATE_INIT(Fogfv)( ctx, GL_FOG_END, &ctx->Fog.End );
|
||||
|
||||
STATE_INIT(FrontFace)( ctx, ctx->Polygon.FrontFace );
|
||||
|
||||
{
|
||||
GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
|
||||
STATE_INIT(LightModelfv)( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
|
||||
}
|
||||
|
||||
STATE_INIT(LineStipple)( ctx, ctx->Line.StippleFactor, ctx->Line.StipplePattern );
|
||||
STATE_INIT(LineWidth)( ctx, ctx->Line.Width );
|
||||
STATE_INIT(LogicOpcode)( ctx, ctx->Color.LogicOp );
|
||||
STATE_INIT(PointSize)( ctx, ctx->Point.Size );
|
||||
STATE_INIT(PolygonMode)( ctx, GL_FRONT, ctx->Polygon.FrontMode );
|
||||
STATE_INIT(PolygonMode)( ctx, GL_BACK, ctx->Polygon.BackMode );
|
||||
STATE_INIT(PolygonOffset)( ctx,
|
||||
ctx->Polygon.OffsetFactor,
|
||||
ctx->Polygon.OffsetUnits );
|
||||
STATE_INIT(PolygonStipple)( ctx, (const GLubyte *)ctx->PolygonStipple );
|
||||
STATE_INIT(ShadeModel)( ctx, ctx->Light.ShadeModel );
|
||||
STATE_INIT(StencilFuncSeparate)( ctx, GL_FRONT,
|
||||
ctx->Stencil.Function[0],
|
||||
ctx->Stencil.Ref[0],
|
||||
ctx->Stencil.ValueMask[0] );
|
||||
STATE_INIT(StencilFuncSeparate)( ctx, GL_BACK,
|
||||
ctx->Stencil.Function[1],
|
||||
ctx->Stencil.Ref[1],
|
||||
ctx->Stencil.ValueMask[1] );
|
||||
STATE_INIT(StencilMaskSeparate)( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
|
||||
STATE_INIT(StencilMaskSeparate)( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
|
||||
STATE_INIT(StencilOpSeparate)( ctx, GL_FRONT,
|
||||
ctx->Stencil.FailFunc[0],
|
||||
ctx->Stencil.ZFailFunc[0],
|
||||
ctx->Stencil.ZPassFunc[0]);
|
||||
STATE_INIT(StencilOpSeparate)( ctx, GL_BACK,
|
||||
ctx->Stencil.FailFunc[1],
|
||||
ctx->Stencil.ZFailFunc[1],
|
||||
ctx->Stencil.ZPassFunc[1]);
|
||||
}
|
||||
48
src/mesa/drivers/dri/nouveau/nouveau_state.h
Normal file
48
src/mesa/drivers/dri/nouveau/nouveau_state.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Jeremy Kolb
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef __NOUVEAU_STATE_H__
|
||||
#define __NOUVEAU_STATE_H__
|
||||
|
||||
#include "nouveau_context.h"
|
||||
|
||||
extern void nouveauDDInitState(nouveauContextPtr nmesa);
|
||||
extern void nouveauDDInitStateFuncs(GLcontext *ctx);
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
extern void nouveauDDUpdateState(GLcontext *ctx);
|
||||
extern void nouveauDDUpdateHWState(GLcontext *ctx);
|
||||
|
||||
extern void nouveauEmitHwStateLocked(nouveauContextPtr nmesa);
|
||||
*/
|
||||
#endif
|
||||
|
||||
64
src/mesa/drivers/dri/nouveau/nouveau_state_cache.c
Normal file
64
src/mesa/drivers/dri/nouveau/nouveau_state_cache.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
#include "nouveau_state_cache.h"
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_object.h"
|
||||
#include "nouveau_fifo.h"
|
||||
|
||||
#define BEGIN_RING_NOFLUSH(subchannel,tag,size) do { \
|
||||
if (nmesa->fifo.free <= (size)) \
|
||||
WAIT_RING(nmesa,(size)); \
|
||||
OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \
|
||||
nmesa->fifo.free -= ((size) + 1); \
|
||||
}while(0)
|
||||
|
||||
// flush all the dirty state
|
||||
void nouveau_state_cache_flush(nouveauContextPtr nmesa)
|
||||
{
|
||||
int i=0;
|
||||
int run=0;
|
||||
|
||||
// fast-path no state changes
|
||||
if (!nmesa->state_cache.dirty)
|
||||
return;
|
||||
nmesa->state_cache.dirty=0;
|
||||
|
||||
do
|
||||
{
|
||||
// jump to a dirty state
|
||||
while((nmesa->state_cache.atoms[i].dirty==0)&&(i<NOUVEAU_STATE_CACHE_ENTRIES))
|
||||
i++;
|
||||
|
||||
// figure out a run of dirty values
|
||||
run=0;
|
||||
while((nmesa->state_cache.atoms[i+run].dirty)&&(i+run<NOUVEAU_STATE_CACHE_ENTRIES))
|
||||
run++;
|
||||
|
||||
// output everything as a single run
|
||||
if (run>0) {
|
||||
int j;
|
||||
|
||||
BEGIN_RING_NOFLUSH(NvSub3D, i*4, run);
|
||||
for(j=0;j<run;j++)
|
||||
{
|
||||
OUT_RING(nmesa->state_cache.atoms[i+j].value);
|
||||
nmesa->state_cache.atoms[i+j].dirty=0;
|
||||
}
|
||||
i+=run;
|
||||
}
|
||||
}
|
||||
while(i<NOUVEAU_STATE_CACHE_ENTRIES);
|
||||
}
|
||||
|
||||
|
||||
// inits the state cache
|
||||
void nouveau_state_cache_init(nouveauContextPtr nmesa)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<NOUVEAU_STATE_CACHE_ENTRIES;i++)
|
||||
{
|
||||
nmesa->state_cache.atoms[i].dirty=0;
|
||||
nmesa->state_cache.atoms[i].value=0xDEADBEEF; // nvidia cards like beef
|
||||
}
|
||||
nmesa->state_cache.dirty=0;
|
||||
}
|
||||
|
||||
23
src/mesa/drivers/dri/nouveau/nouveau_state_cache.h
Normal file
23
src/mesa/drivers/dri/nouveau/nouveau_state_cache.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
#ifndef __NOUVEAU_STATE_CACHE_H__
|
||||
#define __NOUVEAU_STATE_CACHE_H__
|
||||
|
||||
#include "mtypes.h"
|
||||
|
||||
#define NOUVEAU_STATE_CACHE_ENTRIES 2048
|
||||
|
||||
typedef struct nouveau_state_atom_t{
|
||||
uint32_t value;
|
||||
uint32_t dirty;
|
||||
}nouveau_state_atom;
|
||||
|
||||
typedef struct nouveau_state_cache_t{
|
||||
nouveau_state_atom atoms[NOUVEAU_STATE_CACHE_ENTRIES];
|
||||
uint32_t current_pos;
|
||||
// master dirty flag
|
||||
uint32_t dirty;
|
||||
}nouveau_state_cache;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
127
src/mesa/drivers/dri/nouveau/nouveau_swtcl.c
Normal file
127
src/mesa/drivers/dri/nouveau/nouveau_swtcl.c
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
/* Common software TCL code */
|
||||
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_swtcl.h"
|
||||
#include "nv10_swtcl.h"
|
||||
#include "nouveau_span.h"
|
||||
#include "swrast/swrast.h"
|
||||
#include "swrast_setup/swrast_setup.h"
|
||||
#include "tnl/tnl.h"
|
||||
#include "tnl/t_pipeline.h"
|
||||
|
||||
/* Common tri functions */
|
||||
|
||||
/* The fallbacks */
|
||||
void nouveau_fallback_tri(struct nouveau_context *nmesa,
|
||||
nouveauVertex *v0,
|
||||
nouveauVertex *v1,
|
||||
nouveauVertex *v2)
|
||||
{
|
||||
GLcontext *ctx = nmesa->glCtx;
|
||||
SWvertex v[3];
|
||||
_swsetup_Translate(ctx, v0, &v[0]);
|
||||
_swsetup_Translate(ctx, v1, &v[1]);
|
||||
_swsetup_Translate(ctx, v2, &v[2]);
|
||||
_swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
|
||||
}
|
||||
|
||||
|
||||
void nouveau_fallback_line(struct nouveau_context *nmesa,
|
||||
nouveauVertex *v0,
|
||||
nouveauVertex *v1)
|
||||
{
|
||||
GLcontext *ctx = nmesa->glCtx;
|
||||
SWvertex v[2];
|
||||
_swsetup_Translate(ctx, v0, &v[0]);
|
||||
_swsetup_Translate(ctx, v1, &v[1]);
|
||||
_swrast_Line(ctx, &v[0], &v[1]);
|
||||
}
|
||||
|
||||
|
||||
void nouveau_fallback_point(struct nouveau_context *nmesa,
|
||||
nouveauVertex *v0)
|
||||
{
|
||||
GLcontext *ctx = nmesa->glCtx;
|
||||
SWvertex v[1];
|
||||
_swsetup_Translate(ctx, v0, &v[0]);
|
||||
_swrast_Point(ctx, &v[0]);
|
||||
}
|
||||
|
||||
void nouveauFallback(struct nouveau_context *nmesa, GLuint bit, GLboolean mode)
|
||||
{
|
||||
GLcontext *ctx = nmesa->glCtx;
|
||||
GLuint oldfallback = nmesa->Fallback;
|
||||
|
||||
if (mode) {
|
||||
nmesa->Fallback |= bit;
|
||||
if (oldfallback == 0) {
|
||||
if (nmesa->screen->card->type<NV_10) {
|
||||
//nv03FinishPrimitive(nmesa);
|
||||
} else {
|
||||
nv10FinishPrimitive(nmesa);
|
||||
}
|
||||
|
||||
_swsetup_Wakeup(ctx);
|
||||
nmesa->render_index = ~0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nmesa->Fallback &= ~bit;
|
||||
if (oldfallback == bit) {
|
||||
_swrast_flush( ctx );
|
||||
|
||||
if (nmesa->screen->card->type<NV_10) {
|
||||
//nv03TriInitFunctions(ctx);
|
||||
} else {
|
||||
nv10TriInitFunctions(ctx);
|
||||
}
|
||||
|
||||
_tnl_invalidate_vertex_state( ctx, ~0 );
|
||||
_tnl_invalidate_vertices( ctx, ~0 );
|
||||
_tnl_install_attrs( ctx,
|
||||
nmesa->vertex_attrs,
|
||||
nmesa->vertex_attr_count,
|
||||
nmesa->viewport.m, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nouveauRunPipeline( GLcontext *ctx )
|
||||
{
|
||||
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
if (nmesa->new_state) {
|
||||
nmesa->new_render_state |= nmesa->new_state;
|
||||
}
|
||||
|
||||
_tnl_run_pipeline( ctx );
|
||||
}
|
||||
|
||||
|
||||
55
src/mesa/drivers/dri/nouveau/nouveau_swtcl.h
Normal file
55
src/mesa/drivers/dri/nouveau/nouveau_swtcl.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_SWTCL_H__
|
||||
#define __NOUVEAU_SWTCL_H__
|
||||
|
||||
#include "nouveau_context.h"
|
||||
|
||||
extern void nouveau_fallback_tri(struct nouveau_context *nmesa,
|
||||
nouveauVertex *v0,
|
||||
nouveauVertex *v1,
|
||||
nouveauVertex *v2);
|
||||
|
||||
extern void nouveau_fallback_line(struct nouveau_context *nmesa,
|
||||
nouveauVertex *v0,
|
||||
nouveauVertex *v1);
|
||||
|
||||
extern void nouveau_fallback_point(struct nouveau_context *nmesa,
|
||||
nouveauVertex *v0);
|
||||
|
||||
extern void nouveauFallback(struct nouveau_context *nmesa, GLuint bit, GLboolean mode);
|
||||
|
||||
extern void nouveauRunPipeline( GLcontext *ctx );
|
||||
|
||||
extern void nouveauTriInitFunctions( GLcontext *ctx );
|
||||
|
||||
|
||||
#endif /* __NOUVEAU_SWTCL_H__ */
|
||||
|
||||
|
||||
49
src/mesa/drivers/dri/nouveau/nouveau_tex.c
Normal file
49
src/mesa/drivers/dri/nouveau/nouveau_tex.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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_tex.h"
|
||||
|
||||
// XXX needs some love
|
||||
void nouveauTexInitFunctions( struct dd_function_table *functions )
|
||||
{
|
||||
/*
|
||||
functions->TexEnv = nouveauTexEnv;
|
||||
functions->ChooseTextureFormat = nouveauChooseTextureFormat;
|
||||
functions->TexImage1D = nouveauTexImage1D;
|
||||
functions->TexSubImage1D = nouveauTexSubImage1D;
|
||||
functions->TexImage2D = nouveauTexImage2D;
|
||||
functions->TexSubImage2D = nouveauTexSubImage2D;
|
||||
functions->TexParameter = nouveauTexParameter;
|
||||
functions->BindTexture = nouveauBindTexture;
|
||||
functions->NewTextureObject = nouveauNewTextureObject;
|
||||
functions->DeleteTexture = nouveauDeleteTexture;
|
||||
functions->IsTextureResident = driIsTextureResident;
|
||||
|
||||
driInitTextureFormats();
|
||||
*/
|
||||
}
|
||||
|
||||
38
src/mesa/drivers/dri/nouveau/nouveau_tex.h
Normal file
38
src/mesa/drivers/dri/nouveau/nouveau_tex.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef __NOUVEAU_TEX_H__
|
||||
#define __NOUVEAU_TEX_H__
|
||||
|
||||
#include <errno.h>
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
#include "dd.h"
|
||||
|
||||
extern void nouveauTexInitFunctions( struct dd_function_table *functions );
|
||||
|
||||
#endif /* __NOUVEAU_TEX_H__ */
|
||||
646
src/mesa/drivers/dri/nouveau/nv10_state.c
Normal file
646
src/mesa/drivers/dri/nouveau/nv10_state.c
Normal file
|
|
@ -0,0 +1,646 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Nouveau
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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_context.h"
|
||||
#include "nouveau_object.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_reg.h"
|
||||
|
||||
#include "tnl/t_pipeline.h"
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "colormac.h"
|
||||
|
||||
static void nv10AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte ubRef;
|
||||
CLAMPED_FLOAT_TO_UBYTE(ubRef, ref);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
|
||||
OUT_RING_CACHE(func); /* NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC */
|
||||
OUT_RING_CACHE(ubRef); /* NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF */
|
||||
}
|
||||
|
||||
static void nv10BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte cf[4];
|
||||
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_COLOR, 1);
|
||||
OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0]));
|
||||
}
|
||||
|
||||
static void nv10BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1);
|
||||
OUT_RING_CACHE((modeA<<16) | modeRGB);
|
||||
}
|
||||
|
||||
|
||||
static void nv10BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
|
||||
GLenum sfactorA, GLenum dfactorA)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
|
||||
OUT_RING_CACHE((sfactorA<<16) | sfactorRGB);
|
||||
OUT_RING_CACHE((dfactorA<<16) | dfactorRGB);
|
||||
}
|
||||
|
||||
/*
|
||||
static void nv10ClearColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
}
|
||||
|
||||
static void nv10ClearDepth(GLcontext *ctx, GLclampd d)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
/* we're don't support indexed buffers
|
||||
void (*ClearIndex)(GLcontext *ctx, GLuint index)
|
||||
*/
|
||||
|
||||
/*
|
||||
static void nv10ClearStencil(GLcontext *ctx, GLint s)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
static void nv10ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4);
|
||||
OUT_RING_CACHEf(equation[0]);
|
||||
OUT_RING_CACHEf(equation[1]);
|
||||
OUT_RING_CACHEf(equation[2]);
|
||||
OUT_RING_CACHEf(equation[3]);
|
||||
}
|
||||
|
||||
/* Seems does not support alpha in color mask */
|
||||
static void nv10ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
|
||||
GLboolean bmask, GLboolean amask )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
|
||||
OUT_RING_CACHE(/*((amask && 0x01) << 24) |*/ ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0));
|
||||
}
|
||||
|
||||
static void nv10ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
|
||||
{
|
||||
// TODO I need love
|
||||
}
|
||||
|
||||
static void nv10CullFace(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
static void nv10FrontFace(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FRONT_FACE, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
static void nv10DepthFunc(GLcontext *ctx, GLenum func)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
|
||||
OUT_RING_CACHE(func);
|
||||
}
|
||||
|
||||
static void nv10DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
|
||||
OUT_RING_CACHE(flag);
|
||||
}
|
||||
|
||||
static void nv10DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
|
||||
OUT_RING_CACHEf(nearval);
|
||||
OUT_RING_CACHEf(farval);
|
||||
}
|
||||
|
||||
/** Specify the current buffer for writing */
|
||||
//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer );
|
||||
/** Specify the buffers for writing for fragment programs*/
|
||||
//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers );
|
||||
|
||||
static void nv10Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
switch(cap)
|
||||
{
|
||||
case GL_ALPHA_TEST:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_AUTO_NORMAL:
|
||||
case GL_BLEND:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_CLIP_PLANE0:
|
||||
case GL_CLIP_PLANE1:
|
||||
case GL_CLIP_PLANE2:
|
||||
case GL_CLIP_PLANE3:
|
||||
case GL_CLIP_PLANE4:
|
||||
case GL_CLIP_PLANE5:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_COLOR_LOGIC_OP:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_COLOR_MATERIAL:
|
||||
// case GL_COLOR_SUM_EXT:
|
||||
// case GL_COLOR_TABLE:
|
||||
// case GL_CONVOLUTION_1D:
|
||||
// case GL_CONVOLUTION_2D:
|
||||
case GL_CULL_FACE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_DEPTH_TEST:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_DITHER:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_FOG:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_HISTOGRAM:
|
||||
// case GL_INDEX_LOGIC_OP:
|
||||
case GL_LIGHT0:
|
||||
case GL_LIGHT1:
|
||||
case GL_LIGHT2:
|
||||
case GL_LIGHT3:
|
||||
case GL_LIGHT4:
|
||||
case GL_LIGHT5:
|
||||
case GL_LIGHT6:
|
||||
case GL_LIGHT7:
|
||||
{
|
||||
uint32_t mask=1<<(2*(cap-GL_LIGHT0));
|
||||
nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state));
|
||||
if (nmesa->lighting_enabled)
|
||||
{
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
|
||||
OUT_RING_CACHE(nmesa->enabled_lights);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GL_LIGHTING:
|
||||
nmesa->lighting_enabled=state;
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
|
||||
if (nmesa->lighting_enabled)
|
||||
OUT_RING_CACHE(nmesa->enabled_lights);
|
||||
else
|
||||
OUT_RING_CACHE(0x0);
|
||||
break;
|
||||
case GL_LINE_SMOOTH:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_LINE_STIPPLE:
|
||||
// case GL_MAP1_COLOR_4:
|
||||
// case GL_MAP1_INDEX:
|
||||
// case GL_MAP1_NORMAL:
|
||||
// case GL_MAP1_TEXTURE_COORD_1:
|
||||
// case GL_MAP1_TEXTURE_COORD_2:
|
||||
// case GL_MAP1_TEXTURE_COORD_3:
|
||||
// case GL_MAP1_TEXTURE_COORD_4:
|
||||
// case GL_MAP1_VERTEX_3:
|
||||
// case GL_MAP1_VERTEX_4:
|
||||
// case GL_MAP2_COLOR_4:
|
||||
// case GL_MAP2_INDEX:
|
||||
// case GL_MAP2_NORMAL:
|
||||
// case GL_MAP2_TEXTURE_COORD_1:
|
||||
// case GL_MAP2_TEXTURE_COORD_2:
|
||||
// case GL_MAP2_TEXTURE_COORD_3:
|
||||
// case GL_MAP2_TEXTURE_COORD_4:
|
||||
// case GL_MAP2_VERTEX_3:
|
||||
// case GL_MAP2_VERTEX_4:
|
||||
// case GL_MINMAX:
|
||||
case GL_NORMALIZE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_POINT_SMOOTH:
|
||||
case GL_POLYGON_OFFSET_POINT:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_OFFSET_LINE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_OFFSET_FILL:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_SMOOTH:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_POLYGON_STIPPLE:
|
||||
// case GL_POST_COLOR_MATRIX_COLOR_TABLE:
|
||||
// case GL_POST_CONVOLUTION_COLOR_TABLE:
|
||||
// case GL_RESCALE_NORMAL:
|
||||
// case GL_SCISSOR_TEST:
|
||||
// case GL_SEPARABLE_2D:
|
||||
case GL_STENCIL_TEST:
|
||||
// TODO BACK and FRONT ?
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_TEXTURE_GEN_Q:
|
||||
// case GL_TEXTURE_GEN_R:
|
||||
// case GL_TEXTURE_GEN_S:
|
||||
// case GL_TEXTURE_GEN_T:
|
||||
// case GL_TEXTURE_1D:
|
||||
// case GL_TEXTURE_2D:
|
||||
// case GL_TEXTURE_3D:
|
||||
}
|
||||
}
|
||||
|
||||
static void nv10Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
switch(pname)
|
||||
{
|
||||
case GL_FOG_MODE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FOG_MODE, 1);
|
||||
//OUT_RING_CACHE (params);
|
||||
break;
|
||||
/* TODO: unsure about the rest.*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void nv10Hint(GLcontext *ctx, GLenum target, GLenum mode)
|
||||
{
|
||||
// TODO I need love (fog and line_smooth hints)
|
||||
}
|
||||
|
||||
// void (*IndexMask)(GLcontext *ctx, GLuint mask);
|
||||
|
||||
enum {
|
||||
SPOTLIGHT_UPDATE_EXPONENT,
|
||||
SPOTLIGHT_UPDATE_DIRECTION,
|
||||
SPOTLIGHT_UPDATE_ALL
|
||||
};
|
||||
|
||||
static void nv10Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLint p = light - GL_LIGHT0;
|
||||
struct gl_light *l = &ctx->Light.Light[p];
|
||||
int spotlightUpdate = -1;
|
||||
|
||||
switch(pname)
|
||||
{
|
||||
case GL_AMBIENT:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_DIFFUSE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_SPECULAR:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_POSITION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_SPOT_DIRECTION:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_DIRECTION;
|
||||
break;
|
||||
case GL_SPOT_EXPONENT:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_EXPONENT;
|
||||
break;
|
||||
case GL_SPOT_CUTOFF:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_ALL;
|
||||
break;
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(spotlightUpdate) {
|
||||
case SPOTLIGHT_UPDATE_DIRECTION:
|
||||
{
|
||||
GLfloat x,y,z;
|
||||
x = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[0];
|
||||
y = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[1];
|
||||
z = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[2];
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3);
|
||||
OUT_RING_CACHEf(x);
|
||||
OUT_RING_CACHEf(y);
|
||||
OUT_RING_CACHEf(z);
|
||||
}
|
||||
break;
|
||||
case SPOTLIGHT_UPDATE_EXPONENT:
|
||||
{
|
||||
GLfloat cc,lc,qc;
|
||||
cc = 1.0; /* FIXME: These need to be correctly computed */
|
||||
lc = 0.0;
|
||||
qc = 2.0;
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3);
|
||||
OUT_RING_CACHEf(cc);
|
||||
OUT_RING_CACHEf(lc);
|
||||
OUT_RING_CACHEf(qc);
|
||||
}
|
||||
break;
|
||||
case SPOTLIGHT_UPDATE_ALL:
|
||||
{
|
||||
GLfloat cc,lc,qc, x,y,z, c;
|
||||
cc = 1.0; /* FIXME: These need to be correctly computed */
|
||||
lc = 0.0;
|
||||
qc = 2.0;
|
||||
x = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[0];
|
||||
y = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[1];
|
||||
z = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[2];
|
||||
c = -2.0 * (0.5 + l->_CosCutoff);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7);
|
||||
OUT_RING_CACHEf(cc);
|
||||
OUT_RING_CACHEf(lc);
|
||||
OUT_RING_CACHEf(qc);
|
||||
OUT_RING_CACHEf(x);
|
||||
OUT_RING_CACHEf(y);
|
||||
OUT_RING_CACHEf(z);
|
||||
OUT_RING_CACHEf(c);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the lighting model parameters */
|
||||
static void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
|
||||
|
||||
|
||||
static void nv10LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
|
||||
{
|
||||
}
|
||||
|
||||
static void nv10LineWidth(GLcontext *ctx, GLfloat width)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LINE_WIDTH, 1);
|
||||
OUT_RING_CACHE(((int) (width * 8.0)) & -4);
|
||||
}
|
||||
|
||||
static void nv10LogicOpcode(GLcontext *ctx, GLenum opcode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1);
|
||||
OUT_RING_CACHE(opcode);
|
||||
}
|
||||
|
||||
static void nv10PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
|
||||
{
|
||||
/*TODO: not sure what goes here. */
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
}
|
||||
|
||||
/** Specify the diameter of rasterized points */
|
||||
static void nv10PointSize(GLcontext *ctx, GLfloat size)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
|
||||
OUT_RING_CACHE(((int) (size * 8.0)) & -4);
|
||||
}
|
||||
|
||||
/** Select a polygon rasterization mode */
|
||||
static void nv10PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the scale and units used to calculate depth values */
|
||||
void (*PolygonOffset)(GLcontext *ctx, GLfloat factor, GLfloat units);
|
||||
/** Set the polygon stippling pattern */
|
||||
void (*PolygonStipple)(GLcontext *ctx, const GLubyte *mask );
|
||||
/* Specifies the current buffer for reading */
|
||||
void (*ReadBuffer)( GLcontext *ctx, GLenum buffer );
|
||||
/** Set rasterization mode */
|
||||
void (*RenderMode)(GLcontext *ctx, GLenum mode );
|
||||
|
||||
/** Define the scissor box */
|
||||
static void nv10Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
|
||||
{
|
||||
}
|
||||
|
||||
/** Select flat or smooth shading */
|
||||
static void nv10ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilFunc */
|
||||
static void nv10StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
|
||||
GLint ref, GLuint mask)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC, 3);
|
||||
OUT_RING_CACHE(func);
|
||||
OUT_RING_CACHE(ref);
|
||||
OUT_RING_CACHE(mask);
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilMask */
|
||||
static void nv10StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_MASK, 1);
|
||||
OUT_RING_CACHE(mask);
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilOp */
|
||||
static void nv10StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
|
||||
GLenum zfail, GLenum zpass)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL, 1);
|
||||
OUT_RING_CACHE(fail);
|
||||
OUT_RING_CACHE(zfail);
|
||||
OUT_RING_CACHE(zpass);
|
||||
}
|
||||
|
||||
/** Control the generation of texture coordinates */
|
||||
void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname,
|
||||
const GLfloat *params);
|
||||
/** Set texture environment parameters */
|
||||
void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname,
|
||||
const GLfloat *param);
|
||||
/** Set texture parameters */
|
||||
void (*TexParameter)(GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj,
|
||||
GLenum pname, const GLfloat *params);
|
||||
void (*TextureMatrix)(GLcontext *ctx, GLuint unit, const GLmatrix *mat);
|
||||
|
||||
/** Set the viewport */
|
||||
static void nv10Viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
|
||||
{
|
||||
/* TODO: Where do the VIEWPORT_XFRM_* regs come in? */
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
|
||||
OUT_RING_CACHE((w << 16) | x);
|
||||
OUT_RING_CACHE((h << 16) | y);
|
||||
}
|
||||
|
||||
/* Initialise any card-specific non-GL related state */
|
||||
static GLboolean nv10InitCard(nouveauContextPtr nmesa)
|
||||
{
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* Update buffer offset/pitch/format */
|
||||
static GLboolean nv10BindBuffers(nouveauContextPtr nmesa, int num_color,
|
||||
nouveau_renderbuffer **color,
|
||||
nouveau_renderbuffer *depth)
|
||||
{
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* Update anything that depends on the window position/size */
|
||||
static void nv10WindowMoved(nouveauContextPtr nmesa)
|
||||
{
|
||||
}
|
||||
|
||||
void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
func->AlphaFunc = nv10AlphaFunc;
|
||||
func->BlendColor = nv10BlendColor;
|
||||
func->BlendEquationSeparate = nv10BlendEquationSeparate;
|
||||
func->BlendFuncSeparate = nv10BlendFuncSeparate;
|
||||
#if 0
|
||||
func->ClearColor = nv10ClearColor;
|
||||
func->ClearDepth = nv10ClearDepth;
|
||||
func->ClearStencil = nv10ClearStencil;
|
||||
#endif
|
||||
func->ClipPlane = nv10ClipPlane;
|
||||
func->ColorMask = nv10ColorMask;
|
||||
func->ColorMaterial = nv10ColorMaterial;
|
||||
func->CullFace = nv10CullFace;
|
||||
func->FrontFace = nv10FrontFace;
|
||||
func->DepthFunc = nv10DepthFunc;
|
||||
func->DepthMask = nv10DepthMask;
|
||||
func->DepthRange = nv10DepthRange;
|
||||
func->Enable = nv10Enable;
|
||||
func->Fogfv = nv10Fogfv;
|
||||
func->Hint = nv10Hint;
|
||||
func->Lightfv = nv10Lightfv;
|
||||
/* func->LightModelfv = nv10LightModelfv; */
|
||||
func->LineStipple = nv10LineStipple;
|
||||
func->LineWidth = nv10LineWidth;
|
||||
func->LogicOpcode = nv10LogicOpcode;
|
||||
func->PointParameterfv = nv10PointParameterfv;
|
||||
func->PointSize = nv10PointSize;
|
||||
func->PolygonMode = nv10PolygonMode;
|
||||
#if 0
|
||||
func->PolygonOffset = nv10PolygonOffset;
|
||||
func->PolygonStipple = nv10PolygonStipple;
|
||||
func->ReadBuffer = nv10ReadBuffer;
|
||||
func->RenderMode = nv10RenderMode;
|
||||
#endif
|
||||
func->Scissor = nv10Scissor;
|
||||
func->ShadeModel = nv10ShadeModel;
|
||||
func->StencilFuncSeparate = nv10StencilFuncSeparate;
|
||||
func->StencilMaskSeparate = nv10StencilMaskSeparate;
|
||||
func->StencilOpSeparate = nv10StencilOpSeparate;
|
||||
#if 0
|
||||
func->TexGen = nv10TexGen;
|
||||
func->TexParameter = nv10TexParameter;
|
||||
func->TextureMatrix = nv10TextureMatrix;
|
||||
#endif
|
||||
func->Viewport = nv10Viewport;
|
||||
|
||||
nmesa->hw_func.InitCard = nv10InitCard;
|
||||
nmesa->hw_func.BindBuffers = nv10BindBuffers;
|
||||
nmesa->hw_func.WindowMoved = nv10WindowMoved;
|
||||
}
|
||||
|
||||
627
src/mesa/drivers/dri/nouveau/nv10_swtcl.c
Normal file
627
src/mesa/drivers/dri/nouveau/nv10_swtcl.c
Normal file
|
|
@ -0,0 +1,627 @@
|
|||
/*
|
||||
* Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
|
||||
* Copyright 2006 Stephane Marchesin. 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, sub license,
|
||||
* 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* VIA, S3 GRAPHICS, 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.
|
||||
*/
|
||||
|
||||
/* Software TCL for NV10, NV20, NV30, NV40, G70 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "glheader.h"
|
||||
#include "context.h"
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
#include "colormac.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "swrast/swrast.h"
|
||||
#include "swrast_setup/swrast_setup.h"
|
||||
#include "tnl/t_context.h"
|
||||
#include "tnl/t_pipeline.h"
|
||||
|
||||
#include "nouveau_swtcl.h"
|
||||
#include "nv10_swtcl.h"
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_span.h"
|
||||
#include "nouveau_reg.h"
|
||||
#include "nouveau_tex.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_msg.h"
|
||||
#include "nouveau_object.h"
|
||||
|
||||
static void nv10RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
|
||||
static void nv10RenderPrimitive( GLcontext *ctx, GLenum prim );
|
||||
static void nv10ResetLineStipple( GLcontext *ctx );
|
||||
|
||||
|
||||
|
||||
/* the size above which we fire the ring. this is a performance-tunable */
|
||||
#define NOUVEAU_FIRE_SIZE (2048/4)
|
||||
|
||||
static inline void nv10StartPrimitive(struct nouveau_context* nmesa,uint32_t primitive,uint32_t size)
|
||||
{
|
||||
if (nmesa->screen->card->type==NV_10)
|
||||
BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_BEGIN_END,1);
|
||||
else if (nmesa->screen->card->type==NV_20)
|
||||
BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_BEGIN_END,1);
|
||||
else
|
||||
BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_BEGIN_END,1);
|
||||
OUT_RING(primitive);
|
||||
|
||||
if (nmesa->screen->card->type==NV_10)
|
||||
BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_DATA|NONINC_METHOD,size);
|
||||
else if (nmesa->screen->card->type==NV_20)
|
||||
BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_VERTEX_DATA|NONINC_METHOD,size);
|
||||
else
|
||||
BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_DATA|NONINC_METHOD,size);
|
||||
}
|
||||
|
||||
inline void nv10FinishPrimitive(struct nouveau_context *nmesa)
|
||||
{
|
||||
if (nmesa->screen->card->type==NV_10)
|
||||
BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_BEGIN_END,1);
|
||||
else if (nmesa->screen->card->type==NV_20)
|
||||
BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_BEGIN_END,1);
|
||||
else
|
||||
BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_BEGIN_END,1);
|
||||
OUT_RING(0x0);
|
||||
FIRE_RING();
|
||||
}
|
||||
|
||||
|
||||
static inline void nv10ExtendPrimitive(struct nouveau_context* nmesa, int size)
|
||||
{
|
||||
/* make sure there's enough room. if not, wait */
|
||||
if (RING_AVAILABLE()<size)
|
||||
{
|
||||
WAIT_RING(nmesa,size);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nv10_draw_quad(nouveauContextPtr nmesa,
|
||||
nouveauVertexPtr v0,
|
||||
nouveauVertexPtr v1,
|
||||
nouveauVertexPtr v2,
|
||||
nouveauVertexPtr v3)
|
||||
{
|
||||
GLuint vertsize = nmesa->vertex_size;
|
||||
nv10ExtendPrimitive(nmesa, 4 * 4 * vertsize);
|
||||
|
||||
OUT_RINGp(v0,vertsize);
|
||||
OUT_RINGp(v1,vertsize);
|
||||
OUT_RINGp(v2,vertsize);
|
||||
OUT_RINGp(v3,vertsize);
|
||||
}
|
||||
|
||||
static inline void nv10_draw_triangle(nouveauContextPtr nmesa,
|
||||
nouveauVertexPtr v0,
|
||||
nouveauVertexPtr v1,
|
||||
nouveauVertexPtr v2)
|
||||
{
|
||||
GLuint vertsize = nmesa->vertex_size;
|
||||
nv10ExtendPrimitive(nmesa, 3 * 4 * vertsize);
|
||||
|
||||
OUT_RINGp(v0,vertsize);
|
||||
OUT_RINGp(v1,vertsize);
|
||||
OUT_RINGp(v2,vertsize);
|
||||
}
|
||||
|
||||
static inline void nv10_draw_line(nouveauContextPtr nmesa,
|
||||
nouveauVertexPtr v0,
|
||||
nouveauVertexPtr v1)
|
||||
{
|
||||
GLuint vertsize = nmesa->vertex_size;
|
||||
nv10ExtendPrimitive(nmesa, 2 * 4 * vertsize);
|
||||
OUT_RINGp(v0,vertsize);
|
||||
OUT_RINGp(v1,vertsize);
|
||||
}
|
||||
|
||||
static inline void nv10_draw_point(nouveauContextPtr nmesa,
|
||||
nouveauVertexPtr v0)
|
||||
{
|
||||
GLuint vertsize = nmesa->vertex_size;
|
||||
nv10ExtendPrimitive(nmesa, 1 * 4 * vertsize);
|
||||
OUT_RINGp(v0,vertsize);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* Render unclipped begin/end objects */
|
||||
/**********************************************************************/
|
||||
|
||||
static inline void nv10_render_generic_primitive_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags,GLuint prim)
|
||||
{
|
||||
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte *vertptr = (GLubyte *)nmesa->verts;
|
||||
GLuint vertsize = nmesa->vertex_size;
|
||||
GLuint size_dword = vertsize*(count-start)/4;
|
||||
|
||||
nv10ExtendPrimitive(nmesa, size_dword);
|
||||
nv10StartPrimitive(nmesa,prim+1,size_dword);
|
||||
OUT_RINGp((nouveauVertex*)(vertptr+(start*vertsize)),size_dword);
|
||||
nv10FinishPrimitive(nmesa);
|
||||
}
|
||||
|
||||
static void nv10_render_points_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_POINTS);
|
||||
}
|
||||
|
||||
static void nv10_render_lines_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINES);
|
||||
}
|
||||
|
||||
static void nv10_render_line_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINE_STRIP);
|
||||
}
|
||||
|
||||
static void nv10_render_line_loop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINE_LOOP);
|
||||
}
|
||||
|
||||
static void nv10_render_triangles_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLES);
|
||||
}
|
||||
|
||||
static void nv10_render_tri_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLE_STRIP);
|
||||
}
|
||||
|
||||
static void nv10_render_tri_fan_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLE_FAN);
|
||||
}
|
||||
|
||||
static void nv10_render_quads_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_QUADS);
|
||||
}
|
||||
|
||||
static void nv10_render_quad_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_QUAD_STRIP);
|
||||
}
|
||||
|
||||
static void nv10_render_poly_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_POLYGON);
|
||||
}
|
||||
|
||||
static void nv10_render_noop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void (*nv10_render_tab_verts[GL_POLYGON+2])(GLcontext *,
|
||||
GLuint,
|
||||
GLuint,
|
||||
GLuint) =
|
||||
{
|
||||
nv10_render_points_verts,
|
||||
nv10_render_lines_verts,
|
||||
nv10_render_line_loop_verts,
|
||||
nv10_render_line_strip_verts,
|
||||
nv10_render_triangles_verts,
|
||||
nv10_render_tri_strip_verts,
|
||||
nv10_render_tri_fan_verts,
|
||||
nv10_render_quads_verts,
|
||||
nv10_render_quad_strip_verts,
|
||||
nv10_render_poly_verts,
|
||||
nv10_render_noop_verts,
|
||||
};
|
||||
|
||||
|
||||
static inline void nv10_render_generic_primitive_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags,GLuint prim)
|
||||
{
|
||||
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte *vertptr = (GLubyte *)nmesa->verts;
|
||||
GLuint vertsize = nmesa->vertex_size;
|
||||
GLuint size_dword = vertsize*(count-start)/4;
|
||||
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
|
||||
GLuint j;
|
||||
|
||||
nv10ExtendPrimitive(nmesa, size_dword);
|
||||
nv10StartPrimitive(nmesa,prim+1,size_dword);
|
||||
for (j=start; j<count; j++ ) {
|
||||
OUT_RINGp((nouveauVertex*)(vertptr+(elt[j]*vertsize)),vertsize);
|
||||
}
|
||||
nv10FinishPrimitive(nmesa);
|
||||
}
|
||||
|
||||
static void nv10_render_points_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_POINTS);
|
||||
}
|
||||
|
||||
static void nv10_render_lines_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINES);
|
||||
}
|
||||
|
||||
static void nv10_render_line_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINE_STRIP);
|
||||
}
|
||||
|
||||
static void nv10_render_line_loop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINE_LOOP);
|
||||
}
|
||||
|
||||
static void nv10_render_triangles_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLES);
|
||||
}
|
||||
|
||||
static void nv10_render_tri_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLE_STRIP);
|
||||
}
|
||||
|
||||
static void nv10_render_tri_fan_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLE_FAN);
|
||||
}
|
||||
|
||||
static void nv10_render_quads_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_QUADS);
|
||||
}
|
||||
|
||||
static void nv10_render_quad_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_QUAD_STRIP);
|
||||
}
|
||||
|
||||
static void nv10_render_poly_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_POLYGON);
|
||||
}
|
||||
|
||||
static void nv10_render_noop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void (*nv10_render_tab_elts[GL_POLYGON+2])(GLcontext *,
|
||||
GLuint,
|
||||
GLuint,
|
||||
GLuint) =
|
||||
{
|
||||
nv10_render_points_elts,
|
||||
nv10_render_lines_elts,
|
||||
nv10_render_line_loop_elts,
|
||||
nv10_render_line_strip_elts,
|
||||
nv10_render_triangles_elts,
|
||||
nv10_render_tri_strip_elts,
|
||||
nv10_render_tri_fan_elts,
|
||||
nv10_render_quads_elts,
|
||||
nv10_render_quad_strip_elts,
|
||||
nv10_render_poly_elts,
|
||||
nv10_render_noop_elts,
|
||||
};
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* Choose render functions */
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
#define EMIT_ATTR( ATTR, STYLE ) \
|
||||
do { \
|
||||
nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = (ATTR); \
|
||||
nmesa->vertex_attrs[nmesa->vertex_attr_count].format = (STYLE); \
|
||||
nmesa->vertex_attr_count++; \
|
||||
} while (0)
|
||||
|
||||
|
||||
static void nv10ChooseRenderState(GLcontext *ctx)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
nmesa->draw_point = nv10_draw_point;
|
||||
nmesa->draw_line = nv10_draw_line;
|
||||
nmesa->draw_tri = nv10_draw_triangle;
|
||||
|
||||
tnl->Driver.Render.PrimTabVerts = nv10_render_tab_verts;
|
||||
tnl->Driver.Render.PrimTabElts = nv10_render_tab_elts;
|
||||
tnl->Driver.Render.ClippedLine = NULL;
|
||||
tnl->Driver.Render.ClippedPolygon = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void nv10OutputVertexFormat(struct nouveau_context* nmesa)
|
||||
{
|
||||
GLcontext* ctx=nmesa->glCtx;
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
DECLARE_RENDERINPUTS(index);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
int attr_size[16];
|
||||
int default_attr_size[8]={3,3,3,4,3,1,4,4};
|
||||
int i;
|
||||
int slots=0;
|
||||
int total_size=0;
|
||||
/* t_vertex_generic dereferences a NULL pointer if we
|
||||
* pass NULL as the vp transform...
|
||||
*/
|
||||
const GLfloat ident_vp[16] = {
|
||||
1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0
|
||||
};
|
||||
|
||||
RENDERINPUTS_COPY(index, nmesa->render_inputs_bitset);
|
||||
|
||||
/*
|
||||
* Determine attribute sizes
|
||||
*/
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
if (RENDERINPUTS_TEST(index, i))
|
||||
attr_size[i]=default_attr_size[i];
|
||||
else
|
||||
attr_size[i]=0;
|
||||
}
|
||||
for(i=8;i<16;i++)
|
||||
{
|
||||
if (RENDERINPUTS_TEST(index, i))
|
||||
attr_size[i]=VB->TexCoordPtr[i-8]->size;
|
||||
else
|
||||
attr_size[i]=0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell t_vertex about the vertex format
|
||||
*/
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
if (RENDERINPUTS_TEST(index, i))
|
||||
{
|
||||
slots=i+1;
|
||||
if (i==_TNL_ATTRIB_POS)
|
||||
{
|
||||
/* special-case POS */
|
||||
EMIT_ATTR(_TNL_ATTRIB_POS,EMIT_3F_VIEWPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(attr_size[i])
|
||||
{
|
||||
case 1:
|
||||
EMIT_ATTR(i,EMIT_1F);
|
||||
break;
|
||||
case 2:
|
||||
EMIT_ATTR(i,EMIT_2F);
|
||||
break;
|
||||
case 3:
|
||||
EMIT_ATTR(i,EMIT_3F);
|
||||
break;
|
||||
case 4:
|
||||
EMIT_ATTR(i,EMIT_4F);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i==_TNL_ATTRIB_COLOR0)
|
||||
nmesa->color_offset=total_size;
|
||||
if (i==_TNL_ATTRIB_COLOR1)
|
||||
nmesa->specular_offset=total_size;
|
||||
total_size+=attr_size[i];
|
||||
}
|
||||
}
|
||||
|
||||
nmesa->vertex_size=_tnl_install_attrs( ctx,
|
||||
nmesa->vertex_attrs,
|
||||
nmesa->vertex_attr_count,
|
||||
ident_vp, 0 );
|
||||
assert(nmesa->vertex_size==total_size*4);
|
||||
|
||||
/*
|
||||
* Tell the hardware about the vertex format
|
||||
*/
|
||||
if (nmesa->screen->card->type==NV_10) {
|
||||
int size;
|
||||
|
||||
#define NV_VERTEX_ATTRIBUTE_TYPE_FLOAT 2
|
||||
|
||||
#define NV10_SET_VERTEX_ATTRIB(i,j) \
|
||||
do { \
|
||||
size = attr_size[j] << 4; \
|
||||
size |= (attr_size[j]*4) << 8; \
|
||||
size |= NV_VERTEX_ATTRIBUTE_TYPE_FLOAT; \
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VERTEX_ATTR(i),1); \
|
||||
OUT_RING_CACHE(size); \
|
||||
} while (0)
|
||||
|
||||
NV10_SET_VERTEX_ATTRIB(0, _TNL_ATTRIB_POS);
|
||||
NV10_SET_VERTEX_ATTRIB(1, _TNL_ATTRIB_COLOR0);
|
||||
NV10_SET_VERTEX_ATTRIB(2, _TNL_ATTRIB_COLOR1);
|
||||
NV10_SET_VERTEX_ATTRIB(3, _TNL_ATTRIB_TEX0);
|
||||
NV10_SET_VERTEX_ATTRIB(4, _TNL_ATTRIB_TEX1);
|
||||
NV10_SET_VERTEX_ATTRIB(5, _TNL_ATTRIB_NORMAL);
|
||||
NV10_SET_VERTEX_ATTRIB(6, _TNL_ATTRIB_WEIGHT);
|
||||
NV10_SET_VERTEX_ATTRIB(7, _TNL_ATTRIB_FOG);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_VALIDATE,1);
|
||||
OUT_RING_CACHE(0);
|
||||
} else if (nmesa->screen->card->type==NV_20) {
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
int size=attr_size[i];
|
||||
BEGIN_RING_CACHE(NvSub3D,NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR(i),1);
|
||||
OUT_RING_CACHE(NV_VERTEX_ATTRIBUTE_TYPE_FLOAT|(size*0x10));
|
||||
}
|
||||
} else {
|
||||
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DO_VERTICES, 1);
|
||||
OUT_RING(0);
|
||||
BEGIN_RING_CACHE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR0_POS,slots);
|
||||
for(i=0;i<slots;i++)
|
||||
{
|
||||
int size=attr_size[i];
|
||||
OUT_RING_CACHE(NV_VERTEX_ATTRIBUTE_TYPE_FLOAT|(size*0x10));
|
||||
}
|
||||
// FIXME this is probably not needed
|
||||
BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1);
|
||||
OUT_RING(0);
|
||||
BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1);
|
||||
OUT_RING(0);
|
||||
BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1);
|
||||
OUT_RING(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void nv10ChooseVertexState( GLcontext *ctx )
|
||||
{
|
||||
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
DECLARE_RENDERINPUTS(index);
|
||||
|
||||
RENDERINPUTS_COPY(index, tnl->render_inputs_bitset);
|
||||
if (!RENDERINPUTS_EQUAL(index, nmesa->render_inputs_bitset))
|
||||
{
|
||||
RENDERINPUTS_COPY(nmesa->render_inputs_bitset, index);
|
||||
nv10OutputVertexFormat(nmesa);
|
||||
}
|
||||
|
||||
if (nmesa->screen->card->type >= NV_40) {
|
||||
/* Ensure passthrough shader is being used, and mvp matrix
|
||||
* is up to date
|
||||
*/
|
||||
nvsUpdateShader(ctx, nmesa->passthrough_vp);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_IN_REG, 2);
|
||||
OUT_RING_CACHE (0xff09); /*IN : POS, COL, TC0-7 */
|
||||
OUT_RING_CACHE (0x3fc001); /*OUT: COL, TC0-7, POS implied */
|
||||
|
||||
/* Update texenv shader / user fragprog */
|
||||
nvsUpdateShader(ctx, (nouveauShader*)ctx->FragmentProgram._Current);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* High level hooks for t_vb_render.c */
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
static void nv10RenderStart(GLcontext *ctx)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
if (nmesa->new_state) {
|
||||
nmesa->new_render_state |= nmesa->new_state;
|
||||
}
|
||||
|
||||
if (nmesa->Fallback) {
|
||||
tnl->Driver.Render.Start(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nmesa->new_render_state) {
|
||||
nv10ChooseVertexState(ctx);
|
||||
nv10ChooseRenderState(ctx);
|
||||
nmesa->new_render_state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void nv10RenderFinish(GLcontext *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* System to flush dma and emit state changes based on the rasterized
|
||||
* primitive.
|
||||
*/
|
||||
void nv10RasterPrimitive(GLcontext *ctx,
|
||||
GLenum glprim,
|
||||
GLuint hwprim)
|
||||
{
|
||||
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
assert (!nmesa->new_state);
|
||||
|
||||
if (hwprim != nmesa->current_primitive)
|
||||
{
|
||||
nmesa->current_primitive=hwprim;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static const GLuint hw_prim[GL_POLYGON+1] = {
|
||||
GL_POINTS+1,
|
||||
GL_LINES+1,
|
||||
GL_LINE_STRIP+1,
|
||||
GL_LINE_LOOP+1,
|
||||
GL_TRIANGLES+1,
|
||||
GL_TRIANGLE_STRIP+1,
|
||||
GL_TRIANGLE_FAN+1,
|
||||
GL_QUADS+1,
|
||||
GL_QUAD_STRIP+1,
|
||||
GL_POLYGON+1
|
||||
};
|
||||
|
||||
/* Callback for mesa:
|
||||
*/
|
||||
static void nv10RenderPrimitive( GLcontext *ctx, GLuint prim )
|
||||
{
|
||||
nv10RasterPrimitive( ctx, prim, hw_prim[prim] );
|
||||
}
|
||||
|
||||
static void nv10ResetLineStipple( GLcontext *ctx )
|
||||
{
|
||||
/* FIXME do something here */
|
||||
WARN_ONCE("Unimplemented nv10ResetLineStipple\n");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* Initialization. */
|
||||
/**********************************************************************/
|
||||
|
||||
void nv10TriInitFunctions(GLcontext *ctx)
|
||||
{
|
||||
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
|
||||
tnl->Driver.RunPipeline = nouveauRunPipeline;
|
||||
tnl->Driver.Render.Start = nv10RenderStart;
|
||||
tnl->Driver.Render.Finish = nv10RenderFinish;
|
||||
tnl->Driver.Render.PrimitiveNotify = nv10RenderPrimitive;
|
||||
tnl->Driver.Render.ResetLineStipple = nv10ResetLineStipple;
|
||||
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
|
||||
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
|
||||
tnl->Driver.Render.Interp = _tnl_interp;
|
||||
|
||||
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
|
||||
64 * sizeof(GLfloat) );
|
||||
|
||||
nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
|
||||
}
|
||||
|
||||
|
||||
40
src/mesa/drivers/dri/nouveau/nv10_swtcl.h
Normal file
40
src/mesa/drivers/dri/nouveau/nv10_swtcl.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Stephane Marchesin
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __NV10_SWTCL_H__
|
||||
#define __NV10_SWTCL_H__
|
||||
|
||||
#include "mtypes.h"
|
||||
|
||||
extern void nv10Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
|
||||
extern void nv10FinishPrimitive(struct nouveau_context *nmesa);
|
||||
extern void nv10TriInitFunctions(GLcontext *ctx);
|
||||
#define FALLBACK( nmesa, bit, mode ) nouveauFallback( nmesa->glCtx, bit, mode )
|
||||
|
||||
#endif /* __NV10_SWTCL_H__ */
|
||||
|
||||
121
src/mesa/drivers/dri/nouveau/nv20_shader.h
Normal file
121
src/mesa/drivers/dri/nouveau/nv20_shader.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/* NV20_TCL_PRIMITIVE_3D_0x0B00 */
|
||||
#define NV20_VP_INST_0B00 0x00000000 /* always 0? */
|
||||
#define NV20_VP_INST0_KNOWN 0
|
||||
|
||||
/* NV20_TCL_PRIMITIVE_3D_0x0B04 */
|
||||
#define NV20_VP_INST_SCA_OPCODE_SHIFT 25
|
||||
#define NV20_VP_INST_SCA_OPCODE_MASK (0x0F << 25)
|
||||
#define NV20_VP_INST_OPCODE_RCP 0x2
|
||||
#define NV20_VP_INST_OPCODE_RCC 0x3
|
||||
#define NV20_VP_INST_OPCODE_RSQ 0x4
|
||||
#define NV20_VP_INST_OPCODE_EXP 0x5
|
||||
#define NV20_VP_INST_OPCODE_LOG 0x6
|
||||
#define NV20_VP_INST_OPCODE_LIT 0x7
|
||||
#define NV20_VP_INST_VEC_OPCODE_SHIFT 21
|
||||
#define NV20_VP_INST_VEC_OPCODE_MASK (0x0F << 21)
|
||||
#define NV20_VP_INST_OPCODE_NOP 0x0 /* guess */
|
||||
#define NV20_VP_INST_OPCODE_MOV 0x1
|
||||
#define NV20_VP_INST_OPCODE_MUL 0x2
|
||||
#define NV20_VP_INST_OPCODE_ADD 0x3
|
||||
#define NV20_VP_INST_OPCODE_MAD 0x4
|
||||
#define NV20_VP_INST_OPCODE_DP3 0x5
|
||||
#define NV20_VP_INST_OPCODE_DPH 0x6
|
||||
#define NV20_VP_INST_OPCODE_DP4 0x7
|
||||
#define NV20_VP_INST_OPCODE_DST 0x8
|
||||
#define NV20_VP_INST_OPCODE_MIN 0x9
|
||||
#define NV20_VP_INST_OPCODE_MAX 0xA
|
||||
#define NV20_VP_INST_OPCODE_SLT 0xB
|
||||
#define NV20_VP_INST_OPCODE_SGE 0xC
|
||||
#define NV20_VP_INST_OPCODE_ARL 0xD
|
||||
#define NV20_VP_INST_CONST_SRC_SHIFT 13
|
||||
#define NV20_VP_INST_CONST_SRC_MASK (0xFF << 13)
|
||||
#define NV20_VP_INST_INPUT_SRC_SHIFT 9
|
||||
#define NV20_VP_INST_INPUT_SRC_MASK (0xF << 9) /* guess */
|
||||
#define NV20_VP_INST_INPUT_SRC_POS 0
|
||||
#define NV20_VP_INST_INPUT_SRC_COL0 3
|
||||
#define NV20_VP_INST_INPUT_SRC_COL1 4
|
||||
#define NV20_VP_INST_INPUT_SRC_TC(n) (9+n)
|
||||
#define NV20_VP_INST_SRC0H_SHIFT 0
|
||||
#define NV20_VP_INST_SRC0H_MASK (0x1FF << 0)
|
||||
#define NV20_VP_INST1_KNOWN ( \
|
||||
NV20_VP_INST_OPCODE_MASK | \
|
||||
NV20_VP_INST_CONST_SRC_MASK | \
|
||||
NV20_VP_INST_INPUT_SRC_MASK | \
|
||||
NV20_VP_INST_SRC0H_MASK \
|
||||
)
|
||||
|
||||
/* NV20_TCL_PRIMITIVE_3D_0x0B08 */
|
||||
#define NV20_VP_INST_SRC0L_SHIFT 26
|
||||
#define NV20_VP_INST_SRC0L_MASK (0x3F <<26)
|
||||
#define NV20_VP_INST_SRC1_SHIFT 11
|
||||
#define NV20_VP_INST_SRC1_MASK (0x7FFF<<11)
|
||||
#define NV20_VP_INST_SRC2H_SHIFT 0
|
||||
#define NV20_VP_INST_SRC2H_MASK (0x7FF << 0)
|
||||
|
||||
/* NV20_TCL_PRIMITIVE_3D_0x0B0C */
|
||||
#define NV20_VP_INST_SRC2L_SHIFT 28
|
||||
#define NV20_VP_INST_SRC2L_MASK (0x0F <<28)
|
||||
#define NV20_VP_INST_VTEMP_WRITEMASK_SHIFT 24
|
||||
#define NV20_VP_INST_VTEMP_WRITEMASK_MASK (0x0F <<24)
|
||||
# define NV20_VP_INST_TEMP_WRITEMASK_X (1<<27)
|
||||
# define NV20_VP_INST_TEMP_WRITEMASK_Y (1<<26)
|
||||
# define NV20_VP_INST_TEMP_WRITEMASK_Z (1<<25)
|
||||
# define NV20_VP_INST_TEMP_WRITEMASK_W (1<<24)
|
||||
#define NV20_VP_INST_DEST_TEMP_ID_SHIFT 20
|
||||
#define NV20_VP_INST_DEST_TEMP_ID_MASK (0x0F <<20)
|
||||
#define NV20_VP_INST_STEMP_WRITEMASK_SHIFT 16
|
||||
#define NV20_VP_INST_STEMP_WRITEMASK_MASK (0x0F <<16)
|
||||
# define NV20_VP_INST_STEMP_WRITEMASK_X (1<<19)
|
||||
# define NV20_VP_INST_STEMP_WRITEMASK_Y (1<<18)
|
||||
# define NV20_VP_INST_STEMP_WRITEMASK_Z (1<<17)
|
||||
# define NV20_VP_INST_STEMP_WRITEMASK_W (1<<16)
|
||||
#define NV20_VP_INST_DEST_WRITEMASK_SHIFT 12
|
||||
#define NV20_VP_INST_DEST_WRITEMASK_MASK (0x0F <<12)
|
||||
# define NV20_VP_INST_DEST_WRITEMASK_X (1<<15)
|
||||
# define NV20_VP_INST_DEST_WRITEMASK_Y (1<<14)
|
||||
# define NV20_VP_INST_DEST_WRITEMASK_Z (1<<13)
|
||||
# define NV20_VP_INST_DEST_WRITEMASK_W (1<<12)
|
||||
#define NV20_VP_INST_DEST_SHIFT 3
|
||||
#define NV20_VP_INST_DEST_MASK (0xF << 3) /* guess */
|
||||
#define NV20_VP_INST_DEST_POS 0
|
||||
#define NV20_VP_INST_DEST_COL0 3
|
||||
#define NV20_VP_INST_DEST_COL1 4
|
||||
#define NV20_VP_INST_DEST_TC(n) (9+n)
|
||||
#define NV20_VP_INST_INDEX_CONST (1<<1)
|
||||
#define NV20_VP_INST3_KNOWN ( \
|
||||
NV20_VP_INST_SRC2L_MASK | \
|
||||
NV20_VP_INST_TEMP_WRITEMASK_MASK | \
|
||||
NV20_VP_INST_DEST_TEMP_ID_MASK | \
|
||||
NV20_VP_INST_STEMP_WRITEMASK_MASK | \
|
||||
NV20_VP_INST_DEST_WRITEMASK_MASK | \
|
||||
NV20_VP_INST_DEST_MASK | \
|
||||
NV20_VP_INST_INDEX_CONST \
|
||||
)
|
||||
|
||||
/* Useful to split the source selection regs into their pieces */
|
||||
#define NV20_VP_SRC0_HIGH_SHIFT 6
|
||||
#define NV20_VP_SRC0_HIGH_MASK 0x00007FC0
|
||||
#define NV20_VP_SRC0_LOW_MASK 0x0000003F
|
||||
#define NV20_VP_SRC2_HIGH_SHIFT 4
|
||||
#define NV20_VP_SRC2_HIGH_MASK 0x00007FF0
|
||||
#define NV20_VP_SRC2_LOW_MASK 0x0000000F
|
||||
|
||||
#define NV20_VP_SRC_REG_NEGATE (1<<14)
|
||||
#define NV20_VP_SRC_REG_SWZ_X_SHIFT 12
|
||||
#define NV20_VP_SRC_REG_SWZ_X_MASK (0x03 <<12)
|
||||
#define NV20_VP_SRC_REG_SWZ_Y_SHIFT 10
|
||||
#define NV20_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10)
|
||||
#define NV20_VP_SRC_REG_SWZ_Z_SHIFT 8
|
||||
#define NV20_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8)
|
||||
#define NV20_VP_SRC_REG_SWZ_W_SHIFT 6
|
||||
#define NV20_VP_SRC_REG_SWZ_W_MASK (0x03 << 6)
|
||||
#define NV20_VP_SRC_REG_SWZ_ALL_SHIFT 6
|
||||
#define NV20_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6)
|
||||
#define NV20_VP_SRC_REG_TEMP_ID_SHIFT 2
|
||||
#define NV20_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0)
|
||||
#define NV20_VP_SRC_REG_TYPE_SHIFT 0
|
||||
#define NV20_VP_SRC_REG_TYPE_MASK (0x03 << 0)
|
||||
#define NV20_VP_SRC_REG_TYPE_TEMP 1
|
||||
#define NV20_VP_SRC_REG_TYPE_INPUT 2
|
||||
#define NV20_VP_SRC_REG_TYPE_CONST 3 /* guess */
|
||||
|
||||
659
src/mesa/drivers/dri/nouveau/nv20_state.c
Normal file
659
src/mesa/drivers/dri/nouveau/nv20_state.c
Normal file
|
|
@ -0,0 +1,659 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Nouveau
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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_context.h"
|
||||
#include "nouveau_object.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_reg.h"
|
||||
|
||||
#include "tnl/t_pipeline.h"
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "colormac.h"
|
||||
|
||||
static void nv20AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte ubRef;
|
||||
CLAMPED_FLOAT_TO_UBYTE(ubRef, ref);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
|
||||
OUT_RING_CACHE(func); /* NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC */
|
||||
OUT_RING_CACHE(ubRef); /* NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF */
|
||||
}
|
||||
|
||||
static void nv20BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte cf[4];
|
||||
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_COLOR, 1);
|
||||
OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0]));
|
||||
}
|
||||
|
||||
static void nv20BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1);
|
||||
OUT_RING_CACHE((modeA<<16) | modeRGB);
|
||||
}
|
||||
|
||||
|
||||
static void nv20BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
|
||||
GLenum sfactorA, GLenum dfactorA)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
|
||||
OUT_RING_CACHE((sfactorA<<16) | sfactorRGB);
|
||||
OUT_RING_CACHE((dfactorA<<16) | dfactorRGB);
|
||||
}
|
||||
|
||||
static void nv20ClearColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte c[4];
|
||||
UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB, 1);
|
||||
OUT_RING_CACHE(PACK_COLOR_8888(c[3],c[0],c[1],c[2]));
|
||||
}
|
||||
|
||||
static void nv20ClearDepth(GLcontext *ctx, GLclampd d)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
nmesa->clear_value=((nmesa->clear_value&0x000000FF)|(((uint32_t)(d*0xFFFFFF))<<8));
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
|
||||
OUT_RING_CACHE(nmesa->clear_value);
|
||||
}
|
||||
|
||||
/* we're don't support indexed buffers
|
||||
void (*ClearIndex)(GLcontext *ctx, GLuint index)
|
||||
*/
|
||||
|
||||
static void nv20ClearStencil(GLcontext *ctx, GLint s)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
nmesa->clear_value=((nmesa->clear_value&0xFFFFFF00)|(s&0x000000FF));
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
|
||||
OUT_RING_CACHE(nmesa->clear_value);
|
||||
}
|
||||
|
||||
static void nv20ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4);
|
||||
OUT_RING_CACHEf(equation[0]);
|
||||
OUT_RING_CACHEf(equation[1]);
|
||||
OUT_RING_CACHEf(equation[2]);
|
||||
OUT_RING_CACHEf(equation[3]);
|
||||
}
|
||||
|
||||
static void nv20ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
|
||||
GLboolean bmask, GLboolean amask )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
|
||||
OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0));
|
||||
}
|
||||
|
||||
static void nv20ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
|
||||
{
|
||||
// TODO I need love
|
||||
}
|
||||
|
||||
static void nv20CullFace(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CULL_FACE, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
static void nv20FrontFace(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FRONT_FACE, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
static void nv20DepthFunc(GLcontext *ctx, GLenum func)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
|
||||
OUT_RING_CACHE(func);
|
||||
}
|
||||
|
||||
static void nv20DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
|
||||
OUT_RING_CACHE(flag);
|
||||
}
|
||||
|
||||
static void nv20DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
|
||||
OUT_RING_CACHEf(nearval);
|
||||
OUT_RING_CACHEf(farval);
|
||||
}
|
||||
|
||||
/** Specify the current buffer for writing */
|
||||
//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer );
|
||||
/** Specify the buffers for writing for fragment programs*/
|
||||
//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers );
|
||||
|
||||
static void nv20Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
switch(cap)
|
||||
{
|
||||
case GL_ALPHA_TEST:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_AUTO_NORMAL:
|
||||
case GL_BLEND:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_CLIP_PLANE0:
|
||||
case GL_CLIP_PLANE1:
|
||||
case GL_CLIP_PLANE2:
|
||||
case GL_CLIP_PLANE3:
|
||||
case GL_CLIP_PLANE4:
|
||||
case GL_CLIP_PLANE5:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_COLOR_LOGIC_OP:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_COLOR_MATERIAL:
|
||||
// case GL_COLOR_SUM_EXT:
|
||||
// case GL_COLOR_TABLE:
|
||||
// case GL_CONVOLUTION_1D:
|
||||
// case GL_CONVOLUTION_2D:
|
||||
case GL_CULL_FACE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_DEPTH_TEST:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_DITHER:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_FOG:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_HISTOGRAM:
|
||||
// case GL_INDEX_LOGIC_OP:
|
||||
case GL_LIGHT0:
|
||||
case GL_LIGHT1:
|
||||
case GL_LIGHT2:
|
||||
case GL_LIGHT3:
|
||||
case GL_LIGHT4:
|
||||
case GL_LIGHT5:
|
||||
case GL_LIGHT6:
|
||||
case GL_LIGHT7:
|
||||
{
|
||||
uint32_t mask=0x11<<(2*(cap-GL_LIGHT0));
|
||||
nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state));
|
||||
if (nmesa->lighting_enabled)
|
||||
{
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
|
||||
OUT_RING_CACHE(nmesa->enabled_lights);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GL_LIGHTING:
|
||||
nmesa->lighting_enabled=state;
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
|
||||
if (nmesa->lighting_enabled)
|
||||
OUT_RING_CACHE(nmesa->enabled_lights);
|
||||
else
|
||||
OUT_RING_CACHE(0x0);
|
||||
break;
|
||||
case GL_LINE_SMOOTH:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_LINE_STIPPLE:
|
||||
// case GL_MAP1_COLOR_4:
|
||||
// case GL_MAP1_INDEX:
|
||||
// case GL_MAP1_NORMAL:
|
||||
// case GL_MAP1_TEXTURE_COORD_1:
|
||||
// case GL_MAP1_TEXTURE_COORD_2:
|
||||
// case GL_MAP1_TEXTURE_COORD_3:
|
||||
// case GL_MAP1_TEXTURE_COORD_4:
|
||||
// case GL_MAP1_VERTEX_3:
|
||||
// case GL_MAP1_VERTEX_4:
|
||||
// case GL_MAP2_COLOR_4:
|
||||
// case GL_MAP2_INDEX:
|
||||
// case GL_MAP2_NORMAL:
|
||||
// case GL_MAP2_TEXTURE_COORD_1:
|
||||
// case GL_MAP2_TEXTURE_COORD_2:
|
||||
// case GL_MAP2_TEXTURE_COORD_3:
|
||||
// case GL_MAP2_TEXTURE_COORD_4:
|
||||
// case GL_MAP2_VERTEX_3:
|
||||
// case GL_MAP2_VERTEX_4:
|
||||
// case GL_MINMAX:
|
||||
case GL_NORMALIZE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_POINT_SMOOTH:
|
||||
case GL_POLYGON_OFFSET_POINT:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_OFFSET_LINE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_OFFSET_FILL:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_SMOOTH:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_STIPPLE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_POST_COLOR_MATRIX_COLOR_TABLE:
|
||||
// case GL_POST_CONVOLUTION_COLOR_TABLE:
|
||||
// case GL_RESCALE_NORMAL:
|
||||
// case GL_SCISSOR_TEST:
|
||||
// case GL_SEPARABLE_2D:
|
||||
case GL_STENCIL_TEST:
|
||||
// TODO BACK and FRONT ?
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_TEXTURE_GEN_Q:
|
||||
// case GL_TEXTURE_GEN_R:
|
||||
// case GL_TEXTURE_GEN_S:
|
||||
// case GL_TEXTURE_GEN_T:
|
||||
// case GL_TEXTURE_1D:
|
||||
// case GL_TEXTURE_2D:
|
||||
// case GL_TEXTURE_3D:
|
||||
}
|
||||
}
|
||||
|
||||
static void nv20Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
switch(pname)
|
||||
{
|
||||
case GL_FOG_MODE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FOG_MODE, 1);
|
||||
//OUT_RING_CACHE (params);
|
||||
break;
|
||||
/* TODO: unsure about the rest.*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void nv20Hint(GLcontext *ctx, GLenum target, GLenum mode)
|
||||
{
|
||||
// TODO I need love (fog and line_smooth hints)
|
||||
}
|
||||
|
||||
// void (*IndexMask)(GLcontext *ctx, GLuint mask);
|
||||
|
||||
enum {
|
||||
SPOTLIGHT_UPDATE_EXPONENT,
|
||||
SPOTLIGHT_UPDATE_DIRECTION,
|
||||
SPOTLIGHT_UPDATE_ALL
|
||||
};
|
||||
|
||||
static void nv20Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLint p = light - GL_LIGHT0;
|
||||
struct gl_light *l = &ctx->Light.Light[p];
|
||||
int spotlightUpdate = -1;
|
||||
|
||||
/* not sure where the fourth param value goes...*/
|
||||
switch(pname)
|
||||
{
|
||||
case GL_AMBIENT:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_DIFFUSE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_SPECULAR:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_POSITION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_SPOT_DIRECTION:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_DIRECTION;
|
||||
break;
|
||||
case GL_SPOT_EXPONENT:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_EXPONENT;
|
||||
break;
|
||||
case GL_SPOT_CUTOFF:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_ALL;
|
||||
break;
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(spotlightUpdate) {
|
||||
case SPOTLIGHT_UPDATE_DIRECTION:
|
||||
{
|
||||
GLfloat x,y,z;
|
||||
x = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[0];
|
||||
y = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[1];
|
||||
z = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[2];
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3);
|
||||
OUT_RING_CACHEf(x);
|
||||
OUT_RING_CACHEf(y);
|
||||
OUT_RING_CACHEf(z);
|
||||
}
|
||||
break;
|
||||
case SPOTLIGHT_UPDATE_EXPONENT:
|
||||
{
|
||||
GLfloat cc,lc,qc;
|
||||
cc = 1.0; /* FIXME: These need to be correctly computed */
|
||||
lc = 0.0;
|
||||
qc = 2.0;
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3);
|
||||
OUT_RING_CACHEf(cc);
|
||||
OUT_RING_CACHEf(lc);
|
||||
OUT_RING_CACHEf(qc);
|
||||
}
|
||||
break;
|
||||
case SPOTLIGHT_UPDATE_ALL:
|
||||
{
|
||||
GLfloat cc,lc,qc, x,y,z, c;
|
||||
cc = 1.0; /* FIXME: These need to be correctly computed */
|
||||
lc = 0.0;
|
||||
qc = 2.0;
|
||||
x = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[0];
|
||||
y = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[1];
|
||||
z = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[2];
|
||||
c = -2.0 * (0.5 + l->_CosCutoff);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7);
|
||||
OUT_RING_CACHEf(cc);
|
||||
OUT_RING_CACHEf(lc);
|
||||
OUT_RING_CACHEf(qc);
|
||||
OUT_RING_CACHEf(x);
|
||||
OUT_RING_CACHEf(y);
|
||||
OUT_RING_CACHEf(z);
|
||||
OUT_RING_CACHEf(c);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the lighting model parameters */
|
||||
static void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
|
||||
|
||||
|
||||
static void nv20LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
|
||||
{
|
||||
/* nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1);
|
||||
OUT_RING_CACHE((pattern << 16) | factor);*/
|
||||
}
|
||||
|
||||
static void nv20LineWidth(GLcontext *ctx, GLfloat width)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_WIDTH, 1);
|
||||
OUT_RING_CACHEf(width);
|
||||
}
|
||||
|
||||
static void nv20LogicOpcode(GLcontext *ctx, GLenum opcode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1);
|
||||
OUT_RING_CACHE(opcode);
|
||||
}
|
||||
|
||||
static void nv20PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
|
||||
{
|
||||
/*TODO: not sure what goes here. */
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
}
|
||||
|
||||
/** Specify the diameter of rasterized points */
|
||||
static void nv20PointSize(GLcontext *ctx, GLfloat size)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
|
||||
OUT_RING_CACHEf(size);
|
||||
}
|
||||
|
||||
/** Select a polygon rasterization mode */
|
||||
static void nv20PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the scale and units used to calculate depth values */
|
||||
void (*PolygonOffset)(GLcontext *ctx, GLfloat factor, GLfloat units);
|
||||
/** Set the polygon stippling pattern */
|
||||
void (*PolygonStipple)(GLcontext *ctx, const GLubyte *mask );
|
||||
/* Specifies the current buffer for reading */
|
||||
void (*ReadBuffer)( GLcontext *ctx, GLenum buffer );
|
||||
/** Set rasterization mode */
|
||||
void (*RenderMode)(GLcontext *ctx, GLenum mode );
|
||||
|
||||
/** Define the scissor box */
|
||||
static void nv20Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
|
||||
{
|
||||
}
|
||||
|
||||
/** Select flat or smooth shading */
|
||||
static void nv20ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilFunc */
|
||||
static void nv20StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
|
||||
GLint ref, GLuint mask)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC, 3);
|
||||
OUT_RING_CACHE(func);
|
||||
OUT_RING_CACHE(ref);
|
||||
OUT_RING_CACHE(mask);
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilMask */
|
||||
static void nv20StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_MASK, 1);
|
||||
OUT_RING_CACHE(mask);
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilOp */
|
||||
static void nv20StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
|
||||
GLenum zfail, GLenum zpass)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL, 1);
|
||||
OUT_RING_CACHE(fail);
|
||||
OUT_RING_CACHE(zfail);
|
||||
OUT_RING_CACHE(zpass);
|
||||
}
|
||||
|
||||
/** Control the generation of texture coordinates */
|
||||
void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname,
|
||||
const GLfloat *params);
|
||||
/** Set texture environment parameters */
|
||||
void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname,
|
||||
const GLfloat *param);
|
||||
/** Set texture parameters */
|
||||
void (*TexParameter)(GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj,
|
||||
GLenum pname, const GLfloat *params);
|
||||
void (*TextureMatrix)(GLcontext *ctx, GLuint unit, const GLmatrix *mat);
|
||||
|
||||
/** Set the viewport */
|
||||
static void nv20Viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
|
||||
{
|
||||
/* TODO: Where do the VIEWPORT_XFRM_* regs come in? */
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
|
||||
OUT_RING_CACHE((w << 16) | x);
|
||||
OUT_RING_CACHE((h << 16) | y);
|
||||
}
|
||||
|
||||
/* Initialise any card-specific non-GL related state */
|
||||
static GLboolean nv20InitCard(nouveauContextPtr nmesa)
|
||||
{
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* Update buffer offset/pitch/format */
|
||||
static GLboolean nv20BindBuffers(nouveauContextPtr nmesa, int num_color,
|
||||
nouveau_renderbuffer **color,
|
||||
nouveau_renderbuffer *depth)
|
||||
{
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* Update anything that depends on the window position/size */
|
||||
static void nv20WindowMoved(nouveauContextPtr nmesa)
|
||||
{
|
||||
}
|
||||
|
||||
void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
nmesa->hw_func.InitCard = nv20InitCard;
|
||||
nmesa->hw_func.BindBuffers = nv20BindBuffers;
|
||||
nmesa->hw_func.WindowMoved = nv20WindowMoved;
|
||||
|
||||
func->AlphaFunc = nv20AlphaFunc;
|
||||
func->BlendColor = nv20BlendColor;
|
||||
func->BlendEquationSeparate = nv20BlendEquationSeparate;
|
||||
func->BlendFuncSeparate = nv20BlendFuncSeparate;
|
||||
func->ClearColor = nv20ClearColor;
|
||||
func->ClearDepth = nv20ClearDepth;
|
||||
func->ClearStencil = nv20ClearStencil;
|
||||
func->ClipPlane = nv20ClipPlane;
|
||||
func->ColorMask = nv20ColorMask;
|
||||
func->ColorMaterial = nv20ColorMaterial;
|
||||
func->CullFace = nv20CullFace;
|
||||
func->FrontFace = nv20FrontFace;
|
||||
func->DepthFunc = nv20DepthFunc;
|
||||
func->DepthMask = nv20DepthMask;
|
||||
func->DepthRange = nv20DepthRange;
|
||||
func->Enable = nv20Enable;
|
||||
func->Fogfv = nv20Fogfv;
|
||||
func->Hint = nv20Hint;
|
||||
func->Lightfv = nv20Lightfv;
|
||||
/* func->LightModelfv = nv20LightModelfv; */
|
||||
func->LineStipple = nv20LineStipple;
|
||||
func->LineWidth = nv20LineWidth;
|
||||
func->LogicOpcode = nv20LogicOpcode;
|
||||
func->PointParameterfv = nv20PointParameterfv;
|
||||
func->PointSize = nv20PointSize;
|
||||
func->PolygonMode = nv20PolygonMode;
|
||||
#if 0
|
||||
func->PolygonOffset = nv20PolygonOffset;
|
||||
func->PolygonStipple = nv20PolygonStipple;
|
||||
func->ReadBuffer = nv20ReadBuffer;
|
||||
func->RenderMode = nv20RenderMode;
|
||||
#endif
|
||||
func->Scissor = nv20Scissor;
|
||||
func->ShadeModel = nv20ShadeModel;
|
||||
func->StencilFuncSeparate = nv20StencilFuncSeparate;
|
||||
func->StencilMaskSeparate = nv20StencilMaskSeparate;
|
||||
func->StencilOpSeparate = nv20StencilOpSeparate;
|
||||
#if 0
|
||||
func->TexGen = nv20TexGen;
|
||||
func->TexParameter = nv20TexParameter;
|
||||
func->TextureMatrix = nv20TextureMatrix;
|
||||
#endif
|
||||
func->Viewport = nv20Viewport;
|
||||
}
|
||||
|
||||
447
src/mesa/drivers/dri/nouveau/nv20_vertprog.c
Normal file
447
src/mesa/drivers/dri/nouveau/nv20_vertprog.c
Normal file
|
|
@ -0,0 +1,447 @@
|
|||
#include "nouveau_context.h"
|
||||
#include "nouveau_object.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_reg.h"
|
||||
|
||||
#include "nouveau_shader.h"
|
||||
#include "nv20_shader.h"
|
||||
|
||||
unsigned int NVVP_TX_VOP_COUNT = 16;
|
||||
unsigned int NVVP_TX_NVS_OP_COUNT = 16;
|
||||
struct _op_xlat NVVP_TX_VOP[32];
|
||||
struct _op_xlat NVVP_TX_SOP[32];
|
||||
|
||||
nvsSwzComp NV20VP_TX_SWIZZLE[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
|
||||
|
||||
/*****************************************************************************
|
||||
* Support routines
|
||||
*/
|
||||
static void
|
||||
NV20VPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
int i;
|
||||
|
||||
/* XXX: missing a way to say what insn we're uploading from, and possible
|
||||
* the program start position (if NV20 has one) */
|
||||
for (i=0; i<nvs->program_size; i+=4) {
|
||||
BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, 4);
|
||||
OUT_RING(nvs->program[i + 0]);
|
||||
OUT_RING(nvs->program[i + 1]);
|
||||
OUT_RING(nvs->program[i + 2]);
|
||||
OUT_RING(nvs->program[i + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV20VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
/* Worth checking if the value *actually* changed? Mesa doesn't tell us this
|
||||
* as far as I know..
|
||||
*/
|
||||
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID, 1);
|
||||
OUT_RING (id);
|
||||
BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_X, 4);
|
||||
OUT_RINGf(nvs->params[id].source_val[0]);
|
||||
OUT_RINGf(nvs->params[id].source_val[1]);
|
||||
OUT_RINGf(nvs->params[id].source_val[2]);
|
||||
OUT_RINGf(nvs->params[id].source_val[3]);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Assembly routines
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* Disassembly routines
|
||||
*/
|
||||
void
|
||||
NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz)
|
||||
{
|
||||
swz[NVS_SWZ_X] = NV20VP_TX_SWIZZLE[(hwswz & 0xC0) >> 6];
|
||||
swz[NVS_SWZ_Y] = NV20VP_TX_SWIZZLE[(hwswz & 0x30) >> 4];
|
||||
swz[NVS_SWZ_Z] = NV20VP_TX_SWIZZLE[(hwswz & 0x0C) >> 2];
|
||||
swz[NVS_SWZ_W] = NV20VP_TX_SWIZZLE[(hwswz & 0x03) >> 0];
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPHasMergedInst(nvsFunc * shader)
|
||||
{
|
||||
if (shader->GetOpcodeHW(shader, 0) != NV20_VP_INST_OPCODE_NOP &&
|
||||
shader->GetOpcodeHW(shader, 1) != NV20_VP_INST_OPCODE_NOP)
|
||||
printf
|
||||
("\n\n*****both opcode fields have values - PLEASE REPORT*****\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPIsLastInst(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[3] & (1 << 0)) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPGetOffsetNext(nvsFunc * shader)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
static struct _op_xlat *
|
||||
NV20VPGetOPTXRec(nvsFunc * shader, int merged)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
int op;
|
||||
|
||||
if (shader->GetOpcodeSlot(shader, merged)) {
|
||||
opr = NVVP_TX_SOP;
|
||||
op = shader->GetOpcodeHW(shader, 1);
|
||||
if (op >= NVVP_TX_NVS_OP_COUNT)
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
opr = NVVP_TX_VOP;
|
||||
op = shader->GetOpcodeHW(shader, 0);
|
||||
if (op >= NVVP_TX_VOP_COUNT)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (opr[op].SOP == NVS_OP_UNKNOWN)
|
||||
return NULL;
|
||||
return &opr[op];
|
||||
}
|
||||
|
||||
static struct _op_xlat *
|
||||
NV20VPGetOPTXFromSOP(nvsOpcode sop, int *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<NVVP_TX_VOP_COUNT;i++) {
|
||||
if (NVVP_TX_VOP[i].SOP == sop) {
|
||||
if (id) *id = 0;
|
||||
return &NVVP_TX_VOP[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<NVVP_TX_NVS_OP_COUNT;i++) {
|
||||
if (NVVP_TX_SOP[i].SOP == sop) {
|
||||
if (id) *id = 1;
|
||||
return &NVVP_TX_SOP[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPGetOpcodeSlot(nvsFunc * shader, int merged)
|
||||
{
|
||||
if (shader->HasMergedInst(shader))
|
||||
return merged;
|
||||
if (shader->GetOpcodeHW(shader, 0) == NV20_VP_INST_OPCODE_NOP)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static nvsOpcode
|
||||
NV20VPGetOpcode(nvsFunc * shader, int merged)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr)
|
||||
return NVS_OP_UNKNOWN;
|
||||
|
||||
return opr->SOP;
|
||||
}
|
||||
|
||||
static nvsOpcode
|
||||
NV20VPGetOpcodeHW(nvsFunc * shader, int slot)
|
||||
{
|
||||
if (slot)
|
||||
return (shader->inst[1] & NV20_VP_INST_SCA_OPCODE_MASK)
|
||||
>> NV20_VP_INST_SCA_OPCODE_SHIFT;
|
||||
return (shader->inst[1] & NV20_VP_INST_VEC_OPCODE_MASK)
|
||||
>> NV20_VP_INST_VEC_OPCODE_SHIFT;
|
||||
}
|
||||
|
||||
static nvsRegFile
|
||||
NV20VPGetDestFile(nvsFunc * shader, int merged)
|
||||
{
|
||||
switch (shader->GetOpcode(shader, merged)) {
|
||||
case NVS_OP_ARL:
|
||||
return NVS_FILE_ADDRESS;
|
||||
default:
|
||||
/*FIXME: This probably isn't correct.. */
|
||||
if ((shader->inst[3] & NV20_VP_INST_DEST_WRITEMASK_MASK) == 0)
|
||||
return NVS_FILE_TEMP;
|
||||
return NVS_FILE_RESULT;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV20VPGetDestID(nvsFunc * shader, int merged)
|
||||
{
|
||||
int id;
|
||||
|
||||
switch (shader->GetDestFile(shader, merged)) {
|
||||
case NVS_FILE_RESULT:
|
||||
id = ((shader->inst[3] & NV20_VP_INST_DEST_MASK)
|
||||
>> NV20_VP_INST_DEST_SHIFT);
|
||||
switch (id) {
|
||||
case NV20_VP_INST_DEST_POS : return NVS_FR_POSITION;
|
||||
case NV20_VP_INST_DEST_COL0 : return NVS_FR_COL0;
|
||||
case NV20_VP_INST_DEST_COL1 : return NVS_FR_COL1;
|
||||
case NV20_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0;
|
||||
case NV20_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1;
|
||||
case NV20_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2;
|
||||
case NV20_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
case NVS_FILE_ADDRESS:
|
||||
return 0;
|
||||
case NVS_FILE_TEMP:
|
||||
id = ((shader->inst[3] & NV20_VP_INST_DEST_TEMP_ID_MASK)
|
||||
>> NV20_VP_INST_DEST_TEMP_ID_SHIFT);
|
||||
return id;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV20VPGetDestMask(nvsFunc * shader, int merged)
|
||||
{
|
||||
int hwmask, mask = 0;
|
||||
|
||||
/* Special handling for ARL - hardware only supports a
|
||||
* 1-component address reg
|
||||
*/
|
||||
if (shader->GetOpcode(shader, merged) == NVS_OP_ARL)
|
||||
return SMASK_X;
|
||||
|
||||
if (shader->GetDestFile(shader, merged) == NVS_FILE_RESULT)
|
||||
hwmask = (shader->inst[3] & NV20_VP_INST_DEST_WRITEMASK_MASK)
|
||||
>> NV20_VP_INST_DEST_WRITEMASK_SHIFT;
|
||||
else if (shader->GetOpcodeSlot(shader, merged))
|
||||
hwmask = (shader->inst[3] & NV20_VP_INST_STEMP_WRITEMASK_MASK)
|
||||
>> NV20_VP_INST_STEMP_WRITEMASK_SHIFT;
|
||||
else
|
||||
hwmask = (shader->inst[3] & NV20_VP_INST_VTEMP_WRITEMASK_MASK)
|
||||
>> NV20_VP_INST_VTEMP_WRITEMASK_SHIFT;
|
||||
|
||||
if (hwmask & (1 << 3)) mask |= SMASK_X;
|
||||
if (hwmask & (1 << 2)) mask |= SMASK_Y;
|
||||
if (hwmask & (1 << 1)) mask |= SMASK_Z;
|
||||
if (hwmask & (1 << 0)) mask |= SMASK_W;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV20VPGetSourceHW(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
unsigned int src;
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr)
|
||||
return -1;
|
||||
|
||||
switch (opr->srcpos[pos]) {
|
||||
case 0:
|
||||
src = ((shader->inst[1] & NV20_VP_INST_SRC0H_MASK)
|
||||
>> NV20_VP_INST_SRC0H_SHIFT)
|
||||
<< NV20_VP_SRC0_HIGH_SHIFT;
|
||||
src |= ((shader->inst[2] & NV20_VP_INST_SRC0L_MASK)
|
||||
>> NV20_VP_INST_SRC0L_SHIFT);
|
||||
break;
|
||||
case 1:
|
||||
src = ((shader->inst[2] & NV20_VP_INST_SRC1_MASK)
|
||||
>> NV20_VP_INST_SRC1_SHIFT);
|
||||
break;
|
||||
case 2:
|
||||
src = ((shader->inst[2] & NV20_VP_INST_SRC2H_MASK)
|
||||
>> NV20_VP_INST_SRC2H_SHIFT)
|
||||
<< NV20_VP_SRC2_HIGH_SHIFT;
|
||||
src |= ((shader->inst[3] & NV20_VP_INST_SRC2L_MASK)
|
||||
>> NV20_VP_INST_SRC2L_SHIFT);
|
||||
break;
|
||||
default:
|
||||
src = -1;
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static nvsRegFile
|
||||
NV20VPGetSourceFile(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
unsigned int src;
|
||||
struct _op_xlat *opr;
|
||||
int file;
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr || opr->srcpos[pos] == -1)
|
||||
return -1;
|
||||
|
||||
switch (opr->srcpos[pos]) {
|
||||
case SPOS_ADDRESS:
|
||||
return NVS_FILE_ADDRESS;
|
||||
default:
|
||||
src = NV20VPGetSourceHW(shader, merged, pos);
|
||||
file = (src & NV20_VP_SRC_REG_TYPE_MASK) >> NV20_VP_SRC_REG_TYPE_SHIFT;
|
||||
|
||||
switch (file) {
|
||||
case NV20_VP_SRC_REG_TYPE_TEMP : return NVS_FILE_TEMP;
|
||||
case NV20_VP_SRC_REG_TYPE_INPUT: return NVS_FILE_ATTRIB;
|
||||
case NV20_VP_SRC_REG_TYPE_CONST: return NVS_FILE_CONST;
|
||||
default:
|
||||
return NVS_FILE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPGetSourceID(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
unsigned int src;
|
||||
|
||||
switch (shader->GetSourceFile(shader, merged, pos)) {
|
||||
case NVS_FILE_TEMP:
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
return ((src & NV20_VP_SRC_REG_TEMP_ID_MASK) >>
|
||||
NV20_VP_SRC_REG_TEMP_ID_SHIFT);
|
||||
case NVS_FILE_CONST:
|
||||
return ((shader->inst[1] & NV20_VP_INST_CONST_SRC_MASK)
|
||||
>> NV20_VP_INST_CONST_SRC_SHIFT);
|
||||
case NVS_FILE_ATTRIB:
|
||||
src = ((shader->inst[1] & NV20_VP_INST_INPUT_SRC_MASK)
|
||||
>> NV20_VP_INST_INPUT_SRC_SHIFT);
|
||||
switch (src) {
|
||||
case NV20_VP_INST_INPUT_SRC_POS : return NVS_FR_POSITION;
|
||||
case NV20_VP_INST_INPUT_SRC_COL0 : return NVS_FR_COL0;
|
||||
case NV20_VP_INST_INPUT_SRC_COL1 : return NVS_FR_COL1;
|
||||
case NV20_VP_INST_INPUT_SRC_TC(0): return NVS_FR_TEXCOORD0;
|
||||
case NV20_VP_INST_INPUT_SRC_TC(1): return NVS_FR_TEXCOORD1;
|
||||
case NV20_VP_INST_INPUT_SRC_TC(2): return NVS_FR_TEXCOORD2;
|
||||
case NV20_VP_INST_INPUT_SRC_TC(3): return NVS_FR_TEXCOORD3;
|
||||
default:
|
||||
return NVS_FR_UNKNOWN;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPGetSourceNegate(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
unsigned int src;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
|
||||
return ((src & NV20_VP_SRC_REG_NEGATE) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPGetSourceAbs(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
/* NV20 can't do ABS on sources? Appears to be emulated with
|
||||
* MAX reg, reg, -reg
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
NV20VPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz)
|
||||
{
|
||||
unsigned int src;
|
||||
int swzbits;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
swzbits =
|
||||
(src & NV20_VP_SRC_REG_SWZ_ALL_MASK) >> NV20_VP_SRC_REG_SWZ_ALL_SHIFT;
|
||||
return NV20VPTXSwizzle(swzbits, swz);
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPGetSourceIndexed(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
/* I don't think NV20 can index into attribs, at least no GL
|
||||
* extension is exposed that will allow it.
|
||||
*/
|
||||
if (shader->GetSourceFile(shader, merged, pos) != NVS_FILE_CONST)
|
||||
return 0;
|
||||
if (shader->inst[3] & NV20_VP_INST_INDEX_CONST)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
NV20VPGetAddressRegID(nvsFunc * shader)
|
||||
{
|
||||
/* Only 1 address reg */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static nvsSwzComp
|
||||
NV20VPGetAddressRegSwizzle(nvsFunc * shader)
|
||||
{
|
||||
/* Only A0.x available */
|
||||
return NVS_SWZ_X;
|
||||
}
|
||||
|
||||
void
|
||||
NV20VPInitShaderFuncs(nvsFunc * shader)
|
||||
{
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MOV, NVS_OP_MOV, 0, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MUL, NVS_OP_MUL, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_ADD, NVS_OP_ADD, 0, 2, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MAD, NVS_OP_MAD, 0, 1, 2);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DP3, NVS_OP_DP3, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DPH, NVS_OP_DPH, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DP4, NVS_OP_DP4, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DST, NVS_OP_DST, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MIN, NVS_OP_MIN, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MAX, NVS_OP_MAX, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_SLT, NVS_OP_SLT, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_SGE, NVS_OP_SGE, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_ARL, NVS_OP_ARL, 0, -1, -1);
|
||||
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RCP, NVS_OP_RCP, 2, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RCC, NVS_OP_RCC, 2, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RSQ, NVS_OP_RSQ, 2, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_EXP, NVS_OP_EXP, 2, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_LOG, NVS_OP_LOG, 2, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_LIT, NVS_OP_LIT, 2, -1, -1);
|
||||
|
||||
shader->UploadToHW = NV20VPUploadToHW;
|
||||
shader->UpdateConst = NV20VPUpdateConst;
|
||||
|
||||
shader->GetOPTXRec = NV20VPGetOPTXRec;
|
||||
shader->GetOPTXFromSOP = NV20VPGetOPTXFromSOP;
|
||||
|
||||
shader->HasMergedInst = NV20VPHasMergedInst;
|
||||
shader->IsLastInst = NV20VPIsLastInst;
|
||||
shader->GetOffsetNext = NV20VPGetOffsetNext;
|
||||
shader->GetOpcodeSlot = NV20VPGetOpcodeSlot;
|
||||
shader->GetOpcode = NV20VPGetOpcode;
|
||||
shader->GetOpcodeHW = NV20VPGetOpcodeHW;
|
||||
shader->GetDestFile = NV20VPGetDestFile;
|
||||
shader->GetDestID = NV20VPGetDestID;
|
||||
shader->GetDestMask = NV20VPGetDestMask;
|
||||
shader->GetSourceHW = NV20VPGetSourceHW;
|
||||
shader->GetSourceFile = NV20VPGetSourceFile;
|
||||
shader->GetSourceID = NV20VPGetSourceID;
|
||||
shader->GetSourceNegate = NV20VPGetSourceNegate;
|
||||
shader->GetSourceAbs = NV20VPGetSourceAbs;
|
||||
shader->GetSourceSwizzle = NV20VPGetSourceSwizzle;
|
||||
shader->GetSourceIndexed = NV20VPGetSourceIndexed;
|
||||
shader->GetRelAddressRegID = NV20VPGetAddressRegID;
|
||||
shader->GetRelAddressSwizzle = NV20VPGetAddressRegSwizzle;
|
||||
}
|
||||
718
src/mesa/drivers/dri/nouveau/nv30_fragprog.c
Normal file
718
src/mesa/drivers/dri/nouveau/nv30_fragprog.c
Normal file
|
|
@ -0,0 +1,718 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "glheader.h"
|
||||
#include "macros.h"
|
||||
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_reg.h"
|
||||
#include "nouveau_drm.h"
|
||||
#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;
|
||||
struct _op_xlat NVFP_TX_AOP[64];
|
||||
|
||||
/*******************************************************************************
|
||||
* Support routines
|
||||
*/
|
||||
|
||||
static void
|
||||
NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
drm_nouveau_mem_alloc_t mem;
|
||||
|
||||
if (!nvs->program_buffer) {
|
||||
nouveau_mem *fpbuf;
|
||||
|
||||
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.. */
|
||||
/* not using state cache here, updated programs at the same address
|
||||
* seem to not take effect unless ACTIVE_PROGRAM is called again. hw
|
||||
* caches the program somewhere? so, maybe not so bad to just clobber the
|
||||
* old program in vram..
|
||||
*/
|
||||
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(nouveau_mem_gpu_offset_get(ctx, nvs->program_buffer) | 1);
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
|
||||
{
|
||||
uint32_t *new = nvs->params[id].source_val ?
|
||||
(uint32_t*)nvs->params[id].source_val : (uint32_t*)nvs->params[id].val;
|
||||
uint32_t *current;
|
||||
int i;
|
||||
|
||||
for (i=0; i<nvs->params[id].hw_index_cnt; i++) {
|
||||
current = nvs->program + nvs->params[id].hw_index[i];
|
||||
COPY_4V(current, new);
|
||||
}
|
||||
nvs->on_hardware = 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Assembly helpers
|
||||
*/
|
||||
static struct _op_xlat *
|
||||
NV30FPGetOPTXFromSOP(nvsOpcode op, int *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NVFP_TX_AOP_COUNT; i++) {
|
||||
if (NVFP_TX_AOP[i].SOP == op) {
|
||||
if (id) *id = 0;
|
||||
return &NVFP_TX_AOP[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPSupportsOpcode(nvsFunc *shader, nvsOpcode op)
|
||||
{
|
||||
if (shader->GetOPTXFromSOP(op, NULL))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPSetOpcode(nvsFunc *shader, unsigned int opcode, int slot)
|
||||
{
|
||||
shader->inst[0] &= ~NV30_FP_OP_OPCODE_MASK;
|
||||
shader->inst[0] |= (opcode << NV30_FP_OP_OPCODE_SHIFT);
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPSetCCUpdate(nvsFunc *shader)
|
||||
{
|
||||
shader->inst[0] |= NV30_FP_OP_COND_WRITE_ENABLE;
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPSetCondition(nvsFunc *shader, int on, nvsCond cond, int reg,
|
||||
nvsSwzComp *swz)
|
||||
{
|
||||
nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
|
||||
unsigned int hwcond;
|
||||
|
||||
/* cond masking is always enabled */
|
||||
if (!on) {
|
||||
cond = NVS_COND_TR;
|
||||
reg = 0;
|
||||
swz = default_swz;
|
||||
}
|
||||
|
||||
switch (cond) {
|
||||
case NVS_COND_TR: hwcond = NV30_FP_OP_COND_TR; break;
|
||||
case NVS_COND_FL: hwcond = NV30_FP_OP_COND_FL; break;
|
||||
case NVS_COND_LT: hwcond = NV30_FP_OP_COND_LT; break;
|
||||
case NVS_COND_GT: hwcond = NV30_FP_OP_COND_GT; break;
|
||||
case NVS_COND_LE: hwcond = NV30_FP_OP_COND_LE; break;
|
||||
case NVS_COND_GE: hwcond = NV30_FP_OP_COND_GE; break;
|
||||
case NVS_COND_EQ: hwcond = NV30_FP_OP_COND_EQ; break;
|
||||
case NVS_COND_NE: hwcond = NV30_FP_OP_COND_NE; break;
|
||||
default:
|
||||
WARN_ONCE("unknown fp condmask=%d\n", cond);
|
||||
hwcond = NV30_FP_OP_COND_TR;
|
||||
break;
|
||||
}
|
||||
|
||||
shader->inst[1] &= ~NV30_FP_OP_COND_MASK;
|
||||
shader->inst[1] |= (hwcond << NV30_FP_OP_COND_SHIFT);
|
||||
|
||||
shader->inst[1] &= ~NV30_FP_OP_COND_SWZ_ALL_MASK;
|
||||
shader->inst[1] |= (swz[NVS_SWZ_X] << NV30_FP_OP_COND_SWZ_X_SHIFT);
|
||||
shader->inst[1] |= (swz[NVS_SWZ_Y] << NV30_FP_OP_COND_SWZ_Y_SHIFT);
|
||||
shader->inst[1] |= (swz[NVS_SWZ_Z] << NV30_FP_OP_COND_SWZ_Z_SHIFT);
|
||||
shader->inst[1] |= (swz[NVS_SWZ_W] << NV30_FP_OP_COND_SWZ_W_SHIFT);
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPSetResult(nvsFunc *shader, nvsRegister *reg, unsigned int mask, int slot)
|
||||
{
|
||||
unsigned int hwreg;
|
||||
|
||||
if (mask & SMASK_X) shader->inst[0] |= NV30_FP_OP_OUT_X;
|
||||
if (mask & SMASK_Y) shader->inst[0] |= NV30_FP_OP_OUT_Y;
|
||||
if (mask & SMASK_Z) shader->inst[0] |= NV30_FP_OP_OUT_Z;
|
||||
if (mask & SMASK_W) shader->inst[0] |= NV30_FP_OP_OUT_W;
|
||||
|
||||
if (reg->file == NVS_FILE_RESULT) {
|
||||
hwreg = 0; /* FIXME: this is only fragment.color */
|
||||
/* This is *not* correct, I have no idea what it is either */
|
||||
shader->inst[0] |= NV30_FP_OP_UNK0_7;
|
||||
} else {
|
||||
shader->inst[0] &= ~NV30_FP_OP_UNK0_7;
|
||||
hwreg = reg->index;
|
||||
}
|
||||
shader->inst[0] &= ~NV30_FP_OP_OUT_REG_SHIFT;
|
||||
shader->inst[0] |= (hwreg << NV30_FP_OP_OUT_REG_SHIFT);
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPSetSource(nvsFunc *shader, nvsRegister *reg, int pos)
|
||||
{
|
||||
unsigned int hwsrc = 0;
|
||||
|
||||
switch (reg->file) {
|
||||
case NVS_FILE_TEMP:
|
||||
hwsrc |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT);
|
||||
hwsrc |= (reg->index << NV30_FP_REG_SRC_SHIFT);
|
||||
break;
|
||||
case NVS_FILE_ATTRIB:
|
||||
{
|
||||
unsigned int hwin;
|
||||
|
||||
switch (reg->index) {
|
||||
case NVS_FR_POSITION : hwin = NV30_FP_OP_INPUT_SRC_POSITION; break;
|
||||
case NVS_FR_COL0 : hwin = NV30_FP_OP_INPUT_SRC_COL0; break;
|
||||
case NVS_FR_COL1 : hwin = NV30_FP_OP_INPUT_SRC_COL1; break;
|
||||
case NVS_FR_FOGCOORD : hwin = NV30_FP_OP_INPUT_SRC_FOGC; break;
|
||||
case NVS_FR_TEXCOORD0: hwin = NV30_FP_OP_INPUT_SRC_TC(0); break;
|
||||
case NVS_FR_TEXCOORD1: hwin = NV30_FP_OP_INPUT_SRC_TC(1); break;
|
||||
case NVS_FR_TEXCOORD2: hwin = NV30_FP_OP_INPUT_SRC_TC(2); break;
|
||||
case NVS_FR_TEXCOORD3: hwin = NV30_FP_OP_INPUT_SRC_TC(3); break;
|
||||
case NVS_FR_TEXCOORD4: hwin = NV30_FP_OP_INPUT_SRC_TC(4); break;
|
||||
case NVS_FR_TEXCOORD5: hwin = NV30_FP_OP_INPUT_SRC_TC(5); break;
|
||||
case NVS_FR_TEXCOORD6: hwin = NV30_FP_OP_INPUT_SRC_TC(6); break;
|
||||
case NVS_FR_TEXCOORD7: hwin = NV30_FP_OP_INPUT_SRC_TC(7); break;
|
||||
default:
|
||||
WARN_ONCE("unknown fp input %d\n", reg->index);
|
||||
hwin = NV30_FP_OP_INPUT_SRC_COL0;
|
||||
break;
|
||||
}
|
||||
shader->inst[0] &= ~NV30_FP_OP_INPUT_SRC_MASK;
|
||||
shader->inst[0] |= (hwin << NV30_FP_OP_INPUT_SRC_SHIFT);
|
||||
hwsrc |= (hwin << NV30_FP_REG_SRC_SHIFT);
|
||||
}
|
||||
hwsrc |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT);
|
||||
break;
|
||||
case NVS_FILE_CONST:
|
||||
/* consts are inlined after the inst */
|
||||
hwsrc |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (reg->negate)
|
||||
hwsrc |= NV30_FP_REG_NEGATE;
|
||||
if (reg->abs)
|
||||
shader->inst[1] |= (1 << (29+pos));
|
||||
hwsrc |= (reg->swizzle[NVS_SWZ_X] << NV30_FP_REG_SWZ_X_SHIFT);
|
||||
hwsrc |= (reg->swizzle[NVS_SWZ_Y] << NV30_FP_REG_SWZ_Y_SHIFT);
|
||||
hwsrc |= (reg->swizzle[NVS_SWZ_Z] << NV30_FP_REG_SWZ_Z_SHIFT);
|
||||
hwsrc |= (reg->swizzle[NVS_SWZ_W] << NV30_FP_REG_SWZ_W_SHIFT);
|
||||
|
||||
shader->inst[pos+1] &= ~NV30_FP_REG_ALL_MASK;
|
||||
shader->inst[pos+1] |= hwsrc;
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPSetTexImageUnit(nvsFunc *shader, int unit)
|
||||
{
|
||||
shader->inst[0] &= ~NV30_FP_OP_TEX_UNIT_SHIFT;
|
||||
shader->inst[0] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT);
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPSetSaturate(nvsFunc *shader)
|
||||
{
|
||||
shader->inst[0] |= NV30_FP_OP_OUT_SAT;
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPInitInstruction(nvsFunc *shader)
|
||||
{
|
||||
unsigned int hwsrc;
|
||||
|
||||
shader->inst[0] = 0;
|
||||
|
||||
hwsrc = (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT) |
|
||||
(NVS_SWZ_X << NV30_FP_REG_SWZ_X_SHIFT) |
|
||||
(NVS_SWZ_Y << NV30_FP_REG_SWZ_Y_SHIFT) |
|
||||
(NVS_SWZ_Z << NV30_FP_REG_SWZ_Z_SHIFT) |
|
||||
(NVS_SWZ_W << NV30_FP_REG_SWZ_W_SHIFT);
|
||||
shader->inst[1] = hwsrc;
|
||||
shader->inst[2] = hwsrc;
|
||||
shader->inst[3] = hwsrc;
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPSetLastInst(nvsFunc *shader)
|
||||
{
|
||||
shader->inst[0] |= 1;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Disassembly helpers
|
||||
*/
|
||||
static struct _op_xlat *
|
||||
NV30FPGetOPTXRec(nvsFunc * shader, int merged)
|
||||
{
|
||||
int op;
|
||||
|
||||
op = shader->GetOpcodeHW(shader, 0);
|
||||
if (op > NVFP_TX_AOP_COUNT)
|
||||
return NULL;
|
||||
if (NVFP_TX_AOP[op].SOP == NVS_OP_UNKNOWN)
|
||||
return NULL;
|
||||
return &NVFP_TX_AOP[op];
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPHasMergedInst(nvsFunc * shader)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPIsLastInst(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[0] & NV30_FP_OP_PROGRAM_END) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetOffsetNext(nvsFunc * shader)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
if (shader->GetSourceFile(shader, 0, i) == NVS_FILE_CONST)
|
||||
return 8;
|
||||
return 4;
|
||||
}
|
||||
|
||||
static nvsOpcode
|
||||
NV30FPGetOpcode(nvsFunc * shader, int merged)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr)
|
||||
return NVS_OP_UNKNOWN;
|
||||
|
||||
return opr->SOP;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV30FPGetOpcodeHW(nvsFunc * shader, int slot)
|
||||
{
|
||||
int op;
|
||||
|
||||
op = (shader->inst[0] & NV30_FP_OP_OPCODE_MASK) >> NV30_FP_OP_OPCODE_SHIFT;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
static nvsRegFile
|
||||
NV30FPGetDestFile(nvsFunc * shader, int merged)
|
||||
{
|
||||
/* Result regs overlap temporary regs */
|
||||
return NVS_FILE_TEMP;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV30FPGetDestID(nvsFunc * shader, int merged)
|
||||
{
|
||||
int id;
|
||||
|
||||
switch (shader->GetDestFile(shader, merged)) {
|
||||
case NVS_FILE_TEMP:
|
||||
id = ((shader->inst[0] & NV30_FP_OP_OUT_REG_MASK)
|
||||
>> NV30_FP_OP_OUT_REG_SHIFT);
|
||||
return id;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV30FPGetDestMask(nvsFunc * shader, int merged)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (shader->inst[0] & NV30_FP_OP_OUT_X) mask |= SMASK_X;
|
||||
if (shader->inst[0] & NV30_FP_OP_OUT_Y) mask |= SMASK_Y;
|
||||
if (shader->inst[0] & NV30_FP_OP_OUT_Z) mask |= SMASK_Z;
|
||||
if (shader->inst[0] & NV30_FP_OP_OUT_W) mask |= SMASK_W;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV30FPGetSourceHW(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr || opr->srcpos[pos] == -1)
|
||||
return -1;
|
||||
|
||||
return shader->inst[opr->srcpos[pos] + 1];
|
||||
}
|
||||
|
||||
static nvsRegFile
|
||||
NV30FPGetSourceFile(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
unsigned int src;
|
||||
struct _op_xlat *opr;
|
||||
int file;
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr || opr->srcpos[pos] == -1)
|
||||
return NVS_FILE_UNKNOWN;
|
||||
|
||||
switch (opr->srcpos[pos]) {
|
||||
case SPOS_ADDRESS: return NVS_FILE_ADDRESS;
|
||||
default:
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
file = (src & NV30_FP_REG_TYPE_MASK) >> NV30_FP_REG_TYPE_SHIFT;
|
||||
|
||||
switch (file) {
|
||||
case NV30_FP_REG_TYPE_TEMP : return NVS_FILE_TEMP;
|
||||
case NV30_FP_REG_TYPE_INPUT: return NVS_FILE_ATTRIB;
|
||||
case NV30_FP_REG_TYPE_CONST: return NVS_FILE_CONST;
|
||||
default:
|
||||
return NVS_FILE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetSourceID(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
switch (shader->GetSourceFile(shader, merged, pos)) {
|
||||
case NVS_FILE_ATTRIB:
|
||||
switch ((shader->inst[0] & NV30_FP_OP_INPUT_SRC_MASK)
|
||||
>> NV30_FP_OP_INPUT_SRC_SHIFT) {
|
||||
case NV30_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION;
|
||||
case NV30_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0;
|
||||
case NV30_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1;
|
||||
case NV30_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD;
|
||||
case NV30_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0;
|
||||
case NV30_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1;
|
||||
case NV30_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2;
|
||||
case NV30_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3;
|
||||
case NV30_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4;
|
||||
case NV30_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5;
|
||||
case NV30_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6;
|
||||
case NV30_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case NVS_FILE_TEMP:
|
||||
{
|
||||
unsigned int src;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
return ((src & NV30_FP_REG_SRC_MASK) >> NV30_FP_REG_SRC_SHIFT);
|
||||
}
|
||||
case NVS_FILE_CONST: /* inlined into fragprog */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetTexImageUnit(nvsFunc *shader)
|
||||
{
|
||||
return ((shader->inst[0] & NV30_FP_OP_TEX_UNIT_MASK)
|
||||
>> NV30_FP_OP_TEX_UNIT_SHIFT);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetSourceNegate(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
unsigned int src;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
|
||||
if (src == -1)
|
||||
return -1;
|
||||
return ((src & NV30_FP_REG_NEGATE) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetSourceAbs(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
static unsigned int abspos[3] = {
|
||||
NV30_FP_OP_OUT_ABS,
|
||||
(1 << 30), /* guess */
|
||||
(1 << 31) /* guess */
|
||||
};
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr || opr->srcpos[pos] == -1)
|
||||
return -1;
|
||||
|
||||
return ((shader->inst[1] & abspos[opr->srcpos[pos]]) ? 1 : 0);
|
||||
}
|
||||
|
||||
nvsSwzComp NV30FP_TX_SWIZZLE[4] = {NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
|
||||
|
||||
static void
|
||||
NV30FPTXSwizzle(int hwswz, nvsSwzComp *swz)
|
||||
{
|
||||
swz[NVS_SWZ_W] = NV30FP_TX_SWIZZLE[(hwswz & 0xC0) >> 6];
|
||||
swz[NVS_SWZ_Z] = NV30FP_TX_SWIZZLE[(hwswz & 0x30) >> 4];
|
||||
swz[NVS_SWZ_Y] = NV30FP_TX_SWIZZLE[(hwswz & 0x0C) >> 2];
|
||||
swz[NVS_SWZ_X] = NV30FP_TX_SWIZZLE[(hwswz & 0x03) >> 0];
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz)
|
||||
{
|
||||
unsigned int src;
|
||||
int swzbits;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
swzbits = (src & NV30_FP_REG_SWZ_ALL_MASK) >> NV30_FP_REG_SWZ_ALL_SHIFT;
|
||||
NV30FPTXSwizzle(swzbits, swz);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetSourceIndexed(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
switch (shader->GetSourceFile(shader, merged, pos)) {
|
||||
case NVS_FILE_ATTRIB:
|
||||
return ((shader->inst[3] & NV30_FP_OP_INDEX_INPUT) ? 1 : 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPGetSourceConstVal(nvsFunc * shader, int merged, int pos, float *val)
|
||||
{
|
||||
val[0] = *(float *) &(shader->inst[4]);
|
||||
val[1] = *(float *) &(shader->inst[5]);
|
||||
val[2] = *(float *) &(shader->inst[6]);
|
||||
val[3] = *(float *) &(shader->inst[7]);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetSourceScale(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
/*FIXME: is this per-source, only for a specific source, or all sources??*/
|
||||
return (1 << ((shader->inst[2] & NV30_FP_OP_SRC_SCALE_MASK)
|
||||
>> NV30_FP_OP_SRC_SCALE_SHIFT));
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetAddressRegID(nvsFunc * shader)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static nvsSwzComp
|
||||
NV30FPGetAddressRegSwizzle(nvsFunc * shader)
|
||||
{
|
||||
return NVS_SWZ_X;
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPSupportsConditional(nvsFunc * shader)
|
||||
{
|
||||
/*FIXME: Is this true of all ops? */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetConditionUpdate(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[0] & NV30_FP_OP_COND_WRITE_ENABLE) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetConditionTest(nvsFunc * shader)
|
||||
{
|
||||
/*FIXME: always? */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static nvsCond
|
||||
NV30FPGetCondition(nvsFunc * shader)
|
||||
{
|
||||
int cond;
|
||||
|
||||
cond = ((shader->inst[1] & NV30_FP_OP_COND_MASK)
|
||||
>> NV30_FP_OP_COND_SHIFT);
|
||||
|
||||
switch (cond) {
|
||||
case NV30_FP_OP_COND_FL: return NVS_COND_FL;
|
||||
case NV30_FP_OP_COND_LT: return NVS_COND_LT;
|
||||
case NV30_FP_OP_COND_EQ: return NVS_COND_EQ;
|
||||
case NV30_FP_OP_COND_LE: return NVS_COND_LE;
|
||||
case NV30_FP_OP_COND_GT: return NVS_COND_GT;
|
||||
case NV30_FP_OP_COND_NE: return NVS_COND_NE;
|
||||
case NV30_FP_OP_COND_GE: return NVS_COND_GE;
|
||||
case NV30_FP_OP_COND_TR: return NVS_COND_TR;
|
||||
default:
|
||||
return NVS_COND_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV30FPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
|
||||
{
|
||||
int swzbits;
|
||||
|
||||
swzbits = (shader->inst[1] & NV30_FP_OP_COND_SWZ_ALL_MASK)
|
||||
>> NV30_FP_OP_COND_SWZ_ALL_SHIFT;
|
||||
NV30FPTXSwizzle(swzbits, swz);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetCondRegID(nvsFunc * shader)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static nvsPrecision
|
||||
NV30FPGetPrecision(nvsFunc * shader)
|
||||
{
|
||||
int p;
|
||||
|
||||
p = (shader->inst[0] & NV30_FP_OP_PRECISION_MASK)
|
||||
>> NV30_FP_OP_PRECISION_SHIFT;
|
||||
|
||||
switch (p) {
|
||||
case NV30_FP_PRECISION_FP32: return NVS_PREC_FLOAT32;
|
||||
case NV30_FP_PRECISION_FP16: return NVS_PREC_FLOAT16;
|
||||
case NV30_FP_PRECISION_FX12: return NVS_PREC_FIXED12;
|
||||
default:
|
||||
return NVS_PREC_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV30FPGetSaturate(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[0] & NV30_FP_OP_OUT_SAT) ? 1 : 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Init
|
||||
*/
|
||||
void
|
||||
NV30FPInitShaderFuncs(nvsFunc * shader)
|
||||
{
|
||||
/* These are probably bogus, I made them up... */
|
||||
shader->MaxInst = 1024;
|
||||
shader->MaxAttrib = 16;
|
||||
shader->MaxTemp = 32;
|
||||
shader->MaxAddress = 1;
|
||||
shader->MaxConst = 256;
|
||||
shader->caps = SCAP_SRC_ABS;
|
||||
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MOV, NVS_OP_MOV, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MUL, NVS_OP_MUL, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_ADD, NVS_OP_ADD, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MAD, NVS_OP_MAD, 0, 1, 2);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DP3, NVS_OP_DP3, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DP4, NVS_OP_DP4, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DST, NVS_OP_DST, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MIN, NVS_OP_MIN, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MAX, NVS_OP_MAX, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SLT, NVS_OP_SLT, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SGE, NVS_OP_SGE, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_FRC, NVS_OP_FRC, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_FLR, NVS_OP_FLR, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TEX, NVS_OP_TEX, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXD, NVS_OP_TXD, 0, 1, 2);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXP, NVS_OP_TXP, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXB, NVS_OP_TXB, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SEQ, NVS_OP_SEQ, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SGT, NVS_OP_SGT, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SLE, NVS_OP_SLE, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SNE, NVS_OP_SNE, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RCP, NVS_OP_RCP, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LG2, NVS_OP_LG2, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_EX2, NVS_OP_EX2, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_COS, NVS_OP_COS, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SIN, NVS_OP_SIN, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DDX, NVS_OP_DDX, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DDY, NVS_OP_DDY, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_KIL, NVS_OP_KIL, -1, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK4B, NVS_OP_PK4B, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP4B, NVS_OP_UP4B, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK2H, NVS_OP_PK2H, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP2H, NVS_OP_UP2H, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK4UB, NVS_OP_PK4UB, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP4UB, NVS_OP_UP4UB, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK2US, NVS_OP_PK2US, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP2US, NVS_OP_UP2US, 0, -1, -1);
|
||||
/*FIXME: Haven't confirmed the source positions for the below opcodes */
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LIT, NVS_OP_LIT, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LRP, NVS_OP_LRP, 0, 1, 2);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_POW, NVS_OP_POW, 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RSQ, NVS_OP_RSQ, 0, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RFL, NVS_OP_RFL, 0, 1, -1);
|
||||
|
||||
shader->GetOPTXRec = NV30FPGetOPTXRec;
|
||||
shader->GetOPTXFromSOP = NV30FPGetOPTXFromSOP;
|
||||
|
||||
shader->UploadToHW = NV30FPUploadToHW;
|
||||
shader->UpdateConst = NV30FPUpdateConst;
|
||||
|
||||
shader->InitInstruction = NV30FPInitInstruction;
|
||||
shader->SupportsOpcode = NV30FPSupportsOpcode;
|
||||
shader->SetOpcode = NV30FPSetOpcode;
|
||||
shader->SetCCUpdate = NV30FPSetCCUpdate;
|
||||
shader->SetCondition = NV30FPSetCondition;
|
||||
shader->SetResult = NV30FPSetResult;
|
||||
shader->SetSource = NV30FPSetSource;
|
||||
shader->SetTexImageUnit = NV30FPSetTexImageUnit;
|
||||
shader->SetSaturate = NV30FPSetSaturate;
|
||||
shader->SetLastInst = NV30FPSetLastInst;
|
||||
|
||||
shader->HasMergedInst = NV30FPHasMergedInst;
|
||||
shader->IsLastInst = NV30FPIsLastInst;
|
||||
shader->GetOffsetNext = NV30FPGetOffsetNext;
|
||||
shader->GetOpcode = NV30FPGetOpcode;
|
||||
shader->GetOpcodeHW = NV30FPGetOpcodeHW;
|
||||
shader->GetDestFile = NV30FPGetDestFile;
|
||||
shader->GetDestID = NV30FPGetDestID;
|
||||
shader->GetDestMask = NV30FPGetDestMask;
|
||||
shader->GetSourceHW = NV30FPGetSourceHW;
|
||||
shader->GetSourceFile = NV30FPGetSourceFile;
|
||||
shader->GetSourceID = NV30FPGetSourceID;
|
||||
shader->GetTexImageUnit = NV30FPGetTexImageUnit;
|
||||
shader->GetSourceNegate = NV30FPGetSourceNegate;
|
||||
shader->GetSourceAbs = NV30FPGetSourceAbs;
|
||||
shader->GetSourceSwizzle = NV30FPGetSourceSwizzle;
|
||||
shader->GetSourceIndexed = NV30FPGetSourceIndexed;
|
||||
shader->GetSourceConstVal = NV30FPGetSourceConstVal;
|
||||
shader->GetSourceScale = NV30FPGetSourceScale;
|
||||
shader->GetRelAddressRegID = NV30FPGetAddressRegID;
|
||||
shader->GetRelAddressSwizzle = NV30FPGetAddressRegSwizzle;
|
||||
shader->GetPrecision = NV30FPGetPrecision;
|
||||
shader->GetSaturate = NV30FPGetSaturate;
|
||||
shader->SupportsConditional = NV30FPSupportsConditional;
|
||||
shader->GetConditionUpdate = NV30FPGetConditionUpdate;
|
||||
shader->GetConditionTest = NV30FPGetConditionTest;
|
||||
shader->GetCondition = NV30FPGetCondition;
|
||||
shader->GetCondRegSwizzle = NV30FPGetCondRegSwizzle;
|
||||
shader->GetCondRegID = NV30FPGetCondRegID;
|
||||
}
|
||||
379
src/mesa/drivers/dri/nouveau/nv30_shader.h
Normal file
379
src/mesa/drivers/dri/nouveau/nv30_shader.h
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
#ifndef __NV30_SHADER_H__
|
||||
#define __NV30_SHADER_H__
|
||||
|
||||
/* Vertex programs instruction set
|
||||
*
|
||||
* 128bit opcodes, split into 4 32-bit ones for ease of use.
|
||||
*
|
||||
* Non-native instructions
|
||||
* ABS - MOV + NV40_VP_INST0_DEST_ABS
|
||||
* POW - EX2 + MUL + LG2
|
||||
* SUB - ADD, second source negated
|
||||
* SWZ - MOV
|
||||
* XPD -
|
||||
*
|
||||
* Register access
|
||||
* - Only one INPUT can be accessed per-instruction (move extras into TEMPs)
|
||||
* - Only one CONST can be accessed per-instruction (move extras into TEMPs)
|
||||
*
|
||||
* Relative Addressing
|
||||
* According to the value returned for MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
|
||||
* there are only two address registers available. The destination in the ARL
|
||||
* instruction is set to TEMP <n> (The temp isn't actually written).
|
||||
*
|
||||
* When using vanilla ARB_v_p, the proprietary driver will squish both the available
|
||||
* ADDRESS regs into the first hardware reg in the X and Y components.
|
||||
*
|
||||
* To use an address reg as an index into consts, the CONST_SRC is set to
|
||||
* (const_base + offset) and INDEX_CONST is set.
|
||||
*
|
||||
* To access the second address reg use ADDR_REG_SELECT_1. A particular component
|
||||
* of the address regs is selected with ADDR_SWZ.
|
||||
*
|
||||
* Only one address register can be accessed per instruction.
|
||||
*
|
||||
* Conditional execution (see NV_vertex_program{2,3} for details)
|
||||
* Conditional execution of an instruction is enabled by setting COND_TEST_ENABLE, and
|
||||
* selecting the condition which will allow the test to pass with COND_{FL,LT,...}.
|
||||
* It is possible to swizzle the values in the condition register, which allows for
|
||||
* testing against an individual component.
|
||||
*
|
||||
* Branching
|
||||
* The BRA/CAL instructions seem to follow a slightly different opcode layout. The
|
||||
* destination instruction ID (IADDR) overlaps a source field. Instruction ID's seem to
|
||||
* be numbered based on the UPLOAD_FROM_ID FIFO command, and is incremented automatically
|
||||
* on each UPLOAD_INST FIFO command.
|
||||
*
|
||||
* Conditional branching is achieved by using the condition tests described above.
|
||||
* There doesn't appear to be dedicated looping instructions, but this can be done
|
||||
* using a temp reg + conditional branching.
|
||||
*
|
||||
* Subroutines may be uploaded before the main program itself, but the first executed
|
||||
* instruction is determined by the PROGRAM_START_ID FIFO command.
|
||||
*
|
||||
*/
|
||||
|
||||
/* DWORD 0 */
|
||||
#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24)
|
||||
#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */
|
||||
#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */
|
||||
#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */
|
||||
#define NV30_VP_INST_OUT_RESULT (1 << 20)
|
||||
#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16
|
||||
#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16)
|
||||
#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15)
|
||||
#define NV30_VP_INST_COND_TEST_ENABLE (1<<14)
|
||||
#define NV30_VP_INST_COND_SHIFT 11
|
||||
#define NV30_VP_INST_COND_MASK (0x07 << 11)
|
||||
# define NV30_VP_INST_COND_FL 0 /* guess */
|
||||
# define NV30_VP_INST_COND_LT 1
|
||||
# define NV30_VP_INST_COND_EQ 2
|
||||
# define NV30_VP_INST_COND_LE 3
|
||||
# define NV30_VP_INST_COND_GT 4
|
||||
# define NV30_VP_INST_COND_NE 5
|
||||
# define NV30_VP_INST_COND_GE 6
|
||||
# define NV30_VP_INST_COND_TR 7 /* guess */
|
||||
#define NV30_VP_INST_COND_SWZ_X_SHIFT 9
|
||||
#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9)
|
||||
#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7
|
||||
#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7)
|
||||
#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5
|
||||
#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5)
|
||||
#define NV30_VP_INST_COND_SWZ_W_SHIFT 3
|
||||
#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3)
|
||||
#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3
|
||||
#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3)
|
||||
#define NV30_VP_INST_ADDR_SWZ_SHIFT 1
|
||||
#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1)
|
||||
#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0
|
||||
#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0)
|
||||
|
||||
/* DWORD 1 */
|
||||
#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28
|
||||
#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28)
|
||||
# define NV30_VP_INST_OP_NOP 0x00
|
||||
# define NV30_VP_INST_OP_RCP 0x02
|
||||
# define NV30_VP_INST_OP_RCC 0x03
|
||||
# define NV30_VP_INST_OP_RSQ 0x04
|
||||
# define NV30_VP_INST_OP_EXP 0x05
|
||||
# define NV30_VP_INST_OP_LOG 0x06
|
||||
# define NV30_VP_INST_OP_LIT 0x07
|
||||
# define NV30_VP_INST_OP_BRA 0x09
|
||||
# define NV30_VP_INST_OP_CAL 0x0B
|
||||
# define NV30_VP_INST_OP_RET 0x0C
|
||||
# define NV30_VP_INST_OP_LG2 0x0D
|
||||
# define NV30_VP_INST_OP_EX2 0x0E
|
||||
# define NV30_VP_INST_OP_SIN 0x0F
|
||||
# define NV30_VP_INST_OP_COS 0x10
|
||||
#define NV30_VP_INST_VEC_OPCODE_SHIFT 23
|
||||
#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23)
|
||||
# define NV30_VP_INST_OP_NOPV 0x00
|
||||
# define NV30_VP_INST_OP_MOV 0x01
|
||||
# define NV30_VP_INST_OP_MUL 0x02
|
||||
# define NV30_VP_INST_OP_ADD 0x03
|
||||
# define NV30_VP_INST_OP_MAD 0x04
|
||||
# define NV30_VP_INST_OP_DP3 0x05
|
||||
# define NV30_VP_INST_OP_DP4 0x07
|
||||
# define NV30_VP_INST_OP_DPH 0x06
|
||||
# define NV30_VP_INST_OP_DST 0x08
|
||||
# define NV30_VP_INST_OP_MIN 0x09
|
||||
# define NV30_VP_INST_OP_MAX 0x0A
|
||||
# define NV30_VP_INST_OP_SLT 0x0B
|
||||
# define NV30_VP_INST_OP_SGE 0x0C
|
||||
# define NV30_VP_INST_OP_ARL 0x0D
|
||||
# define NV30_VP_INST_OP_FRC 0x0E
|
||||
# define NV30_VP_INST_OP_FLR 0x0F
|
||||
# define NV30_VP_INST_OP_SEQ 0x10
|
||||
# define NV30_VP_INST_OP_SFL 0x11
|
||||
# define NV30_VP_INST_OP_SGT 0x12
|
||||
# define NV30_VP_INST_OP_SLE 0x13
|
||||
# define NV30_VP_INST_OP_SNE 0x14
|
||||
# define NV30_VP_INST_OP_STR 0x15
|
||||
# define NV30_VP_INST_OP_SSG 0x16
|
||||
# define NV30_VP_INST_OP_ARR 0x17
|
||||
# define NV30_VP_INST_OP_ARA 0x18
|
||||
#define NV30_VP_INST_CONST_SRC_SHIFT 14
|
||||
#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14)
|
||||
#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/
|
||||
#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/
|
||||
# define NV30_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */
|
||||
# define NV30_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */
|
||||
# define NV30_VP_INST_IN_NORMAL 2
|
||||
# define NV30_VP_INST_IN_COL0 3 /* Should probably confirm them all though */
|
||||
# define NV30_VP_INST_IN_COL1 4
|
||||
# define NV30_VP_INST_IN_FOGC 5
|
||||
# define NV30_VP_INST_IN_TC0 8
|
||||
# define NV30_VP_INST_IN_TC(n) (8+n)
|
||||
#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/
|
||||
#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/
|
||||
|
||||
/* DWORD 2 */
|
||||
#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/
|
||||
#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /*NV20*/
|
||||
#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/
|
||||
#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/
|
||||
#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/
|
||||
#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /*NV20*/
|
||||
#define NV30_VP_INST_IADDR_SHIFT 2
|
||||
#define NV30_VP_INST_IADDR_MASK (0xFF << 2) /* guess */
|
||||
|
||||
/* DWORD 3 */
|
||||
#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/
|
||||
#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/
|
||||
#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24
|
||||
#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24)
|
||||
#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20
|
||||
#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20)
|
||||
#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16
|
||||
#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16)
|
||||
#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/
|
||||
#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/
|
||||
#define NV30_VP_INST_DEST_ID_SHIFT 2
|
||||
#define NV30_VP_INST_DEST_ID_MASK (0x0F << 2)
|
||||
# define NV30_VP_INST_DEST_POS 0
|
||||
# define NV30_VP_INST_DEST_COL0 3
|
||||
# define NV30_VP_INST_DEST_COL1 4
|
||||
# define NV30_VP_INST_DEST_TC(n) (8+n)
|
||||
|
||||
/* Source-register definition - matches NV20 exactly */
|
||||
#define NV30_VP_SRC_REG_NEGATE (1<<14)
|
||||
#define NV30_VP_SRC_REG_SWZ_X_SHIFT 12
|
||||
#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12)
|
||||
#define NV30_VP_SRC_REG_SWZ_Y_SHIFT 10
|
||||
#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10)
|
||||
#define NV30_VP_SRC_REG_SWZ_Z_SHIFT 8
|
||||
#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8)
|
||||
#define NV30_VP_SRC_REG_SWZ_W_SHIFT 6
|
||||
#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6)
|
||||
#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6
|
||||
#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6)
|
||||
#define NV30_VP_SRC_REG_TEMP_ID_SHIFT 2
|
||||
#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0)
|
||||
#define NV30_VP_SRC_REG_TYPE_SHIFT 0
|
||||
#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0)
|
||||
#define NV30_VP_SRC_REG_TYPE_TEMP 1
|
||||
#define NV30_VP_SRC_REG_TYPE_INPUT 2
|
||||
#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */
|
||||
|
||||
/*
|
||||
* Each fragment program opcode appears to be comprised of 4 32-bit values.
|
||||
*
|
||||
* 0 - Opcode, output reg/mask, ATTRIB source
|
||||
* 1 - Source 0
|
||||
* 2 - Source 1
|
||||
* 3 - Source 2
|
||||
*
|
||||
* There appears to be no special difference between result regs and temp regs.
|
||||
* result.color == R0.xyzw
|
||||
* result.depth == R1.z
|
||||
* When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0
|
||||
* otherwise it is set to 1.
|
||||
*
|
||||
* Constants are inserted directly after the instruction that uses them.
|
||||
*
|
||||
* It appears that it's not possible to use two input registers in one
|
||||
* instruction as the input sourcing is done in the instruction dword
|
||||
* and not the source selection dwords. As such instructions such as:
|
||||
*
|
||||
* ADD result.color, fragment.color, fragment.texcoord[0];
|
||||
*
|
||||
* must be split into two MOV's and then an ADD (nvidia does this) but
|
||||
* I'm not sure why it's not just one MOV and then source the second input
|
||||
* in the ADD instruction..
|
||||
*
|
||||
* Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary
|
||||
* negation requires multiplication with a const.
|
||||
*
|
||||
* Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE
|
||||
* The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO
|
||||
* is implemented simply by not writing to the relevant components of the destination.
|
||||
*
|
||||
* Conditional execution
|
||||
* TODO
|
||||
*
|
||||
* Non-native instructions:
|
||||
* LIT
|
||||
* LRP - MAD+MAD
|
||||
* SUB - ADD, negate second source
|
||||
* RSQ - LG2 + EX2
|
||||
* POW - LG2 + MUL + EX2
|
||||
* SCS - COS + SIN
|
||||
* XPD
|
||||
*/
|
||||
|
||||
//== Opcode / Destination selection ==
|
||||
#define NV30_FP_OP_PROGRAM_END (1 << 0)
|
||||
#define NV30_FP_OP_OUT_REG_SHIFT 1
|
||||
#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */
|
||||
/* Needs to be set when writing outputs to get expected result.. */
|
||||
#define NV30_FP_OP_UNK0_7 (1 << 7)
|
||||
#define NV30_FP_OP_COND_WRITE_ENABLE (1 << 8)
|
||||
#define NV30_FP_OP_OUTMASK_SHIFT 9
|
||||
#define NV30_FP_OP_OUTMASK_MASK (0xF << 9)
|
||||
# define NV30_FP_OP_OUT_X (1<<9)
|
||||
# define NV30_FP_OP_OUT_Y (1<<10)
|
||||
# define NV30_FP_OP_OUT_Z (1<<11)
|
||||
# define NV30_FP_OP_OUT_W (1<<12)
|
||||
/* Uncertain about these, especially the input_src values.. it's possible that
|
||||
* they can be dynamically changed.
|
||||
*/
|
||||
#define NV30_FP_OP_INPUT_SRC_SHIFT 13
|
||||
#define NV30_FP_OP_INPUT_SRC_MASK (15 << 13)
|
||||
# define NV30_FP_OP_INPUT_SRC_POSITION 0x0
|
||||
# define NV30_FP_OP_INPUT_SRC_COL0 0x1
|
||||
# define NV30_FP_OP_INPUT_SRC_COL1 0x2
|
||||
# define NV30_FP_OP_INPUT_SRC_FOGC 0x3
|
||||
# define NV30_FP_OP_INPUT_SRC_TC0 0x4
|
||||
# define NV30_FP_OP_INPUT_SRC_TC(n) (0x4 + n)
|
||||
#define NV30_FP_OP_TEX_UNIT_SHIFT 17
|
||||
#define NV30_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */
|
||||
#define NV30_FP_OP_PRECISION_SHIFT 22
|
||||
#define NV30_FP_OP_PRECISION_MASK (3 << 22)
|
||||
# define NV30_FP_PRECISION_FP32 0
|
||||
# define NV30_FP_PRECISION_FP16 1
|
||||
# define NV30_FP_PRECISION_FX12 2
|
||||
#define NV30_FP_OP_OPCODE_SHIFT 24
|
||||
#define NV30_FP_OP_OPCODE_MASK (0x3F << 24)
|
||||
# define NV30_FP_OP_OPCODE_NOP 0x00
|
||||
# define NV30_FP_OP_OPCODE_MOV 0x01
|
||||
# define NV30_FP_OP_OPCODE_MUL 0x02
|
||||
# define NV30_FP_OP_OPCODE_ADD 0x03
|
||||
# define NV30_FP_OP_OPCODE_MAD 0x04
|
||||
# define NV30_FP_OP_OPCODE_DP3 0x05
|
||||
# define NV30_FP_OP_OPCODE_DP4 0x06
|
||||
# define NV30_FP_OP_OPCODE_DST 0x07
|
||||
# define NV30_FP_OP_OPCODE_MIN 0x08
|
||||
# define NV30_FP_OP_OPCODE_MAX 0x09
|
||||
# define NV30_FP_OP_OPCODE_SLT 0x0A
|
||||
# define NV30_FP_OP_OPCODE_SGE 0x0B
|
||||
# define NV30_FP_OP_OPCODE_SLE 0x0C
|
||||
# define NV30_FP_OP_OPCODE_SGT 0x0D
|
||||
# define NV30_FP_OP_OPCODE_SNE 0x0E
|
||||
# define NV30_FP_OP_OPCODE_SEQ 0x0F
|
||||
# define NV30_FP_OP_OPCODE_FRC 0x10
|
||||
# define NV30_FP_OP_OPCODE_FLR 0x11
|
||||
# define NV30_FP_OP_OPCODE_KIL 0x12
|
||||
# define NV30_FP_OP_OPCODE_PK4B 0x13
|
||||
# define NV30_FP_OP_OPCODE_UP4B 0x14
|
||||
# define NV30_FP_OP_OPCODE_DDX 0x15 /* can only write XY */
|
||||
# define NV30_FP_OP_OPCODE_DDY 0x16 /* can only write XY */
|
||||
# define NV30_FP_OP_OPCODE_TEX 0x17
|
||||
# define NV30_FP_OP_OPCODE_TXP 0x18
|
||||
# define NV30_FP_OP_OPCODE_TXD 0x19
|
||||
# define NV30_FP_OP_OPCODE_RCP 0x1A
|
||||
# define NV30_FP_OP_OPCODE_RSQ 0x1B
|
||||
# define NV30_FP_OP_OPCODE_EX2 0x1C
|
||||
# define NV30_FP_OP_OPCODE_LG2 0x1D
|
||||
# define NV30_FP_OP_OPCODE_LIT 0x1E
|
||||
# define NV30_FP_OP_OPCODE_LRP 0x1F
|
||||
# define NV30_FP_OP_OPCODE_COS 0x22
|
||||
# define NV30_FP_OP_OPCODE_SIN 0x23
|
||||
# define NV30_FP_OP_OPCODE_PK2H 0x24
|
||||
# define NV30_FP_OP_OPCODE_UP2H 0x25
|
||||
# define NV30_FP_OP_OPCODE_POW 0x26
|
||||
# define NV30_FP_OP_OPCODE_PK4UB 0x27
|
||||
# define NV30_FP_OP_OPCODE_UP4UB 0x28
|
||||
# define NV30_FP_OP_OPCODE_PK2US 0x29
|
||||
# define NV30_FP_OP_OPCODE_UP2US 0x2A
|
||||
# define NV30_FP_OP_OPCODE_DP2A 0x2E
|
||||
# define NV30_FP_OP_OPCODE_TXB 0x31
|
||||
# define NV30_FP_OP_OPCODE_RFL 0x36
|
||||
#define NV30_FP_OP_OUT_SAT (1 << 31)
|
||||
|
||||
/* high order bits of SRC0 */
|
||||
#define NV30_FP_OP_OUT_ABS (1 << 29)
|
||||
#define NV30_FP_OP_COND_SWZ_W_SHIFT 27
|
||||
#define NV30_FP_OP_COND_SWZ_W_MASK (3 << 27)
|
||||
#define NV30_FP_OP_COND_SWZ_Z_SHIFT 25
|
||||
#define NV30_FP_OP_COND_SWZ_Z_MASK (3 << 25)
|
||||
#define NV30_FP_OP_COND_SWZ_Y_SHIFT 23
|
||||
#define NV30_FP_OP_COND_SWZ_Y_MASK (3 << 23)
|
||||
#define NV30_FP_OP_COND_SWZ_X_SHIFT 21
|
||||
#define NV30_FP_OP_COND_SWZ_X_MASK (3 << 21)
|
||||
#define NV30_FP_OP_COND_SWZ_ALL_SHIFT 21
|
||||
#define NV30_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21)
|
||||
#define NV30_FP_OP_COND_SHIFT 18
|
||||
#define NV30_FP_OP_COND_MASK (0x07 << 18)
|
||||
# define NV30_FP_OP_COND_FL 0
|
||||
# define NV30_FP_OP_COND_LT 1
|
||||
# define NV30_FP_OP_COND_EQ 2
|
||||
# define NV30_FP_OP_COND_LE 3
|
||||
# define NV30_FP_OP_COND_GT 4
|
||||
# define NV30_FP_OP_COND_NE 5
|
||||
# define NV30_FP_OP_COND_GE 6
|
||||
# define NV30_FP_OP_COND_TR 7
|
||||
|
||||
/* high order bits of SRC1 */
|
||||
#define NV30_FP_OP_SRC_SCALE_SHIFT 28
|
||||
#define NV30_FP_OP_SRC_SCALE_MASK (3 << 28)
|
||||
|
||||
/* high order bits of SRC2 */
|
||||
#define NV30_FP_OP_INDEX_INPUT (1 << 30)
|
||||
|
||||
//== Register selection ==
|
||||
#define NV30_FP_REG_ALL_MASK (0x1FFFF<<0)
|
||||
#define NV30_FP_REG_TYPE_SHIFT 0
|
||||
#define NV30_FP_REG_TYPE_MASK (3 << 0)
|
||||
# define NV30_FP_REG_TYPE_TEMP 0
|
||||
# define NV30_FP_REG_TYPE_INPUT 1
|
||||
# define NV30_FP_REG_TYPE_CONST 2
|
||||
#define NV30_FP_REG_SRC_SHIFT 2 /* uncertain */
|
||||
#define NV30_FP_REG_SRC_MASK (31 << 2)
|
||||
#define NV30_FP_REG_UNK_0 (1 << 8)
|
||||
#define NV30_FP_REG_SWZ_ALL_SHIFT 9
|
||||
#define NV30_FP_REG_SWZ_ALL_MASK (255 << 9)
|
||||
#define NV30_FP_REG_SWZ_X_SHIFT 9
|
||||
#define NV30_FP_REG_SWZ_X_MASK (3 << 9)
|
||||
#define NV30_FP_REG_SWZ_Y_SHIFT 11
|
||||
#define NV30_FP_REG_SWZ_Y_MASK (3 << 11)
|
||||
#define NV30_FP_REG_SWZ_Z_SHIFT 13
|
||||
#define NV30_FP_REG_SWZ_Z_MASK (3 << 13)
|
||||
#define NV30_FP_REG_SWZ_W_SHIFT 15
|
||||
#define NV30_FP_REG_SWZ_W_MASK (3 << 15)
|
||||
# define NV30_FP_SWIZZLE_X 0
|
||||
# define NV30_FP_SWIZZLE_Y 1
|
||||
# define NV30_FP_SWIZZLE_Z 2
|
||||
# define NV30_FP_SWIZZLE_W 3
|
||||
#define NV30_FP_REG_NEGATE (1 << 17)
|
||||
|
||||
#endif
|
||||
862
src/mesa/drivers/dri/nouveau/nv30_state.c
Normal file
862
src/mesa/drivers/dri/nouveau/nv30_state.c
Normal file
|
|
@ -0,0 +1,862 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Nouveau
|
||||
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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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_context.h"
|
||||
#include "nouveau_object.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_reg.h"
|
||||
#include "nouveau_state.h"
|
||||
|
||||
#include "tnl/t_pipeline.h"
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "colormac.h"
|
||||
|
||||
#define NOUVEAU_CARD_USING_SHADERS (nmesa->screen->card->type >= NV_40)
|
||||
|
||||
static void nv30AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte ubRef;
|
||||
CLAMPED_FLOAT_TO_UBYTE(ubRef, ref);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
|
||||
OUT_RING_CACHE(func); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC */
|
||||
OUT_RING_CACHE(ubRef); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF */
|
||||
}
|
||||
|
||||
static void nv30BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte cf[4];
|
||||
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_COLOR, 1);
|
||||
OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0]));
|
||||
}
|
||||
|
||||
static void nv30BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1);
|
||||
OUT_RING_CACHE((modeA<<16) | modeRGB);
|
||||
}
|
||||
|
||||
|
||||
static void nv30BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
|
||||
GLenum sfactorA, GLenum dfactorA)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
|
||||
OUT_RING_CACHE((sfactorA<<16) | sfactorRGB);
|
||||
OUT_RING_CACHE((dfactorA<<16) | dfactorRGB);
|
||||
}
|
||||
|
||||
static void nv30Clear(GLcontext *ctx, GLbitfield mask)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLuint hw_bufs = 0;
|
||||
|
||||
if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT))
|
||||
hw_bufs |= 0xf0;
|
||||
if (mask & (BUFFER_BIT_DEPTH))
|
||||
hw_bufs |= 0x03;
|
||||
|
||||
if (hw_bufs) {
|
||||
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS, 1);
|
||||
OUT_RING(hw_bufs);
|
||||
}
|
||||
}
|
||||
|
||||
static void nv30ClearColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte c[4];
|
||||
UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB, 1);
|
||||
OUT_RING_CACHE(PACK_COLOR_8888(c[3],c[0],c[1],c[2]));
|
||||
}
|
||||
|
||||
static void nv30ClearDepth(GLcontext *ctx, GLclampd d)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
nmesa->clear_value=((nmesa->clear_value&0x000000FF)|(((uint32_t)(d*0xFFFFFF))<<8));
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
|
||||
OUT_RING_CACHE(nmesa->clear_value);
|
||||
}
|
||||
|
||||
/* we're don't support indexed buffers
|
||||
void (*ClearIndex)(GLcontext *ctx, GLuint index)
|
||||
*/
|
||||
|
||||
static void nv30ClearStencil(GLcontext *ctx, GLint s)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
nmesa->clear_value=((nmesa->clear_value&0xFFFFFF00)|(s&0x000000FF));
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
|
||||
OUT_RING_CACHE(nmesa->clear_value);
|
||||
}
|
||||
|
||||
static void nv30ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4);
|
||||
OUT_RING_CACHEf(equation[0]);
|
||||
OUT_RING_CACHEf(equation[1]);
|
||||
OUT_RING_CACHEf(equation[2]);
|
||||
OUT_RING_CACHEf(equation[3]);
|
||||
}
|
||||
|
||||
static void nv30ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
|
||||
GLboolean bmask, GLboolean amask )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
|
||||
OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0));
|
||||
}
|
||||
|
||||
static void nv30ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
|
||||
{
|
||||
// TODO I need love
|
||||
}
|
||||
|
||||
static void nv30CullFace(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
static void nv30FrontFace(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FRONT_FACE, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
static void nv30DepthFunc(GLcontext *ctx, GLenum func)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
|
||||
OUT_RING_CACHE(func);
|
||||
}
|
||||
|
||||
static void nv30DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
|
||||
OUT_RING_CACHE(flag);
|
||||
}
|
||||
|
||||
static void nv30DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
|
||||
OUT_RING_CACHEf(nearval);
|
||||
OUT_RING_CACHEf(farval);
|
||||
}
|
||||
|
||||
/** Specify the current buffer for writing */
|
||||
//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer );
|
||||
/** Specify the buffers for writing for fragment programs*/
|
||||
//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers );
|
||||
|
||||
static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
switch(cap)
|
||||
{
|
||||
case GL_ALPHA_TEST:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_AUTO_NORMAL:
|
||||
case GL_BLEND:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_CLIP_PLANE0:
|
||||
case GL_CLIP_PLANE1:
|
||||
case GL_CLIP_PLANE2:
|
||||
case GL_CLIP_PLANE3:
|
||||
case GL_CLIP_PLANE4:
|
||||
case GL_CLIP_PLANE5:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_COLOR_LOGIC_OP:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_COLOR_MATERIAL:
|
||||
// case GL_COLOR_SUM_EXT:
|
||||
// case GL_COLOR_TABLE:
|
||||
// case GL_CONVOLUTION_1D:
|
||||
// case GL_CONVOLUTION_2D:
|
||||
case GL_CULL_FACE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_DEPTH_TEST:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_DITHER:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_FOG:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_HISTOGRAM:
|
||||
// case GL_INDEX_LOGIC_OP:
|
||||
case GL_LIGHT0:
|
||||
case GL_LIGHT1:
|
||||
case GL_LIGHT2:
|
||||
case GL_LIGHT3:
|
||||
case GL_LIGHT4:
|
||||
case GL_LIGHT5:
|
||||
case GL_LIGHT6:
|
||||
case GL_LIGHT7:
|
||||
{
|
||||
uint32_t mask=0x11<<(2*(cap-GL_LIGHT0));
|
||||
|
||||
if (NOUVEAU_CARD_USING_SHADERS)
|
||||
break;
|
||||
|
||||
nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state));
|
||||
if (nmesa->lighting_enabled)
|
||||
{
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
|
||||
OUT_RING_CACHE(nmesa->enabled_lights);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GL_LIGHTING:
|
||||
if (NOUVEAU_CARD_USING_SHADERS)
|
||||
break;
|
||||
|
||||
nmesa->lighting_enabled=state;
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
|
||||
if (nmesa->lighting_enabled)
|
||||
OUT_RING_CACHE(nmesa->enabled_lights);
|
||||
else
|
||||
OUT_RING_CACHE(0x0);
|
||||
break;
|
||||
// case GL_LINE_SMOOTH:
|
||||
// case GL_LINE_STIPPLE:
|
||||
// case GL_MAP1_COLOR_4:
|
||||
// case GL_MAP1_INDEX:
|
||||
// case GL_MAP1_NORMAL:
|
||||
// case GL_MAP1_TEXTURE_COORD_1:
|
||||
// case GL_MAP1_TEXTURE_COORD_2:
|
||||
// case GL_MAP1_TEXTURE_COORD_3:
|
||||
// case GL_MAP1_TEXTURE_COORD_4:
|
||||
// case GL_MAP1_VERTEX_3:
|
||||
// case GL_MAP1_VERTEX_4:
|
||||
// case GL_MAP2_COLOR_4:
|
||||
// case GL_MAP2_INDEX:
|
||||
// case GL_MAP2_NORMAL:
|
||||
// case GL_MAP2_TEXTURE_COORD_1:
|
||||
// case GL_MAP2_TEXTURE_COORD_2:
|
||||
// case GL_MAP2_TEXTURE_COORD_3:
|
||||
// case GL_MAP2_TEXTURE_COORD_4:
|
||||
// case GL_MAP2_VERTEX_3:
|
||||
// case GL_MAP2_VERTEX_4:
|
||||
// case GL_MINMAX:
|
||||
case GL_NORMALIZE:
|
||||
if (nmesa->screen->card->type != NV_44) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
}
|
||||
break;
|
||||
// case GL_POINT_SMOOTH:
|
||||
case GL_POLYGON_OFFSET_POINT:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_OFFSET_LINE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_OFFSET_FILL:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_SMOOTH:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
case GL_POLYGON_STIPPLE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE, 1);
|
||||
OUT_RING_CACHE(state);
|
||||
break;
|
||||
// case GL_POST_COLOR_MATRIX_COLOR_TABLE:
|
||||
// case GL_POST_CONVOLUTION_COLOR_TABLE:
|
||||
// case GL_RESCALE_NORMAL:
|
||||
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;
|
||||
// case GL_TEXTURE_GEN_Q:
|
||||
// case GL_TEXTURE_GEN_R:
|
||||
// case GL_TEXTURE_GEN_S:
|
||||
// case GL_TEXTURE_GEN_T:
|
||||
// case GL_TEXTURE_1D:
|
||||
// case GL_TEXTURE_2D:
|
||||
// case GL_TEXTURE_3D:
|
||||
}
|
||||
}
|
||||
|
||||
static void nv30Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
switch(pname)
|
||||
{
|
||||
case GL_FOG_MODE:
|
||||
//BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_MODE, 1);
|
||||
//OUT_RING_CACHE (params);
|
||||
break;
|
||||
/* TODO: unsure about the rest.*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void nv30Hint(GLcontext *ctx, GLenum target, GLenum mode)
|
||||
{
|
||||
// TODO I need love (fog and line_smooth hints)
|
||||
}
|
||||
|
||||
// void (*IndexMask)(GLcontext *ctx, GLuint mask);
|
||||
|
||||
enum {
|
||||
SPOTLIGHT_UPDATE_EXPONENT,
|
||||
SPOTLIGHT_UPDATE_DIRECTION,
|
||||
SPOTLIGHT_UPDATE_ALL
|
||||
};
|
||||
|
||||
static void nv30Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLint p = light - GL_LIGHT0;
|
||||
struct gl_light *l = &ctx->Light.Light[p];
|
||||
int spotlightUpdate = -1;
|
||||
|
||||
if (NOUVEAU_CARD_USING_SHADERS)
|
||||
return;
|
||||
|
||||
/* not sure where the fourth param value goes...*/
|
||||
switch(pname)
|
||||
{
|
||||
case GL_AMBIENT:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_DIFFUSE:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_SPECULAR:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_POSITION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3);
|
||||
OUT_RING_CACHEf(params[0]);
|
||||
OUT_RING_CACHEf(params[1]);
|
||||
OUT_RING_CACHEf(params[2]);
|
||||
break;
|
||||
case GL_SPOT_DIRECTION:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_DIRECTION;
|
||||
break;
|
||||
case GL_SPOT_EXPONENT:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_EXPONENT;
|
||||
break;
|
||||
case GL_SPOT_CUTOFF:
|
||||
spotlightUpdate = SPOTLIGHT_UPDATE_ALL;
|
||||
break;
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1);
|
||||
OUT_RING_CACHEf(*params);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(spotlightUpdate) {
|
||||
case SPOTLIGHT_UPDATE_DIRECTION:
|
||||
{
|
||||
GLfloat x,y,z;
|
||||
x = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[0];
|
||||
y = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[1];
|
||||
z = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[2];
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3);
|
||||
OUT_RING_CACHEf(x);
|
||||
OUT_RING_CACHEf(y);
|
||||
OUT_RING_CACHEf(z);
|
||||
}
|
||||
break;
|
||||
case SPOTLIGHT_UPDATE_EXPONENT:
|
||||
{
|
||||
GLfloat cc,lc,qc;
|
||||
cc = 1.0; /* FIXME: These need to be correctly computed */
|
||||
lc = 0.0;
|
||||
qc = 2.0;
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3);
|
||||
OUT_RING_CACHEf(cc);
|
||||
OUT_RING_CACHEf(lc);
|
||||
OUT_RING_CACHEf(qc);
|
||||
}
|
||||
break;
|
||||
case SPOTLIGHT_UPDATE_ALL:
|
||||
{
|
||||
GLfloat cc,lc,qc, x,y,z, c;
|
||||
cc = 1.0; /* FIXME: These need to be correctly computed */
|
||||
lc = 0.0;
|
||||
qc = 2.0;
|
||||
x = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[0];
|
||||
y = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[1];
|
||||
z = -2.0 * (1.0 + l->_CosCutoff) * l->_NormDirection[2];
|
||||
c = -2.0 * (0.5 + l->_CosCutoff);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7);
|
||||
OUT_RING_CACHEf(cc);
|
||||
OUT_RING_CACHEf(lc);
|
||||
OUT_RING_CACHEf(qc);
|
||||
OUT_RING_CACHEf(x);
|
||||
OUT_RING_CACHEf(y);
|
||||
OUT_RING_CACHEf(z);
|
||||
OUT_RING_CACHEf(c);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the lighting model parameters */
|
||||
void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
|
||||
|
||||
|
||||
static void nv30LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1);
|
||||
OUT_RING_CACHE((pattern << 16) | factor);
|
||||
}
|
||||
|
||||
static void nv30LineWidth(GLcontext *ctx, GLfloat width)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLubyte ubWidth;
|
||||
|
||||
CLAMPED_FLOAT_TO_UBYTE(ubWidth, width);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LINE_WIDTH_SMOOTH, 1);
|
||||
OUT_RING_CACHE(ubWidth);
|
||||
}
|
||||
|
||||
static void nv30LogicOpcode(GLcontext *ctx, GLenum opcode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1);
|
||||
OUT_RING_CACHE(opcode);
|
||||
}
|
||||
|
||||
static void nv30PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
|
||||
{
|
||||
/*TODO: not sure what goes here. */
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
}
|
||||
|
||||
/** Specify the diameter of rasterized points */
|
||||
static void nv30PointSize(GLcontext *ctx, GLfloat size)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
|
||||
OUT_RING_CACHEf(size);
|
||||
}
|
||||
|
||||
/** Select a polygon rasterization mode */
|
||||
static void nv30PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the scale and units used to calculate depth values */
|
||||
static void nv30PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
|
||||
OUT_RING_CACHEf(factor);
|
||||
|
||||
/* Looks like we always multiply units by 2.0... according to the dumps.*/
|
||||
OUT_RING_CACHEf(units * 2.0);
|
||||
}
|
||||
|
||||
/** Set the polygon stippling pattern */
|
||||
static void nv30PolygonStipple(GLcontext *ctx, const GLubyte *mask )
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 32);
|
||||
OUT_RING_CACHEp(mask, 32);
|
||||
}
|
||||
|
||||
/* Specifies the current buffer for reading */
|
||||
void (*ReadBuffer)( GLcontext *ctx, GLenum buffer );
|
||||
/** Set rasterization mode */
|
||||
void (*RenderMode)(GLcontext *ctx, GLenum mode );
|
||||
|
||||
/** Define the scissor box */
|
||||
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);
|
||||
}
|
||||
|
||||
/** Select flat or smooth shading */
|
||||
static void nv30ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
|
||||
OUT_RING_CACHE(mode);
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilFunc */
|
||||
static void nv30StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
|
||||
GLint ref, GLuint mask)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC, 3);
|
||||
OUT_RING_CACHE(func);
|
||||
OUT_RING_CACHE(ref);
|
||||
OUT_RING_CACHE(mask);
|
||||
}
|
||||
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC, 3);
|
||||
OUT_RING_CACHE(func);
|
||||
OUT_RING_CACHE(ref);
|
||||
OUT_RING_CACHE(mask);
|
||||
}
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilMask */
|
||||
static void nv30StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK, 1);
|
||||
OUT_RING_CACHE(mask);
|
||||
}
|
||||
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK, 1);
|
||||
OUT_RING_CACHE(mask);
|
||||
}
|
||||
}
|
||||
|
||||
/** OpenGL 2.0 two-sided StencilOp */
|
||||
static void nv30StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
|
||||
GLenum zfail, GLenum zpass)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
|
||||
if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL, 3);
|
||||
OUT_RING_CACHE(fail);
|
||||
OUT_RING_CACHE(zfail);
|
||||
OUT_RING_CACHE(zpass);
|
||||
}
|
||||
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL, 3);
|
||||
OUT_RING_CACHE(fail);
|
||||
OUT_RING_CACHE(zfail);
|
||||
OUT_RING_CACHE(zpass);
|
||||
}
|
||||
}
|
||||
|
||||
/** Control the generation of texture coordinates */
|
||||
void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname,
|
||||
const GLfloat *params);
|
||||
/** Set texture environment parameters */
|
||||
void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname,
|
||||
const GLfloat *param);
|
||||
/** Set texture parameters */
|
||||
void (*TexParameter)(GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj,
|
||||
GLenum pname, const GLfloat *params);
|
||||
|
||||
static void nv30TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16);
|
||||
/*XXX: This SHOULD work.*/
|
||||
OUT_RING_CACHEp(mat->m, 16);
|
||||
}
|
||||
|
||||
static void nv30WindowMoved(nouveauContextPtr nmesa)
|
||||
{
|
||||
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);
|
||||
/* 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, 0x1ea4, 3);
|
||||
OUT_RING(0x00000010);
|
||||
OUT_RING(0x01000100);
|
||||
OUT_RING(0xff800006);
|
||||
BEGIN_RING_SIZE(NvSub3D, 0x1fc4, 1);
|
||||
OUT_RING(0x06144321);
|
||||
BEGIN_RING_SIZE(NvSub3D, 0x1fc8, 2);
|
||||
OUT_RING(0xedcba987);
|
||||
OUT_RING(0x00000021);
|
||||
BEGIN_RING_SIZE(NvSub3D, 0x1fd0, 1);
|
||||
OUT_RING(0x00171615);
|
||||
BEGIN_RING_SIZE(NvSub3D, 0x1fd4, 1);
|
||||
OUT_RING(0x001b1a19);
|
||||
|
||||
BEGIN_RING_SIZE(NvSub3D, 0x1ef8, 1);
|
||||
OUT_RING(0x0020ffff);
|
||||
BEGIN_RING_SIZE(NvSub3D, 0x1d64, 1);
|
||||
OUT_RING(0x00d30000);
|
||||
BEGIN_RING_SIZE(NvSub3D, 0x1e94, 1);
|
||||
OUT_RING(0x00000001);
|
||||
|
||||
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;
|
||||
func->BlendFuncSeparate = nv30BlendFuncSeparate;
|
||||
func->Clear = nv30Clear;
|
||||
func->ClearColor = nv30ClearColor;
|
||||
func->ClearDepth = nv30ClearDepth;
|
||||
func->ClearStencil = nv30ClearStencil;
|
||||
func->ClipPlane = nv30ClipPlane;
|
||||
func->ColorMask = nv30ColorMask;
|
||||
func->ColorMaterial = nv30ColorMaterial;
|
||||
func->CullFace = nv30CullFace;
|
||||
func->FrontFace = nv30FrontFace;
|
||||
func->DepthFunc = nv30DepthFunc;
|
||||
func->DepthMask = nv30DepthMask;
|
||||
func->Enable = nv30Enable;
|
||||
func->Fogfv = nv30Fogfv;
|
||||
func->Hint = nv30Hint;
|
||||
func->Lightfv = nv30Lightfv;
|
||||
/* func->LightModelfv = nv30LightModelfv; */
|
||||
func->LineStipple = nv30LineStipple;
|
||||
func->LineWidth = nv30LineWidth;
|
||||
func->LogicOpcode = nv30LogicOpcode;
|
||||
func->PointParameterfv = nv30PointParameterfv;
|
||||
func->PointSize = nv30PointSize;
|
||||
func->PolygonMode = nv30PolygonMode;
|
||||
func->PolygonOffset = nv30PolygonOffset;
|
||||
func->PolygonStipple = nv30PolygonStipple;
|
||||
#if 0
|
||||
func->ReadBuffer = nv30ReadBuffer;
|
||||
func->RenderMode = nv30RenderMode;
|
||||
#endif
|
||||
func->Scissor = nv30Scissor;
|
||||
func->ShadeModel = nv30ShadeModel;
|
||||
func->StencilFuncSeparate = nv30StencilFuncSeparate;
|
||||
func->StencilMaskSeparate = nv30StencilMaskSeparate;
|
||||
func->StencilOpSeparate = nv30StencilOpSeparate;
|
||||
#if 0
|
||||
func->TexGen = nv30TexGen;
|
||||
func->TexParameter = nv30TexParameter;
|
||||
#endif
|
||||
func->TextureMatrix = nv30TextureMatrix;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
356
src/mesa/drivers/dri/nouveau/nv30_vertprog.c
Normal file
356
src/mesa/drivers/dri/nouveau/nv30_vertprog.c
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
#include "nouveau_context.h"
|
||||
#include "nouveau_object.h"
|
||||
#include "nouveau_fifo.h"
|
||||
#include "nouveau_reg.h"
|
||||
|
||||
#include "nouveau_shader.h"
|
||||
#include "nv30_shader.h"
|
||||
|
||||
extern nvsSwzComp NV20VP_TX_SWIZZLE[4];
|
||||
extern void NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz);
|
||||
|
||||
/*****************************************************************************
|
||||
* Support routines
|
||||
*/
|
||||
static void
|
||||
NV30VPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
int i;
|
||||
|
||||
/* We can do better here and keep more than one VP on the hardware, and
|
||||
* switch between them with PROGRAM_START_ID..
|
||||
*/
|
||||
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID, 1);
|
||||
OUT_RING(0);
|
||||
for (i=0; i<nvs->program_size; i+=4) {
|
||||
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, 4);
|
||||
OUT_RING(nvs->program[i + 0]);
|
||||
OUT_RING(nvs->program[i + 1]);
|
||||
OUT_RING(nvs->program[i + 2]);
|
||||
OUT_RING(nvs->program[i + 3]);
|
||||
}
|
||||
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID, 1);
|
||||
OUT_RING(0);
|
||||
}
|
||||
|
||||
static void
|
||||
NV30VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
|
||||
{
|
||||
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
|
||||
GLfloat *val;
|
||||
|
||||
val = nvs->params[id].source_val ?
|
||||
nvs->params[id].source_val : nvs->params[id].val;
|
||||
|
||||
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID, 5);
|
||||
OUT_RING (id);
|
||||
OUT_RINGp(val, 4);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Assembly routines
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* Disassembly routines
|
||||
*/
|
||||
static unsigned int
|
||||
NV30VPGetOpcodeHW(nvsFunc * shader, int slot)
|
||||
{
|
||||
int op;
|
||||
|
||||
if (slot) {
|
||||
op = (shader->inst[1] & NV30_VP_INST_SCA_OPCODEL_MASK)
|
||||
>> NV30_VP_INST_SCA_OPCODEL_SHIFT;
|
||||
op |= ((shader->inst[0] & NV30_VP_INST_SCA_OPCODEH_MASK)
|
||||
>> NV30_VP_INST_SCA_OPCODEH_SHIFT) << 4;
|
||||
}
|
||||
else {
|
||||
op = (shader->inst[1] & NV30_VP_INST_VEC_OPCODE_MASK)
|
||||
>> NV30_VP_INST_VEC_OPCODE_SHIFT;
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
static nvsRegFile
|
||||
NV30VPGetDestFile(nvsFunc * shader, int merged)
|
||||
{
|
||||
switch (shader->GetOpcode(shader, merged)) {
|
||||
case NVS_OP_ARL:
|
||||
case NVS_OP_ARR:
|
||||
case NVS_OP_ARA:
|
||||
return NVS_FILE_ADDRESS;
|
||||
default:
|
||||
/*FIXME: This probably isn't correct.. */
|
||||
if ((shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK) != 0)
|
||||
return NVS_FILE_RESULT;
|
||||
if ((shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK) != 0)
|
||||
return NVS_FILE_RESULT;
|
||||
return NVS_FILE_TEMP;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV30VPGetDestID(nvsFunc * shader, int merged)
|
||||
{
|
||||
int id;
|
||||
|
||||
switch (shader->GetDestFile(shader, merged)) {
|
||||
case NVS_FILE_RESULT:
|
||||
id = ((shader->inst[3] & NV30_VP_INST_DEST_ID_MASK)
|
||||
>> NV30_VP_INST_DEST_ID_SHIFT);
|
||||
switch (id) {
|
||||
case NV30_VP_INST_DEST_POS : return NVS_FR_POSITION;
|
||||
case NV30_VP_INST_DEST_COL0 : return NVS_FR_COL0;
|
||||
case NV30_VP_INST_DEST_COL1 : return NVS_FR_COL1;
|
||||
case NV30_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0;
|
||||
case NV30_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1;
|
||||
case NV30_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2;
|
||||
case NV30_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3;
|
||||
case NV30_VP_INST_DEST_TC(4): return NVS_FR_TEXCOORD4;
|
||||
case NV30_VP_INST_DEST_TC(5): return NVS_FR_TEXCOORD5;
|
||||
case NV30_VP_INST_DEST_TC(6): return NVS_FR_TEXCOORD6;
|
||||
case NV30_VP_INST_DEST_TC(7): return NVS_FR_TEXCOORD7;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
case NVS_FILE_ADDRESS:
|
||||
case NVS_FILE_TEMP:
|
||||
return (shader->inst[0] & NV30_VP_INST_DEST_TEMP_ID_MASK)
|
||||
>> NV30_VP_INST_DEST_TEMP_ID_SHIFT;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV30VPGetDestMask(nvsFunc * shader, int merged)
|
||||
{
|
||||
int hwmask, mask = 0;
|
||||
|
||||
if (shader->GetDestFile(shader, merged) == NVS_FILE_RESULT)
|
||||
if (shader->GetOpcodeSlot(shader, merged))
|
||||
hwmask = (shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK)
|
||||
>> NV30_VP_INST_SDEST_WRITEMASK_SHIFT;
|
||||
else
|
||||
hwmask = (shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK)
|
||||
>> NV30_VP_INST_VDEST_WRITEMASK_SHIFT;
|
||||
else if (shader->GetOpcodeSlot(shader, merged))
|
||||
hwmask = (shader->inst[3] & NV30_VP_INST_STEMP_WRITEMASK_MASK)
|
||||
>> NV30_VP_INST_STEMP_WRITEMASK_SHIFT;
|
||||
else
|
||||
hwmask = (shader->inst[3] & NV30_VP_INST_VTEMP_WRITEMASK_MASK)
|
||||
>> NV30_VP_INST_VTEMP_WRITEMASK_SHIFT;
|
||||
|
||||
if (hwmask & (1 << 3)) mask |= SMASK_X;
|
||||
if (hwmask & (1 << 2)) mask |= SMASK_Y;
|
||||
if (hwmask & (1 << 1)) mask |= SMASK_Z;
|
||||
if (hwmask & (1 << 0)) mask |= SMASK_W;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static int
|
||||
NV30VPGetSourceID(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
unsigned int src;
|
||||
|
||||
switch (shader->GetSourceFile(shader, merged, pos)) {
|
||||
case NVS_FILE_TEMP:
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
return ((src & NV30_VP_SRC_REG_TEMP_ID_MASK) >>
|
||||
NV30_VP_SRC_REG_TEMP_ID_SHIFT);
|
||||
case NVS_FILE_CONST:
|
||||
return ((shader->inst[1] & NV30_VP_INST_CONST_SRC_MASK)
|
||||
>> NV30_VP_INST_CONST_SRC_SHIFT);
|
||||
case NVS_FILE_ATTRIB:
|
||||
src = ((shader->inst[1] & NV30_VP_INST_INPUT_SRC_MASK)
|
||||
>> NV30_VP_INST_INPUT_SRC_SHIFT);
|
||||
switch (src) {
|
||||
case NV30_VP_INST_IN_POS : return NVS_FR_POSITION;
|
||||
case NV30_VP_INST_IN_COL0 : return NVS_FR_COL0;
|
||||
case NV30_VP_INST_IN_COL1 : return NVS_FR_COL1;
|
||||
case NV30_VP_INST_IN_TC(0): return NVS_FR_TEXCOORD0;
|
||||
case NV30_VP_INST_IN_TC(1): return NVS_FR_TEXCOORD1;
|
||||
case NV30_VP_INST_IN_TC(2): return NVS_FR_TEXCOORD2;
|
||||
case NV30_VP_INST_IN_TC(3): return NVS_FR_TEXCOORD3;
|
||||
case NV30_VP_INST_IN_TC(4): return NVS_FR_TEXCOORD4;
|
||||
case NV30_VP_INST_IN_TC(5): return NVS_FR_TEXCOORD5;
|
||||
case NV30_VP_INST_IN_TC(6): return NVS_FR_TEXCOORD6;
|
||||
case NV30_VP_INST_IN_TC(7): return NVS_FR_TEXCOORD7;
|
||||
default:
|
||||
return NVS_FR_UNKNOWN;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV30VPGetSourceAbs(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
static unsigned int abspos[3] = {
|
||||
NV30_VP_INST_SRC0_ABS,
|
||||
NV30_VP_INST_SRC1_ABS,
|
||||
NV30_VP_INST_SRC2_ABS,
|
||||
};
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr || opr->srcpos[pos] == -1 || opr->srcpos[pos] > 2)
|
||||
return 0;
|
||||
|
||||
return ((shader->inst[0] & abspos[opr->srcpos[pos]]) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30VPGetRelAddressRegID(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[0] & NV30_VP_INST_ADDR_REG_SELECT_1) ? 1 : 0);
|
||||
}
|
||||
|
||||
static nvsSwzComp
|
||||
NV30VPGetRelAddressSwizzle(nvsFunc * shader)
|
||||
{
|
||||
nvsSwzComp swz;
|
||||
|
||||
swz = NV20VP_TX_SWIZZLE[(shader->inst[0] & NV30_VP_INST_ADDR_SWZ_MASK)
|
||||
>> NV30_VP_INST_ADDR_SWZ_SHIFT];
|
||||
return swz;
|
||||
}
|
||||
|
||||
static int
|
||||
NV30VPSupportsConditional(nvsFunc * shader)
|
||||
{
|
||||
/*FIXME: Is this true of all ops? */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
NV30VPGetConditionUpdate(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[0] & NV30_VP_INST_COND_UPDATE_ENABLE) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30VPGetConditionTest(nvsFunc * shader)
|
||||
{
|
||||
int op;
|
||||
|
||||
/* The condition test is unconditionally enabled on some
|
||||
* instructions. ie: the condition test bit does *NOT* have
|
||||
* to be set.
|
||||
*
|
||||
* FIXME: check other relevant ops for this situation.
|
||||
*/
|
||||
op = shader->GetOpcodeHW(shader, 1);
|
||||
switch (op) {
|
||||
case NV30_VP_INST_OP_BRA:
|
||||
return 1;
|
||||
default:
|
||||
return ((shader->inst[0] & NV30_VP_INST_COND_TEST_ENABLE) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
static nvsCond
|
||||
NV30VPGetCondition(nvsFunc * shader)
|
||||
{
|
||||
int cond;
|
||||
|
||||
cond = ((shader->inst[0] & NV30_VP_INST_COND_MASK)
|
||||
>> NV30_VP_INST_COND_SHIFT);
|
||||
|
||||
switch (cond) {
|
||||
case NV30_VP_INST_COND_FL: return NVS_COND_FL;
|
||||
case NV30_VP_INST_COND_LT: return NVS_COND_LT;
|
||||
case NV30_VP_INST_COND_EQ: return NVS_COND_EQ;
|
||||
case NV30_VP_INST_COND_LE: return NVS_COND_LE;
|
||||
case NV30_VP_INST_COND_GT: return NVS_COND_GT;
|
||||
case NV30_VP_INST_COND_NE: return NVS_COND_NE;
|
||||
case NV30_VP_INST_COND_GE: return NVS_COND_GE;
|
||||
case NV30_VP_INST_COND_TR: return NVS_COND_TR;
|
||||
default:
|
||||
return NVS_COND_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV30VPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
|
||||
{
|
||||
int swzbits;
|
||||
|
||||
swzbits = (shader->inst[0] & NV30_VP_INST_COND_SWZ_ALL_MASK)
|
||||
>> NV30_VP_INST_COND_SWZ_ALL_SHIFT;
|
||||
NV20VPTXSwizzle(swzbits, swz);
|
||||
}
|
||||
|
||||
static int
|
||||
NV30VPGetCondRegID(nvsFunc * shader)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
NV30VPGetBranch(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[2] & NV30_VP_INST_IADDR_MASK)
|
||||
>> NV30_VP_INST_IADDR_SHIFT);
|
||||
}
|
||||
|
||||
void
|
||||
NV30VPInitShaderFuncs(nvsFunc * shader)
|
||||
{
|
||||
/* Inherit NV20 code, a lot of it is the same */
|
||||
NV20VPInitShaderFuncs(shader);
|
||||
|
||||
/* Increase max valid opcode ID, and add new instructions */
|
||||
NVVP_TX_VOP_COUNT = NVVP_TX_NVS_OP_COUNT = 32;
|
||||
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FRC, NVS_OP_FRC, 0, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FLR, NVS_OP_FLR, 0, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SEQ, NVS_OP_SEQ, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SFL, NVS_OP_SFL, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SGT, NVS_OP_SGT, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SLE, NVS_OP_SLE, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SNE, NVS_OP_SNE, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_STR, NVS_OP_STR, 0, 1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SSG, NVS_OP_SSG, 0, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARR, NVS_OP_ARR, 0, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARA, NVS_OP_ARA, 3, -1, -1);
|
||||
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_BRA, NVS_OP_BRA, -1, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_CAL, NVS_OP_CAL, -1, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_RET, NVS_OP_RET, -1, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_LG2, NVS_OP_LG2, 2, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_EX2, NVS_OP_EX2, 2, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_SIN, NVS_OP_SIN, 2, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_COS, NVS_OP_COS, 2, -1, -1);
|
||||
|
||||
shader->UploadToHW = NV30VPUploadToHW;
|
||||
shader->UpdateConst = NV30VPUpdateConst;
|
||||
|
||||
shader->GetOpcodeHW = NV30VPGetOpcodeHW;
|
||||
|
||||
shader->GetDestFile = NV30VPGetDestFile;
|
||||
shader->GetDestID = NV30VPGetDestID;
|
||||
shader->GetDestMask = NV30VPGetDestMask;
|
||||
|
||||
shader->GetSourceID = NV30VPGetSourceID;
|
||||
shader->GetSourceAbs = NV30VPGetSourceAbs;
|
||||
|
||||
shader->GetRelAddressRegID = NV30VPGetRelAddressRegID;
|
||||
shader->GetRelAddressSwizzle = NV30VPGetRelAddressSwizzle;
|
||||
|
||||
shader->SupportsConditional = NV30VPSupportsConditional;
|
||||
shader->GetConditionUpdate = NV30VPGetConditionUpdate;
|
||||
shader->GetConditionTest = NV30VPGetConditionTest;
|
||||
shader->GetCondition = NV30VPGetCondition;
|
||||
shader->GetCondRegSwizzle = NV30VPGetCondRegSwizzle;
|
||||
shader->GetCondRegID = NV30VPGetCondRegID;
|
||||
|
||||
shader->GetBranch = NV30VPGetBranch;
|
||||
}
|
||||
|
||||
152
src/mesa/drivers/dri/nouveau/nv40_fragprog.c
Normal file
152
src/mesa/drivers/dri/nouveau/nv40_fragprog.c
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
#include "nouveau_shader.h"
|
||||
#include "nv40_shader.h"
|
||||
|
||||
/* branching ops */
|
||||
unsigned int NVFP_TX_BOP_COUNT = 5;
|
||||
struct _op_xlat NVFP_TX_BOP[64];
|
||||
|
||||
static struct _op_xlat *
|
||||
NV40FPGetOPTXRec(nvsFunc * shader, int merged)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
int op;
|
||||
|
||||
op = shader->GetOpcodeHW(shader, 0);
|
||||
if (shader->inst[2] & NV40_FP_OP_OPCODE_IS_BRANCH) {
|
||||
opr = NVFP_TX_BOP;
|
||||
op &= ~NV40_FP_OP_OPCODE_IS_BRANCH;
|
||||
if (op > NVFP_TX_BOP_COUNT)
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
opr = NVFP_TX_AOP;
|
||||
if (op > NVFP_TX_AOP_COUNT)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (opr[op].SOP == NVS_OP_UNKNOWN)
|
||||
return NULL;
|
||||
return &opr[op];
|
||||
}
|
||||
|
||||
static int
|
||||
NV40FPGetSourceID(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
switch (shader->GetSourceFile(shader, merged, pos)) {
|
||||
case NVS_FILE_ATTRIB:
|
||||
switch ((shader->inst[0] & NV40_FP_OP_INPUT_SRC_MASK)
|
||||
>> NV40_FP_OP_INPUT_SRC_SHIFT) {
|
||||
case NV40_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION;
|
||||
case NV40_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0;
|
||||
case NV40_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1;
|
||||
case NV40_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD;
|
||||
case NV40_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0;
|
||||
case NV40_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1;
|
||||
case NV40_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2;
|
||||
case NV40_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3;
|
||||
case NV40_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4;
|
||||
case NV40_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5;
|
||||
case NV40_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6;
|
||||
case NV40_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7;
|
||||
case NV40_FP_OP_INPUT_SRC_FACING : return NVS_FR_FACING;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case NVS_FILE_TEMP:
|
||||
{
|
||||
unsigned int src;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
return ((src & NV40_FP_REG_SRC_MASK) >> NV40_FP_REG_SRC_SHIFT);
|
||||
}
|
||||
case NVS_FILE_CONST: /* inlined into fragprog */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV40FPGetBranch(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[2] & NV40_FP_OP_IADDR_MASK)
|
||||
>> NV40_FP_OP_IADDR_SHIFT);;
|
||||
}
|
||||
|
||||
static int
|
||||
NV40FPGetBranchElse(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[2] & NV40_FP_OP_ELSE_ID_MASK)
|
||||
>> NV40_FP_OP_ELSE_ID_SHIFT);
|
||||
}
|
||||
|
||||
static int
|
||||
NV40FPGetBranchEnd(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[3] & NV40_FP_OP_END_ID_MASK)
|
||||
>> NV40_FP_OP_END_ID_SHIFT);
|
||||
}
|
||||
|
||||
static int
|
||||
NV40FPGetLoopCount(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[2] & NV40_FP_OP_LOOP_COUNT_MASK)
|
||||
>> NV40_FP_OP_LOOP_COUNT_SHIFT);
|
||||
}
|
||||
|
||||
static int
|
||||
NV40FPGetLoopInitial(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[2] & NV40_FP_OP_LOOP_INDEX_MASK)
|
||||
>> NV40_FP_OP_LOOP_INDEX_SHIFT);
|
||||
}
|
||||
|
||||
static int
|
||||
NV40FPGetLoopIncrement(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[2] & NV40_FP_OP_LOOP_INCR_MASK)
|
||||
>> NV40_FP_OP_LOOP_INCR_SHIFT);
|
||||
}
|
||||
|
||||
void
|
||||
NV40FPInitShaderFuncs(nvsFunc * shader)
|
||||
{
|
||||
/* Inherit NV30 FP code, it's mostly the same */
|
||||
NV30FPInitShaderFuncs(shader);
|
||||
|
||||
/* Kill off opcodes seen on NV30, but not seen on NV40 - need to find
|
||||
* out if these actually work or not.
|
||||
*
|
||||
* update: either LIT/RSQ don't work on nv40, or I generate bad code for
|
||||
* them. haven't tested the others yet
|
||||
*/
|
||||
MOD_OPCODE(NVFP_TX_AOP, 0x1B, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RSQ */
|
||||
MOD_OPCODE(NVFP_TX_AOP, 0x1E, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LIT */
|
||||
MOD_OPCODE(NVFP_TX_AOP, 0x1F, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LRP */
|
||||
MOD_OPCODE(NVFP_TX_AOP, 0x26, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 POW */
|
||||
MOD_OPCODE(NVFP_TX_AOP, 0x36, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RFL */
|
||||
|
||||
/* Extra opcodes supported on NV40 */
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DIV , NVS_OP_DIV , 0, 1, -1);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DP2A , NVS_OP_DP2A, 0, 1, 2);
|
||||
MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_TXL , NVS_OP_TXL , 0, -1, -1);
|
||||
|
||||
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_BRK , NVS_OP_BRK , -1, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_CAL , NVS_OP_CAL , -1, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_IF , NVS_OP_IF , -1, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_LOOP, NVS_OP_LOOP, -1, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_REP , NVS_OP_REP , -1, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_RET , NVS_OP_RET , -1, -1, -1);
|
||||
|
||||
/* fragment.facing */
|
||||
shader->GetSourceID = NV40FPGetSourceID;
|
||||
|
||||
/* branching */
|
||||
shader->GetOPTXRec = NV40FPGetOPTXRec;
|
||||
shader->GetBranch = NV40FPGetBranch;
|
||||
shader->GetBranchElse = NV40FPGetBranchElse;
|
||||
shader->GetBranchEnd = NV40FPGetBranchEnd;
|
||||
shader->GetLoopCount = NV40FPGetLoopCount;
|
||||
shader->GetLoopInitial = NV40FPGetLoopInitial;
|
||||
shader->GetLoopIncrement = NV40FPGetLoopIncrement;
|
||||
}
|
||||
467
src/mesa/drivers/dri/nouveau/nv40_shader.h
Normal file
467
src/mesa/drivers/dri/nouveau/nv40_shader.h
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
#ifndef __NV40_SHADER_H__
|
||||
#define __NV40_SHADER_H__
|
||||
|
||||
/* Vertex programs instruction set
|
||||
*
|
||||
* The NV40 instruction set is very similar to NV30. Most fields are in
|
||||
* a slightly different position in the instruction however.
|
||||
*
|
||||
* Merged instructions
|
||||
* In some cases it is possible to put two instructions into one opcode
|
||||
* slot. The rules for when this is OK is not entirely clear to me yet.
|
||||
*
|
||||
* There are separate writemasks and dest temp register fields for each
|
||||
* grouping of instructions. There is however only one field with the
|
||||
* ID of a result register. Writing to temp/result regs is selected by
|
||||
* setting VEC_RESULT/SCA_RESULT.
|
||||
*
|
||||
* Temporary registers
|
||||
* The source/dest temp register fields have been extended by 1 bit, to
|
||||
* give a total of 32 temporary registers.
|
||||
*
|
||||
* Relative Addressing
|
||||
* NV40 can use an address register to index into vertex attribute regs.
|
||||
* This is done by putting the offset value into INPUT_SRC and setting
|
||||
* the INDEX_INPUT flag.
|
||||
*
|
||||
* Conditional execution (see NV_vertex_program{2,3} for details)
|
||||
* There is a second condition code register on NV40, it's use is enabled
|
||||
* by setting the COND_REG_SELECT_1 flag.
|
||||
*
|
||||
* Texture lookup
|
||||
* TODO
|
||||
*/
|
||||
|
||||
/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */
|
||||
#define NV40_VP_INST_VEC_RESULT (1 << 30)
|
||||
/* uncertain.. */
|
||||
#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29)
|
||||
/* use address reg as index into attribs */
|
||||
#define NV40_VP_INST_INDEX_INPUT (1 << 27)
|
||||
#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25)
|
||||
#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24)
|
||||
#define NV40_VP_INST_SRC2_ABS (1 << 23)
|
||||
#define NV40_VP_INST_SRC1_ABS (1 << 22)
|
||||
#define NV40_VP_INST_SRC0_ABS (1 << 21)
|
||||
#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15
|
||||
#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 15)
|
||||
#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13)
|
||||
#define NV40_VP_INST_COND_SHIFT 10
|
||||
#define NV40_VP_INST_COND_MASK (0x7 << 10)
|
||||
# define NV40_VP_INST_COND_FL 0
|
||||
# define NV40_VP_INST_COND_LT 1
|
||||
# define NV40_VP_INST_COND_EQ 2
|
||||
# define NV40_VP_INST_COND_LE 3
|
||||
# define NV40_VP_INST_COND_GT 4
|
||||
# define NV40_VP_INST_COND_NE 5
|
||||
# define NV40_VP_INST_COND_GE 6
|
||||
# define NV40_VP_INST_COND_TR 7
|
||||
#define NV40_VP_INST_COND_SWZ_X_SHIFT 8
|
||||
#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8)
|
||||
#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6
|
||||
#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6)
|
||||
#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4
|
||||
#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4)
|
||||
#define NV40_VP_INST_COND_SWZ_W_SHIFT 2
|
||||
#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2)
|
||||
#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2
|
||||
#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2)
|
||||
#define NV40_VP_INST_ADDR_SWZ_SHIFT 0
|
||||
#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0)
|
||||
#define NV40_VP_INST0_KNOWN ( \
|
||||
NV40_VP_INST_INDEX_INPUT | \
|
||||
NV40_VP_INST_COND_REG_SELECT_1 | \
|
||||
NV40_VP_INST_ADDR_REG_SELECT_1 | \
|
||||
NV40_VP_INST_SRC2_ABS | \
|
||||
NV40_VP_INST_SRC1_ABS | \
|
||||
NV40_VP_INST_SRC0_ABS | \
|
||||
NV40_VP_INST_VEC_DEST_TEMP_MASK | \
|
||||
NV40_VP_INST_COND_TEST_ENABLE | \
|
||||
NV40_VP_INST_COND_MASK | \
|
||||
NV40_VP_INST_COND_SWZ_ALL_MASK | \
|
||||
NV40_VP_INST_ADDR_SWZ_MASK)
|
||||
|
||||
/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */
|
||||
#define NV40_VP_INST_VEC_OPCODE_SHIFT 22
|
||||
#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22)
|
||||
# define NV40_VP_INST_OP_NOP 0x00
|
||||
# define NV40_VP_INST_OP_MOV 0x01
|
||||
# define NV40_VP_INST_OP_MUL 0x02
|
||||
# define NV40_VP_INST_OP_ADD 0x03
|
||||
# define NV40_VP_INST_OP_MAD 0x04
|
||||
# define NV40_VP_INST_OP_DP3 0x05
|
||||
# define NV40_VP_INST_OP_DP4 0x07
|
||||
# define NV40_VP_INST_OP_DPH 0x06
|
||||
# define NV40_VP_INST_OP_DST 0x08
|
||||
# define NV40_VP_INST_OP_MIN 0x09
|
||||
# define NV40_VP_INST_OP_MAX 0x0A
|
||||
# define NV40_VP_INST_OP_SLT 0x0B
|
||||
# define NV40_VP_INST_OP_SGE 0x0C
|
||||
# define NV40_VP_INST_OP_ARL 0x0D
|
||||
# define NV40_VP_INST_OP_FRC 0x0E
|
||||
# define NV40_VP_INST_OP_FLR 0x0F
|
||||
# define NV40_VP_INST_OP_SEQ 0x10
|
||||
# define NV40_VP_INST_OP_SFL 0x11
|
||||
# define NV40_VP_INST_OP_SGT 0x12
|
||||
# define NV40_VP_INST_OP_SLE 0x13
|
||||
# define NV40_VP_INST_OP_SNE 0x14
|
||||
# define NV40_VP_INST_OP_STR 0x15
|
||||
# define NV40_VP_INST_OP_SSG 0x16
|
||||
# define NV40_VP_INST_OP_ARR 0x17
|
||||
# define NV40_VP_INST_OP_ARA 0x18
|
||||
# define NV40_VP_INST_OP_TXWHAT 0x19
|
||||
#define NV40_VP_INST_SCA_OPCODE_SHIFT 27
|
||||
#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27)
|
||||
# define NV40_VP_INST_OP_RCP 0x02
|
||||
# define NV40_VP_INST_OP_RCC 0x03
|
||||
# define NV40_VP_INST_OP_RSQ 0x04
|
||||
# define NV40_VP_INST_OP_EXP 0x05
|
||||
# define NV40_VP_INST_OP_LOG 0x06
|
||||
# define NV40_VP_INST_OP_LIT 0x07
|
||||
# define NV40_VP_INST_OP_BRA 0x09
|
||||
# define NV40_VP_INST_OP_CAL 0x0B
|
||||
# define NV40_VP_INST_OP_RET 0x0C
|
||||
# define NV40_VP_INST_OP_LG2 0x0D
|
||||
# define NV40_VP_INST_OP_EX2 0x0E
|
||||
# define NV40_VP_INST_OP_SIN 0x0F
|
||||
# define NV40_VP_INST_OP_COS 0x10
|
||||
# define NV40_VP_INST_OP_PUSHA 0x13
|
||||
# define NV40_VP_INST_OP_POPA 0x14
|
||||
#define NV40_VP_INST_CONST_SRC_SHIFT 12
|
||||
#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12)
|
||||
#define NV40_VP_INST_INPUT_SRC_SHIFT 8
|
||||
#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8)
|
||||
# define NV40_VP_INST_IN_POS 0
|
||||
# define NV40_VP_INST_IN_WEIGHT 1
|
||||
# define NV40_VP_INST_IN_NORMAL 2
|
||||
# define NV40_VP_INST_IN_COL0 3
|
||||
# define NV40_VP_INST_IN_COL1 4
|
||||
# define NV40_VP_INST_IN_FOGC 5
|
||||
# define NV40_VP_INST_IN_TC0 8
|
||||
# define NV40_VP_INST_IN_TC(n) (8+n)
|
||||
#define NV40_VP_INST_SRC0H_SHIFT 0
|
||||
#define NV40_VP_INST_SRC0H_MASK (0xFF << 0)
|
||||
#define NV40_VP_INST1_KNOWN ( \
|
||||
NV40_VP_INST_VEC_OPCODE_MASK | \
|
||||
NV40_VP_INST_SCA_OPCODE_MASK | \
|
||||
NV40_VP_INST_CONST_SRC_MASK | \
|
||||
NV40_VP_INST_INPUT_SRC_MASK | \
|
||||
NV40_VP_INST_SRC0H_MASK \
|
||||
)
|
||||
|
||||
/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */
|
||||
#define NV40_VP_INST_SRC0L_SHIFT 23
|
||||
#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23)
|
||||
#define NV40_VP_INST_SRC1_SHIFT 6
|
||||
#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6)
|
||||
#define NV40_VP_INST_SRC2H_SHIFT 0
|
||||
#define NV40_VP_INST_SRC2H_MASK (0x3F << 0)
|
||||
#define NV40_VP_INST_IADDRH_SHIFT 0
|
||||
#define NV40_VP_INST_IADDRH_MASK (0x1F << 0)
|
||||
|
||||
/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */
|
||||
#define NV40_VP_INST_IADDRL_SHIFT 29
|
||||
#define NV40_VP_INST_IADDRL_MASK (7 << 29)
|
||||
#define NV40_VP_INST_SRC2L_SHIFT 21
|
||||
#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21)
|
||||
#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17
|
||||
#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17)
|
||||
# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20)
|
||||
# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19)
|
||||
# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18)
|
||||
# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17)
|
||||
#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13
|
||||
#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13)
|
||||
# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16)
|
||||
# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15)
|
||||
# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14)
|
||||
# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13)
|
||||
#define NV40_VP_INST_SCA_RESULT (1 << 12)
|
||||
#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7
|
||||
#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7)
|
||||
#define NV40_VP_INST_DEST_SHIFT 2
|
||||
#define NV40_VP_INST_DEST_MASK (31 << 2)
|
||||
# define NV40_VP_INST_DEST_POS 0
|
||||
# define NV40_VP_INST_DEST_COL0 1
|
||||
# define NV40_VP_INST_DEST_COL1 2
|
||||
# define NV40_VP_INST_DEST_BFC0 3
|
||||
# define NV40_VP_INST_DEST_BFC1 4
|
||||
# define NV40_VP_INST_DEST_FOGC 5
|
||||
# define NV40_VP_INST_DEST_PSZ 6
|
||||
# define NV40_VP_INST_DEST_TC0 7
|
||||
# define NV40_VP_INST_DEST_TC(n) (7+n)
|
||||
# define NV40_VP_INST_DEST_TEMP 0x1F
|
||||
#define NV40_VP_INST_INDEX_CONST (1 << 1)
|
||||
#define NV40_VP_INST_LAST (1 << 0)
|
||||
#define NV40_VP_INST3_KNOWN ( \
|
||||
NV40_VP_INST_SRC2L_MASK |\
|
||||
NV40_VP_INST_SCA_WRITEMASK_MASK |\
|
||||
NV40_VP_INST_VEC_WRITEMASK_MASK |\
|
||||
NV40_VP_INST_SCA_DEST_TEMP_MASK |\
|
||||
NV40_VP_INST_DEST_MASK |\
|
||||
NV40_VP_INST_INDEX_CONST)
|
||||
|
||||
/* Useful to split the source selection regs into their pieces */
|
||||
#define NV40_VP_SRC0_HIGH_SHIFT 9
|
||||
#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00
|
||||
#define NV40_VP_SRC0_LOW_MASK 0x000001FF
|
||||
#define NV40_VP_SRC2_HIGH_SHIFT 11
|
||||
#define NV40_VP_SRC2_HIGH_MASK 0x0001F800
|
||||
#define NV40_VP_SRC2_LOW_MASK 0x000007FF
|
||||
|
||||
/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */
|
||||
#define NV40_VP_SRC_NEGATE (1 << 16)
|
||||
#define NV40_VP_SRC_SWZ_X_SHIFT 14
|
||||
#define NV40_VP_SRC_SWZ_X_MASK (3 << 14)
|
||||
#define NV40_VP_SRC_SWZ_Y_SHIFT 12
|
||||
#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12)
|
||||
#define NV40_VP_SRC_SWZ_Z_SHIFT 10
|
||||
#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10)
|
||||
#define NV40_VP_SRC_SWZ_W_SHIFT 8
|
||||
#define NV40_VP_SRC_SWZ_W_MASK (3 << 8)
|
||||
#define NV40_VP_SRC_SWZ_ALL_SHIFT 8
|
||||
#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8)
|
||||
#define NV40_VP_SRC_TEMP_SRC_SHIFT 2
|
||||
#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2)
|
||||
#define NV40_VP_SRC_REG_TYPE_SHIFT 0
|
||||
#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0)
|
||||
# define NV40_VP_SRC_REG_TYPE_UNK0 0
|
||||
# define NV40_VP_SRC_REG_TYPE_TEMP 1
|
||||
# define NV40_VP_SRC_REG_TYPE_INPUT 2
|
||||
# define NV40_VP_SRC_REG_TYPE_CONST 3
|
||||
|
||||
|
||||
/*
|
||||
* Each fragment program opcode appears to be comprised of 4 32-bit values.
|
||||
*
|
||||
* 0 - Opcode, output reg/mask, ATTRIB source
|
||||
* 1 - Source 0
|
||||
* 2 - Source 1
|
||||
* 3 - Source 2
|
||||
*
|
||||
* There appears to be no special difference between result regs and temp regs.
|
||||
* result.color == R0.xyzw
|
||||
* result.depth == R1.z
|
||||
* When the fragprog contains instructions to write depth,
|
||||
* NV30_TCL_PRIMITIVE_3D_UNK1D78=0 otherwise it is set to 1.
|
||||
*
|
||||
* Constants are inserted directly after the instruction that uses them.
|
||||
*
|
||||
* It appears that it's not possible to use two input registers in one
|
||||
* instruction as the input sourcing is done in the instruction dword
|
||||
* and not the source selection dwords. As such instructions such as:
|
||||
*
|
||||
* ADD result.color, fragment.color, fragment.texcoord[0];
|
||||
*
|
||||
* must be split into two MOV's and then an ADD (nvidia does this) but
|
||||
* I'm not sure why it's not just one MOV and then source the second input
|
||||
* in the ADD instruction..
|
||||
*
|
||||
* Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary
|
||||
* negation requires multiplication with a const.
|
||||
*
|
||||
* Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO and
|
||||
* SWIZZLE_ONE.
|
||||
*
|
||||
* The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as
|
||||
* SWIZZLE_ZERO is implemented simply by not writing to the relevant components
|
||||
* of the destination.
|
||||
*
|
||||
* Looping
|
||||
* Loops appear to be fairly expensive on NV40 at least, the proprietary
|
||||
* driver goes to a lot of effort to avoid using the native looping
|
||||
* instructions. If the total number of *executed* instructions between
|
||||
* REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop.
|
||||
* The maximum loop count is 255.
|
||||
*
|
||||
* Conditional execution
|
||||
* TODO
|
||||
*
|
||||
* Non-native instructions:
|
||||
* LIT
|
||||
* LRP - MAD+MAD
|
||||
* SUB - ADD, negate second source
|
||||
* RSQ - LG2 + EX2
|
||||
* POW - LG2 + MUL + EX2
|
||||
* SCS - COS + SIN
|
||||
* XPD
|
||||
* DP2 - MUL + ADD
|
||||
* NRM
|
||||
*/
|
||||
|
||||
//== Opcode / Destination selection ==
|
||||
#define NV40_FP_OP_PROGRAM_END (1 << 0)
|
||||
#define NV40_FP_OP_OUT_REG_SHIFT 1
|
||||
#define NV40_FP_OP_OUT_REG_MASK (31 << 1)
|
||||
/* Needs to be set when writing outputs to get expected result.. */
|
||||
#define NV40_FP_OP_UNK0_7 (1 << 7)
|
||||
#define NV40_FP_OP_COND_WRITE_ENABLE (1 << 8)
|
||||
#define NV40_FP_OP_OUTMASK_SHIFT 9
|
||||
#define NV40_FP_OP_OUTMASK_MASK (0xF << 9)
|
||||
# define NV40_FP_OP_OUT_X (1 << 9)
|
||||
# define NV40_FP_OP_OUT_Y (1 <<10)
|
||||
# define NV40_FP_OP_OUT_Z (1 <<11)
|
||||
# define NV40_FP_OP_OUT_W (1 <<12)
|
||||
/* Uncertain about these, especially the input_src values.. it's possible that
|
||||
* they can be dynamically changed.
|
||||
*/
|
||||
#define NV40_FP_OP_INPUT_SRC_SHIFT 13
|
||||
#define NV40_FP_OP_INPUT_SRC_MASK (15 << 13)
|
||||
# define NV40_FP_OP_INPUT_SRC_POSITION 0x0
|
||||
# define NV40_FP_OP_INPUT_SRC_COL0 0x1
|
||||
# define NV40_FP_OP_INPUT_SRC_COL1 0x2
|
||||
# define NV40_FP_OP_INPUT_SRC_FOGC 0x3
|
||||
# define NV40_FP_OP_INPUT_SRC_TC0 0x4
|
||||
# define NV40_FP_OP_INPUT_SRC_TC(n) (0x4 + n)
|
||||
# define NV40_FP_OP_INPUT_SRC_FACING 0xE
|
||||
#define NV40_FP_OP_TEX_UNIT_SHIFT 17
|
||||
#define NV40_FP_OP_TEX_UNIT_MASK (0xF << 17)
|
||||
#define NV40_FP_OP_PRECISION_SHIFT 22
|
||||
#define NV40_FP_OP_PRECISION_MASK (3 << 22)
|
||||
# define NV40_FP_PRECISION_FP32 0
|
||||
# define NV40_FP_PRECISION_FP16 1
|
||||
# define NV40_FP_PRECISION_FX12 2
|
||||
#define NV40_FP_OP_OPCODE_SHIFT 24
|
||||
#define NV40_FP_OP_OPCODE_MASK (0x3F << 24)
|
||||
# define NV40_FP_OP_OPCODE_NOP 0x00
|
||||
# define NV40_FP_OP_OPCODE_MOV 0x01
|
||||
# define NV40_FP_OP_OPCODE_MUL 0x02
|
||||
# define NV40_FP_OP_OPCODE_ADD 0x03
|
||||
# define NV40_FP_OP_OPCODE_MAD 0x04
|
||||
# define NV40_FP_OP_OPCODE_DP3 0x05
|
||||
# define NV40_FP_OP_OPCODE_DP4 0x06
|
||||
# define NV40_FP_OP_OPCODE_DST 0x07
|
||||
# define NV40_FP_OP_OPCODE_MIN 0x08
|
||||
# define NV40_FP_OP_OPCODE_MAX 0x09
|
||||
# define NV40_FP_OP_OPCODE_SLT 0x0A
|
||||
# define NV40_FP_OP_OPCODE_SGE 0x0B
|
||||
# define NV40_FP_OP_OPCODE_SLE 0x0C
|
||||
# define NV40_FP_OP_OPCODE_SGT 0x0D
|
||||
# define NV40_FP_OP_OPCODE_SNE 0x0E
|
||||
# define NV40_FP_OP_OPCODE_SEQ 0x0F
|
||||
# define NV40_FP_OP_OPCODE_FRC 0x10
|
||||
# define NV40_FP_OP_OPCODE_FLR 0x11
|
||||
# define NV40_FP_OP_OPCODE_KIL 0x12
|
||||
# define NV40_FP_OP_OPCODE_PK4B 0x13
|
||||
# define NV40_FP_OP_OPCODE_UP4B 0x14
|
||||
/* DDX/DDY can only write to XY */
|
||||
# define NV40_FP_OP_OPCODE_DDX 0x15
|
||||
# define NV40_FP_OP_OPCODE_DDY 0x16
|
||||
# define NV40_FP_OP_OPCODE_TEX 0x17
|
||||
# define NV40_FP_OP_OPCODE_TXP 0x18
|
||||
# define NV40_FP_OP_OPCODE_TXD 0x19
|
||||
# define NV40_FP_OP_OPCODE_RCP 0x1A
|
||||
# define NV40_FP_OP_OPCODE_EX2 0x1C
|
||||
# define NV40_FP_OP_OPCODE_LG2 0x1D
|
||||
# define NV40_FP_OP_OPCODE_COS 0x22
|
||||
# define NV40_FP_OP_OPCODE_SIN 0x23
|
||||
# define NV40_FP_OP_OPCODE_PK2H 0x24
|
||||
# define NV40_FP_OP_OPCODE_UP2H 0x25
|
||||
# define NV40_FP_OP_OPCODE_PK4UB 0x27
|
||||
# define NV40_FP_OP_OPCODE_UP4UB 0x28
|
||||
# define NV40_FP_OP_OPCODE_PK2US 0x29
|
||||
# define NV40_FP_OP_OPCODE_UP2US 0x2A
|
||||
# define NV40_FP_OP_OPCODE_DP2A 0x2E
|
||||
# define NV40_FP_OP_OPCODE_TXL 0x2F
|
||||
# define NV40_FP_OP_OPCODE_TXB 0x31
|
||||
# define NV40_FP_OP_OPCODE_DIV 0x3A
|
||||
/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/
|
||||
# define NV40_FP_OP_BRA_OPCODE_BRK 0x0
|
||||
# define NV40_FP_OP_BRA_OPCODE_CAL 0x1
|
||||
# define NV40_FP_OP_BRA_OPCODE_IF 0x2
|
||||
# define NV40_FP_OP_BRA_OPCODE_LOOP 0x3
|
||||
# define NV40_FP_OP_BRA_OPCODE_REP 0x4
|
||||
# define NV40_FP_OP_BRA_OPCODE_RET 0x5
|
||||
#define NV40_FP_OP_OUT_SAT (1 << 31)
|
||||
|
||||
/* high order bits of SRC0 */
|
||||
#define NV40_FP_OP_OUT_ABS (1 << 29)
|
||||
#define NV40_FP_OP_COND_SWZ_W_SHIFT 27
|
||||
#define NV40_FP_OP_COND_SWZ_W_MASK (3 << 27)
|
||||
#define NV40_FP_OP_COND_SWZ_Z_SHIFT 25
|
||||
#define NV40_FP_OP_COND_SWZ_Z_MASK (3 << 25)
|
||||
#define NV40_FP_OP_COND_SWZ_Y_SHIFT 23
|
||||
#define NV40_FP_OP_COND_SWZ_Y_MASK (3 << 23)
|
||||
#define NV40_FP_OP_COND_SWZ_X_SHIFT 21
|
||||
#define NV40_FP_OP_COND_SWZ_X_MASK (3 << 21)
|
||||
#define NV40_FP_OP_COND_SWZ_ALL_SHIFT 21
|
||||
#define NV40_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21)
|
||||
#define NV40_FP_OP_COND_SHIFT 18
|
||||
#define NV40_FP_OP_COND_MASK (0x07 << 18)
|
||||
# define NV40_FP_OP_COND_FL 0
|
||||
# define NV40_FP_OP_COND_LT 1
|
||||
# define NV40_FP_OP_COND_EQ 2
|
||||
# define NV40_FP_OP_COND_LE 3
|
||||
# define NV40_FP_OP_COND_GT 4
|
||||
# define NV40_FP_OP_COND_NE 5
|
||||
# define NV40_FP_OP_COND_GE 6
|
||||
# define NV40_FP_OP_COND_TR 7
|
||||
|
||||
/* high order bits of SRC1 */
|
||||
#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31)
|
||||
#define NV40_FP_OP_SRC_SCALE_SHIFT 28
|
||||
#define NV40_FP_OP_SRC_SCALE_MASK (3 << 28)
|
||||
|
||||
/* SRC1 LOOP */
|
||||
#define NV40_FP_OP_LOOP_INCR_SHIFT 19
|
||||
#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19)
|
||||
#define NV40_FP_OP_LOOP_INDEX_SHIFT 10
|
||||
#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10)
|
||||
#define NV40_FP_OP_LOOP_COUNT_SHIFT 2
|
||||
#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2)
|
||||
|
||||
/* SRC1 IF */
|
||||
#define NV40_FP_OP_ELSE_ID_SHIFT 2
|
||||
#define NV40_FP_OP_ELSE_ID_MASK (0xFF << 2)
|
||||
|
||||
/* SRC1 CAL */
|
||||
#define NV40_FP_OP_IADDR_SHIFT 2
|
||||
#define NV40_FP_OP_IADDR_MASK (0xFF << 2)
|
||||
|
||||
/* SRC1 REP
|
||||
* I have no idea why there are 3 count values here.. but they
|
||||
* have always been filled with the same value in my tests so
|
||||
* far..
|
||||
*/
|
||||
#define NV40_FP_OP_REP_COUNT1_SHIFT 2
|
||||
#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2)
|
||||
#define NV40_FP_OP_REP_COUNT2_SHIFT 10
|
||||
#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10)
|
||||
#define NV40_FP_OP_REP_COUNT3_SHIFT 19
|
||||
#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19)
|
||||
|
||||
/* SRC2 REP/IF */
|
||||
#define NV40_FP_OP_END_ID_SHIFT 2
|
||||
#define NV40_FP_OP_END_ID_MASK (0xFF << 2)
|
||||
|
||||
// SRC2 high-order
|
||||
#define NV40_FP_OP_INDEX_INPUT (1 << 30)
|
||||
#define NV40_FP_OP_ADDR_INDEX_SHIFT 19
|
||||
#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19)
|
||||
|
||||
//== Register selection ==
|
||||
#define NV40_FP_REG_TYPE_SHIFT 0
|
||||
#define NV40_FP_REG_TYPE_MASK (3 << 0)
|
||||
# define NV40_FP_REG_TYPE_TEMP 0
|
||||
# define NV40_FP_REG_TYPE_INPUT 1
|
||||
# define NV40_FP_REG_TYPE_CONST 2
|
||||
#define NV40_FP_REG_SRC_SHIFT 2
|
||||
#define NV40_FP_REG_SRC_MASK (31 << 2)
|
||||
#define NV40_FP_REG_UNK_0 (1 << 8)
|
||||
#define NV40_FP_REG_SWZ_ALL_SHIFT 9
|
||||
#define NV40_FP_REG_SWZ_ALL_MASK (255 << 9)
|
||||
#define NV40_FP_REG_SWZ_X_SHIFT 9
|
||||
#define NV40_FP_REG_SWZ_X_MASK (3 << 9)
|
||||
#define NV40_FP_REG_SWZ_Y_SHIFT 11
|
||||
#define NV40_FP_REG_SWZ_Y_MASK (3 << 11)
|
||||
#define NV40_FP_REG_SWZ_Z_SHIFT 13
|
||||
#define NV40_FP_REG_SWZ_Z_MASK (3 << 13)
|
||||
#define NV40_FP_REG_SWZ_W_SHIFT 15
|
||||
#define NV40_FP_REG_SWZ_W_MASK (3 << 15)
|
||||
# define NV40_FP_SWIZZLE_X 0
|
||||
# define NV40_FP_SWIZZLE_Y 1
|
||||
# define NV40_FP_SWIZZLE_Z 2
|
||||
# define NV40_FP_SWIZZLE_W 3
|
||||
#define NV40_FP_REG_NEGATE (1 << 17)
|
||||
|
||||
#endif
|
||||
688
src/mesa/drivers/dri/nouveau/nv40_vertprog.c
Normal file
688
src/mesa/drivers/dri/nouveau/nv40_vertprog.c
Normal file
|
|
@ -0,0 +1,688 @@
|
|||
#include "nouveau_shader.h"
|
||||
#include "nouveau_msg.h"
|
||||
#include "nv40_shader.h"
|
||||
|
||||
extern nvsSwzComp NV20VP_TX_SWIZZLE[4];
|
||||
extern void NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz);
|
||||
|
||||
/*****************************************************************************
|
||||
* Assembly routines
|
||||
*/
|
||||
static int
|
||||
NV40VPSupportsOpcode(nvsFunc * shader, nvsOpcode op)
|
||||
{
|
||||
if (shader->GetOPTXFromSOP(op, NULL))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPSetOpcode(nvsFunc *shader, unsigned int opcode, int slot)
|
||||
{
|
||||
if (slot) {
|
||||
shader->inst[1] &= ~NV40_VP_INST_SCA_OPCODE_MASK;
|
||||
shader->inst[1] |= (opcode << NV40_VP_INST_SCA_OPCODE_SHIFT);
|
||||
} else {
|
||||
shader->inst[1] &= ~NV40_VP_INST_VEC_OPCODE_MASK;
|
||||
shader->inst[1] |= (opcode << NV40_VP_INST_VEC_OPCODE_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPSetCCUpdate(nvsFunc *shader)
|
||||
{
|
||||
shader->inst[0] |= NV40_VP_INST_COND_UPDATE_ENABLE;
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPSetCondition(nvsFunc *shader, int on, nvsCond cond, int reg,
|
||||
nvsSwzComp *swizzle)
|
||||
{
|
||||
unsigned int hwcond;
|
||||
|
||||
if (on ) shader->inst[0] |= NV40_VP_INST_COND_TEST_ENABLE;
|
||||
else shader->inst[0] &= ~NV40_VP_INST_COND_TEST_ENABLE;
|
||||
if (reg) shader->inst[0] |= NV40_VP_INST_COND_REG_SELECT_1;
|
||||
else shader->inst[0] &= ~NV40_VP_INST_COND_REG_SELECT_1;
|
||||
|
||||
switch (cond) {
|
||||
case NVS_COND_TR: hwcond = NV40_VP_INST_COND_TR; break;
|
||||
case NVS_COND_FL: hwcond = NV40_VP_INST_COND_FL; break;
|
||||
case NVS_COND_LT: hwcond = NV40_VP_INST_COND_LT; break;
|
||||
case NVS_COND_GT: hwcond = NV40_VP_INST_COND_GT; break;
|
||||
case NVS_COND_NE: hwcond = NV40_VP_INST_COND_NE; break;
|
||||
case NVS_COND_EQ: hwcond = NV40_VP_INST_COND_EQ; break;
|
||||
case NVS_COND_GE: hwcond = NV40_VP_INST_COND_GE; break;
|
||||
case NVS_COND_LE: hwcond = NV40_VP_INST_COND_LE; break;
|
||||
default:
|
||||
WARN_ONCE("unknown vp cond %d\n", cond);
|
||||
hwcond = NV40_VP_INST_COND_TR;
|
||||
break;
|
||||
}
|
||||
shader->inst[0] &= ~NV40_VP_INST_COND_MASK;
|
||||
shader->inst[0] |= (hwcond << NV40_VP_INST_COND_SHIFT);
|
||||
|
||||
shader->inst[0] &= ~NV40_VP_INST_COND_SWZ_ALL_MASK;
|
||||
shader->inst[0] |= (swizzle[NVS_SWZ_X] << NV40_VP_INST_COND_SWZ_X_SHIFT);
|
||||
shader->inst[0] |= (swizzle[NVS_SWZ_Y] << NV40_VP_INST_COND_SWZ_Y_SHIFT);
|
||||
shader->inst[0] |= (swizzle[NVS_SWZ_Z] << NV40_VP_INST_COND_SWZ_Z_SHIFT);
|
||||
shader->inst[0] |= (swizzle[NVS_SWZ_W] << NV40_VP_INST_COND_SWZ_W_SHIFT);
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPSetResult(nvsFunc *shader, nvsRegister * dest, unsigned int mask,
|
||||
int slot)
|
||||
{
|
||||
unsigned int hwmask = 0;
|
||||
|
||||
if (mask & SMASK_X) hwmask |= (1 << 3);
|
||||
if (mask & SMASK_Y) hwmask |= (1 << 2);
|
||||
if (mask & SMASK_Z) hwmask |= (1 << 1);
|
||||
if (mask & SMASK_W) hwmask |= (1 << 0);
|
||||
|
||||
if (dest->file == NVS_FILE_RESULT) {
|
||||
int hwidx;
|
||||
|
||||
switch (dest->index) {
|
||||
case NVS_FR_POSITION : hwidx = NV40_VP_INST_DEST_POS; break;
|
||||
case NVS_FR_COL0 : hwidx = NV40_VP_INST_DEST_COL0; break;
|
||||
case NVS_FR_COL1 : hwidx = NV40_VP_INST_DEST_COL1; break;
|
||||
case NVS_FR_BFC0 : hwidx = NV40_VP_INST_DEST_BFC0; break;
|
||||
case NVS_FR_BFC1 : hwidx = NV40_VP_INST_DEST_BFC1; break;
|
||||
case NVS_FR_FOGCOORD : hwidx = NV40_VP_INST_DEST_FOGC; break;
|
||||
case NVS_FR_POINTSZ : hwidx = NV40_VP_INST_DEST_PSZ; break;
|
||||
case NVS_FR_TEXCOORD0: hwidx = NV40_VP_INST_DEST_TC(0); break;
|
||||
case NVS_FR_TEXCOORD1: hwidx = NV40_VP_INST_DEST_TC(1); break;
|
||||
case NVS_FR_TEXCOORD2: hwidx = NV40_VP_INST_DEST_TC(2); break;
|
||||
case NVS_FR_TEXCOORD3: hwidx = NV40_VP_INST_DEST_TC(3); break;
|
||||
case NVS_FR_TEXCOORD4: hwidx = NV40_VP_INST_DEST_TC(4); break;
|
||||
case NVS_FR_TEXCOORD5: hwidx = NV40_VP_INST_DEST_TC(5); break;
|
||||
case NVS_FR_TEXCOORD6: hwidx = NV40_VP_INST_DEST_TC(6); break;
|
||||
case NVS_FR_TEXCOORD7: hwidx = NV40_VP_INST_DEST_TC(7); break;
|
||||
default:
|
||||
WARN_ONCE("unknown vtxprog output %d\n", dest->index);
|
||||
hwidx = 0;
|
||||
break;
|
||||
}
|
||||
shader->inst[3] &= ~NV40_VP_INST_DEST_MASK;
|
||||
shader->inst[3] |= (hwidx << NV40_VP_INST_DEST_SHIFT);
|
||||
|
||||
if (slot) shader->inst[3] |= NV40_VP_INST_SCA_RESULT;
|
||||
else shader->inst[0] |= NV40_VP_INST_VEC_RESULT;
|
||||
} else {
|
||||
/* NVS_FILE_TEMP || NVS_FILE_ADDRESS */
|
||||
if (slot) {
|
||||
shader->inst[3] &= ~NV40_VP_INST_SCA_RESULT;
|
||||
shader->inst[3] &= ~NV40_VP_INST_SCA_DEST_TEMP_MASK;
|
||||
shader->inst[3] |= (dest->index << NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
|
||||
} else {
|
||||
shader->inst[0] &= ~NV40_VP_INST_VEC_RESULT;
|
||||
shader->inst[0] &= ~(NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20));
|
||||
shader->inst[0] |= (dest->index << NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
if (slot) {
|
||||
shader->inst[3] &= ~NV40_VP_INST_SCA_WRITEMASK_MASK;
|
||||
shader->inst[3] |= (hwmask << NV40_VP_INST_SCA_WRITEMASK_SHIFT);
|
||||
} else {
|
||||
shader->inst[3] &= ~NV40_VP_INST_VEC_WRITEMASK_MASK;
|
||||
shader->inst[3] |= (hwmask << NV40_VP_INST_VEC_WRITEMASK_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPInsertSource(nvsFunc *shader, unsigned int hw, int pos)
|
||||
{
|
||||
switch (pos) {
|
||||
case 0:
|
||||
shader->inst[1] &= ~NV40_VP_INST_SRC0H_MASK;
|
||||
shader->inst[2] &= ~NV40_VP_INST_SRC0L_MASK;
|
||||
shader->inst[1] |= ((hw & NV40_VP_SRC0_HIGH_MASK) >>
|
||||
NV40_VP_SRC0_HIGH_SHIFT)
|
||||
<< NV40_VP_INST_SRC0H_SHIFT;
|
||||
shader->inst[2] |= (hw & NV40_VP_SRC0_LOW_MASK)
|
||||
<< NV40_VP_INST_SRC0L_SHIFT;
|
||||
break;
|
||||
case 1:
|
||||
shader->inst[2] &= ~NV40_VP_INST_SRC1_MASK;
|
||||
shader->inst[2] |= hw
|
||||
<< NV40_VP_INST_SRC1_SHIFT;
|
||||
break;
|
||||
case 2:
|
||||
shader->inst[2] &= ~NV40_VP_INST_SRC2H_MASK;
|
||||
shader->inst[3] &= ~NV40_VP_INST_SRC2L_MASK;
|
||||
shader->inst[2] |= ((hw & NV40_VP_SRC2_HIGH_MASK) >>
|
||||
NV40_VP_SRC2_HIGH_SHIFT)
|
||||
<< NV40_VP_INST_SRC2H_SHIFT;
|
||||
shader->inst[3] |= (hw & NV40_VP_SRC2_LOW_MASK)
|
||||
<< NV40_VP_INST_SRC2L_SHIFT;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPSetSource(nvsFunc *shader, nvsRegister * src, int pos)
|
||||
{
|
||||
unsigned int hw = 0;
|
||||
|
||||
switch (src->file) {
|
||||
case NVS_FILE_ADDRESS:
|
||||
break;
|
||||
case NVS_FILE_ATTRIB:
|
||||
hw |= (NV40_VP_SRC_REG_TYPE_INPUT << NV40_VP_SRC_REG_TYPE_SHIFT);
|
||||
|
||||
shader->inst[1] &= ~NV40_VP_INST_INPUT_SRC_MASK;
|
||||
shader->inst[1] |= (src->index << NV40_VP_INST_INPUT_SRC_SHIFT);
|
||||
if (src->indexed) {
|
||||
shader->inst[0] |= NV40_VP_INST_INDEX_INPUT;
|
||||
if (src->addr_reg)
|
||||
shader->inst[0] |= NV40_VP_INST_ADDR_REG_SELECT_1;
|
||||
else
|
||||
shader->inst[0] &= ~NV40_VP_INST_ADDR_REG_SELECT_1;
|
||||
shader->inst[0] &= ~NV40_VP_INST_ADDR_SWZ_SHIFT;
|
||||
shader->inst[0] |= (src->addr_comp << NV40_VP_INST_ADDR_SWZ_SHIFT);
|
||||
} else
|
||||
shader->inst[0] &= ~NV40_VP_INST_INDEX_INPUT;
|
||||
break;
|
||||
case NVS_FILE_CONST:
|
||||
hw |= (NV40_VP_SRC_REG_TYPE_CONST << NV40_VP_SRC_REG_TYPE_SHIFT);
|
||||
|
||||
shader->inst[1] &= ~NV40_VP_INST_CONST_SRC_MASK;
|
||||
shader->inst[1] |= (src->index << NV40_VP_INST_CONST_SRC_SHIFT);
|
||||
if (src->indexed) {
|
||||
shader->inst[3] |= NV40_VP_INST_INDEX_CONST;
|
||||
if (src->addr_reg)
|
||||
shader->inst[0] |= NV40_VP_INST_ADDR_REG_SELECT_1;
|
||||
else
|
||||
shader->inst[0] &= ~NV40_VP_INST_ADDR_REG_SELECT_1;
|
||||
shader->inst[0] &= ~NV40_VP_INST_ADDR_SWZ_MASK;
|
||||
shader->inst[0] |= (src->addr_comp << NV40_VP_INST_ADDR_SWZ_SHIFT);
|
||||
} else
|
||||
shader->inst[3] &= ~NV40_VP_INST_INDEX_CONST;
|
||||
break;
|
||||
case NVS_FILE_TEMP:
|
||||
hw |= (NV40_VP_SRC_REG_TYPE_TEMP << NV40_VP_SRC_REG_TYPE_SHIFT);
|
||||
hw |= (src->index << NV40_VP_SRC_TEMP_SRC_SHIFT);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown source file %d\n", src->file);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (src->file != NVS_FILE_ADDRESS) {
|
||||
if (src->negate)
|
||||
hw |= NV40_VP_SRC_NEGATE;
|
||||
if (src->abs)
|
||||
shader->inst[0] |= (1 << (21 + pos));
|
||||
else
|
||||
shader->inst[0] &= ~(1 << (21 + pos));
|
||||
hw |= (src->swizzle[0] << NV40_VP_SRC_SWZ_X_SHIFT);
|
||||
hw |= (src->swizzle[1] << NV40_VP_SRC_SWZ_Y_SHIFT);
|
||||
hw |= (src->swizzle[2] << NV40_VP_SRC_SWZ_Z_SHIFT);
|
||||
hw |= (src->swizzle[3] << NV40_VP_SRC_SWZ_W_SHIFT);
|
||||
|
||||
NV40VPInsertSource(shader, hw, pos);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPInitInstruction(nvsFunc *shader)
|
||||
{
|
||||
unsigned int hwsrc = 0;
|
||||
|
||||
shader->inst[0] = /*NV40_VP_INST_VEC_RESULT | */
|
||||
NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
|
||||
shader->inst[1] = 0;
|
||||
shader->inst[2] = 0;
|
||||
shader->inst[3] = NV40_VP_INST_SCA_RESULT |
|
||||
NV40_VP_INST_SCA_DEST_TEMP_MASK |
|
||||
NV40_VP_INST_DEST_MASK;
|
||||
|
||||
hwsrc = (NV40_VP_SRC_REG_TYPE_INPUT << NV40_VP_SRC_REG_TYPE_SHIFT) |
|
||||
(NVS_SWZ_X << NV40_VP_SRC_SWZ_X_SHIFT) |
|
||||
(NVS_SWZ_Y << NV40_VP_SRC_SWZ_Y_SHIFT) |
|
||||
(NVS_SWZ_Z << NV40_VP_SRC_SWZ_Z_SHIFT) |
|
||||
(NVS_SWZ_W << NV40_VP_SRC_SWZ_W_SHIFT);
|
||||
NV40VPInsertSource(shader, hwsrc, 0);
|
||||
NV40VPInsertSource(shader, hwsrc, 1);
|
||||
NV40VPInsertSource(shader, hwsrc, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPSetLastInst(nvsFunc *shader)
|
||||
{
|
||||
shader->inst[3] |= 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Disassembly routines
|
||||
*/
|
||||
static int
|
||||
NV40VPHasMergedInst(nvsFunc * shader)
|
||||
{
|
||||
if (shader->GetOpcodeHW(shader, 0) != NV40_VP_INST_OP_NOP &&
|
||||
shader->GetOpcodeHW(shader, 1) != NV40_VP_INST_OP_NOP)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV40VPGetOpcodeHW(nvsFunc * shader, int slot)
|
||||
{
|
||||
int op;
|
||||
|
||||
if (slot)
|
||||
op = (shader->inst[1] & NV40_VP_INST_SCA_OPCODE_MASK)
|
||||
>> NV40_VP_INST_SCA_OPCODE_SHIFT;
|
||||
else
|
||||
op = (shader->inst[1] & NV40_VP_INST_VEC_OPCODE_MASK)
|
||||
>> NV40_VP_INST_VEC_OPCODE_SHIFT;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
static nvsRegFile
|
||||
NV40VPGetDestFile(nvsFunc * shader, int merged)
|
||||
{
|
||||
nvsOpcode op;
|
||||
|
||||
op = shader->GetOpcode(shader, merged);
|
||||
switch (op) {
|
||||
case NVS_OP_ARL:
|
||||
case NVS_OP_ARR:
|
||||
case NVS_OP_ARA:
|
||||
case NVS_OP_POPA:
|
||||
return NVS_FILE_ADDRESS;
|
||||
default:
|
||||
if (shader->GetOpcodeSlot(shader, merged)) {
|
||||
if (shader->inst[3] & NV40_VP_INST_SCA_RESULT)
|
||||
return NVS_FILE_RESULT;
|
||||
}
|
||||
else {
|
||||
if (shader->inst[0] & NV40_VP_INST_VEC_RESULT)
|
||||
return NVS_FILE_RESULT;
|
||||
}
|
||||
return NVS_FILE_TEMP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV40VPGetDestID(nvsFunc * shader, int merged)
|
||||
{
|
||||
int id;
|
||||
|
||||
switch (shader->GetDestFile(shader, merged)) {
|
||||
case NVS_FILE_RESULT:
|
||||
id = ((shader->inst[3] & NV40_VP_INST_DEST_MASK)
|
||||
>> NV40_VP_INST_DEST_SHIFT);
|
||||
switch (id) {
|
||||
case NV40_VP_INST_DEST_POS : return NVS_FR_POSITION;
|
||||
case NV40_VP_INST_DEST_COL0: return NVS_FR_COL0;
|
||||
case NV40_VP_INST_DEST_COL1: return NVS_FR_COL1;
|
||||
case NV40_VP_INST_DEST_BFC0: return NVS_FR_BFC0;
|
||||
case NV40_VP_INST_DEST_BFC1: return NVS_FR_BFC1;
|
||||
case NV40_VP_INST_DEST_FOGC: {
|
||||
int mask = shader->GetDestMask(shader, merged);
|
||||
switch (mask) {
|
||||
case SMASK_X: return NVS_FR_FOGCOORD;
|
||||
case SMASK_Y: return NVS_FR_CLIP0;
|
||||
case SMASK_Z: return NVS_FR_CLIP1;
|
||||
case SMASK_W: return NVS_FR_CLIP2;
|
||||
default:
|
||||
printf("more than 1 mask component set in FOGC writemask!\n");
|
||||
return NVS_FR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
case NV40_VP_INST_DEST_PSZ:
|
||||
{
|
||||
int mask = shader->GetDestMask(shader, merged);
|
||||
switch (mask) {
|
||||
case SMASK_X: return NVS_FR_POINTSZ;
|
||||
case SMASK_Y: return NVS_FR_CLIP3;
|
||||
case SMASK_Z: return NVS_FR_CLIP4;
|
||||
case SMASK_W: return NVS_FR_CLIP5;
|
||||
default:
|
||||
printf("more than 1 mask component set in PSZ writemask!\n");
|
||||
return NVS_FR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
case NV40_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0;
|
||||
case NV40_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1;
|
||||
case NV40_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2;
|
||||
case NV40_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3;
|
||||
case NV40_VP_INST_DEST_TC(4): return NVS_FR_TEXCOORD4;
|
||||
case NV40_VP_INST_DEST_TC(5): return NVS_FR_TEXCOORD5;
|
||||
case NV40_VP_INST_DEST_TC(6): return NVS_FR_TEXCOORD6;
|
||||
case NV40_VP_INST_DEST_TC(7): return NVS_FR_TEXCOORD7;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
case NVS_FILE_ADDRESS:
|
||||
/* Instructions that write address regs are encoded as if
|
||||
* they would write temps.
|
||||
*/
|
||||
case NVS_FILE_TEMP:
|
||||
if (shader->GetOpcodeSlot(shader, merged))
|
||||
id = ((shader->inst[3] & NV40_VP_INST_SCA_DEST_TEMP_MASK)
|
||||
>> NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
|
||||
else
|
||||
id = ((shader->inst[0] & NV40_VP_INST_VEC_DEST_TEMP_MASK)
|
||||
>> NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
|
||||
return id;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV40VPGetDestMask(nvsFunc * shader, int merged)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (shader->GetOpcodeSlot(shader, merged)) {
|
||||
if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_X) mask |= SMASK_X;
|
||||
if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_Y) mask |= SMASK_Y;
|
||||
if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_Z) mask |= SMASK_Z;
|
||||
if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_W) mask |= SMASK_W;
|
||||
} else {
|
||||
if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_X) mask |= SMASK_X;
|
||||
if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_Y) mask |= SMASK_Y;
|
||||
if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_Z) mask |= SMASK_Z;
|
||||
if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_W) mask |= SMASK_W;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
NV40VPGetSourceHW(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
struct _op_xlat *opr;
|
||||
unsigned int src;
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr)
|
||||
return -1;
|
||||
|
||||
switch (opr->srcpos[pos]) {
|
||||
case 0:
|
||||
src = ((shader->inst[1] & NV40_VP_INST_SRC0H_MASK)
|
||||
>> NV40_VP_INST_SRC0H_SHIFT)
|
||||
<< NV40_VP_SRC0_HIGH_SHIFT;
|
||||
src |= ((shader->inst[2] & NV40_VP_INST_SRC0L_MASK)
|
||||
>> NV40_VP_INST_SRC0L_SHIFT);
|
||||
break;
|
||||
case 1:
|
||||
src = ((shader->inst[2] & NV40_VP_INST_SRC1_MASK)
|
||||
>> NV40_VP_INST_SRC1_SHIFT);
|
||||
break;
|
||||
case 2:
|
||||
src = ((shader->inst[2] & NV40_VP_INST_SRC2H_MASK)
|
||||
>> NV40_VP_INST_SRC2H_SHIFT)
|
||||
<< NV40_VP_SRC2_HIGH_SHIFT;
|
||||
src |= ((shader->inst[3] & NV40_VP_INST_SRC2L_MASK)
|
||||
>> NV40_VP_INST_SRC2L_SHIFT);
|
||||
break;
|
||||
default:
|
||||
src = -1;
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static nvsRegFile
|
||||
NV40VPGetSourceFile(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
unsigned int src;
|
||||
struct _op_xlat *opr;
|
||||
int file;
|
||||
|
||||
opr = shader->GetOPTXRec(shader, merged);
|
||||
if (!opr || opr->srcpos[pos] == -1)
|
||||
return -1;
|
||||
|
||||
switch (opr->srcpos[pos]) {
|
||||
case SPOS_ADDRESS: return NVS_FILE_ADDRESS;
|
||||
default:
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
file = (src & NV40_VP_SRC_REG_TYPE_MASK) >> NV40_VP_SRC_REG_TYPE_SHIFT;
|
||||
|
||||
switch (file) {
|
||||
case NV40_VP_SRC_REG_TYPE_TEMP : return NVS_FILE_TEMP;
|
||||
case NV40_VP_SRC_REG_TYPE_INPUT: return NVS_FILE_ATTRIB;
|
||||
case NV40_VP_SRC_REG_TYPE_CONST: return NVS_FILE_CONST;
|
||||
default:
|
||||
return NVS_FILE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV40VPGetSourceID(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
switch (shader->GetSourceFile(shader, merged, pos)) {
|
||||
case NVS_FILE_ATTRIB:
|
||||
switch ((shader->inst[1] & NV40_VP_INST_INPUT_SRC_MASK)
|
||||
>> NV40_VP_INST_INPUT_SRC_SHIFT) {
|
||||
case NV40_VP_INST_IN_POS: return NVS_FR_POSITION;
|
||||
case NV40_VP_INST_IN_WEIGHT: return NVS_FR_WEIGHT;
|
||||
case NV40_VP_INST_IN_NORMAL: return NVS_FR_NORMAL;
|
||||
case NV40_VP_INST_IN_COL0: return NVS_FR_COL0;
|
||||
case NV40_VP_INST_IN_COL1: return NVS_FR_COL1;
|
||||
case NV40_VP_INST_IN_FOGC: return NVS_FR_FOGCOORD;
|
||||
case NV40_VP_INST_IN_TC(0): return NVS_FR_TEXCOORD0;
|
||||
case NV40_VP_INST_IN_TC(1): return NVS_FR_TEXCOORD1;
|
||||
case NV40_VP_INST_IN_TC(2): return NVS_FR_TEXCOORD2;
|
||||
case NV40_VP_INST_IN_TC(3): return NVS_FR_TEXCOORD3;
|
||||
case NV40_VP_INST_IN_TC(4): return NVS_FR_TEXCOORD4;
|
||||
case NV40_VP_INST_IN_TC(5): return NVS_FR_TEXCOORD5;
|
||||
case NV40_VP_INST_IN_TC(6): return NVS_FR_TEXCOORD6;
|
||||
case NV40_VP_INST_IN_TC(7): return NVS_FR_TEXCOORD7;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case NVS_FILE_CONST:
|
||||
return ((shader->inst[1] & NV40_VP_INST_CONST_SRC_MASK)
|
||||
>> NV40_VP_INST_CONST_SRC_SHIFT);
|
||||
case NVS_FILE_TEMP:
|
||||
{
|
||||
unsigned int src;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
return ((src & NV40_VP_SRC_TEMP_SRC_MASK) >>
|
||||
NV40_VP_SRC_TEMP_SRC_SHIFT);
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
NV40VPGetSourceNegate(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
unsigned int src;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
|
||||
if (src == -1)
|
||||
return -1;
|
||||
return ((src & NV40_VP_SRC_NEGATE) ? 1 : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz)
|
||||
{
|
||||
unsigned int src;
|
||||
int swzbits;
|
||||
|
||||
src = shader->GetSourceHW(shader, merged, pos);
|
||||
swzbits = (src & NV40_VP_SRC_SWZ_ALL_MASK) >> NV40_VP_SRC_SWZ_ALL_SHIFT;
|
||||
NV20VPTXSwizzle(swzbits, swz);
|
||||
}
|
||||
|
||||
static int
|
||||
NV40VPGetSourceIndexed(nvsFunc * shader, int merged, int pos)
|
||||
{
|
||||
switch (shader->GetSourceFile(shader, merged, pos)) {
|
||||
case NVS_FILE_ATTRIB:
|
||||
return ((shader->inst[0] & NV40_VP_INST_INDEX_INPUT) ? 1 : 0);
|
||||
case NVS_FILE_CONST:
|
||||
return ((shader->inst[3] & NV40_VP_INST_INDEX_CONST) ? 1 : 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static nvsSwzComp
|
||||
NV40VPGetAddressRegSwizzle(nvsFunc * shader)
|
||||
{
|
||||
nvsSwzComp swz;
|
||||
|
||||
swz = NV20VP_TX_SWIZZLE[(shader->inst[0] & NV40_VP_INST_ADDR_SWZ_MASK)
|
||||
>> NV40_VP_INST_ADDR_SWZ_SHIFT];
|
||||
return swz;
|
||||
}
|
||||
|
||||
static int
|
||||
NV40VPSupportsConditional(nvsFunc * shader)
|
||||
{
|
||||
/*FIXME: Is this true of all ops? */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
NV40VPGetConditionUpdate(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[0] & NV40_VP_INST_COND_UPDATE_ENABLE) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV40VPGetConditionTest(nvsFunc * shader)
|
||||
{
|
||||
int op;
|
||||
|
||||
/* The condition test is unconditionally enabled on some
|
||||
* instructions. ie: the condition test bit does *NOT* have
|
||||
* to be set.
|
||||
*
|
||||
* FIXME: check other relevant ops for this situation.
|
||||
*/
|
||||
op = shader->GetOpcodeHW(shader, 1);
|
||||
switch (op) {
|
||||
case NV40_VP_INST_OP_BRA:
|
||||
return 1;
|
||||
default:
|
||||
return ((shader->inst[0] & NV40_VP_INST_COND_TEST_ENABLE) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
static nvsCond
|
||||
NV40VPGetCondition(nvsFunc * shader)
|
||||
{
|
||||
int cond;
|
||||
|
||||
cond = ((shader->inst[0] & NV40_VP_INST_COND_MASK)
|
||||
>> NV40_VP_INST_COND_SHIFT);
|
||||
|
||||
switch (cond) {
|
||||
case NV40_VP_INST_COND_FL: return NVS_COND_FL;
|
||||
case NV40_VP_INST_COND_LT: return NVS_COND_LT;
|
||||
case NV40_VP_INST_COND_EQ: return NVS_COND_EQ;
|
||||
case NV40_VP_INST_COND_LE: return NVS_COND_LE;
|
||||
case NV40_VP_INST_COND_GT: return NVS_COND_GT;
|
||||
case NV40_VP_INST_COND_NE: return NVS_COND_NE;
|
||||
case NV40_VP_INST_COND_GE: return NVS_COND_GE;
|
||||
case NV40_VP_INST_COND_TR: return NVS_COND_TR;
|
||||
default:
|
||||
return NVS_COND_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV40VPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
|
||||
{
|
||||
int swzbits;
|
||||
|
||||
swzbits = (shader->inst[0] & NV40_VP_INST_COND_SWZ_ALL_MASK)
|
||||
>> NV40_VP_INST_COND_SWZ_ALL_SHIFT;
|
||||
NV20VPTXSwizzle(swzbits, swz);
|
||||
}
|
||||
|
||||
static int
|
||||
NV40VPGetCondRegID(nvsFunc * shader)
|
||||
{
|
||||
return ((shader->inst[0] & NV40_VP_INST_COND_REG_SELECT_1) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
NV40VPGetBranch(nvsFunc * shader)
|
||||
{
|
||||
int addr;
|
||||
|
||||
addr = ((shader->inst[2] & NV40_VP_INST_IADDRH_MASK)
|
||||
>> NV40_VP_INST_IADDRH_SHIFT) << 3;
|
||||
addr |= ((shader->inst[3] & NV40_VP_INST_IADDRL_MASK)
|
||||
>> NV40_VP_INST_IADDRL_SHIFT);
|
||||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
NV40VPInitShaderFuncs(nvsFunc * shader)
|
||||
{
|
||||
/* Inherit NV30 VP code, we share some of it */
|
||||
NV30VPInitShaderFuncs(shader);
|
||||
|
||||
/* Limits */
|
||||
shader->MaxInst = 4096;
|
||||
shader->MaxAttrib = 16;
|
||||
shader->MaxTemp = 32;
|
||||
shader->MaxAddress = 2;
|
||||
shader->MaxConst = 256;
|
||||
shader->caps = SCAP_SRC_ABS;
|
||||
|
||||
/* Add extra opcodes for NV40+ */
|
||||
// MOD_OPCODE(NVVP_TX_VOP, NV40_VP_INST_OP_TXWHAT, NVS_OP_TEX , 0, 4, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV40_VP_INST_OP_PUSHA, NVS_OP_PUSHA, 3, -1, -1);
|
||||
MOD_OPCODE(NVVP_TX_SOP, NV40_VP_INST_OP_POPA , NVS_OP_POPA , -1, -1, -1);
|
||||
|
||||
shader->InitInstruction = NV40VPInitInstruction;
|
||||
shader->SupportsOpcode = NV40VPSupportsOpcode;
|
||||
shader->SetOpcode = NV40VPSetOpcode;
|
||||
shader->SetCCUpdate = NV40VPSetCCUpdate;
|
||||
shader->SetCondition = NV40VPSetCondition;
|
||||
shader->SetResult = NV40VPSetResult;
|
||||
shader->SetSource = NV40VPSetSource;
|
||||
shader->SetLastInst = NV40VPSetLastInst;
|
||||
|
||||
shader->HasMergedInst = NV40VPHasMergedInst;
|
||||
shader->GetOpcodeHW = NV40VPGetOpcodeHW;
|
||||
|
||||
shader->GetDestFile = NV40VPGetDestFile;
|
||||
shader->GetDestID = NV40VPGetDestID;
|
||||
shader->GetDestMask = NV40VPGetDestMask;
|
||||
|
||||
shader->GetSourceHW = NV40VPGetSourceHW;
|
||||
shader->GetSourceFile = NV40VPGetSourceFile;
|
||||
shader->GetSourceID = NV40VPGetSourceID;
|
||||
shader->GetSourceNegate = NV40VPGetSourceNegate;
|
||||
shader->GetSourceSwizzle = NV40VPGetSourceSwizzle;
|
||||
shader->GetSourceIndexed = NV40VPGetSourceIndexed;
|
||||
|
||||
shader->GetRelAddressSwizzle = NV40VPGetAddressRegSwizzle;
|
||||
|
||||
shader->SupportsConditional = NV40VPSupportsConditional;
|
||||
shader->GetConditionUpdate = NV40VPGetConditionUpdate;
|
||||
shader->GetConditionTest = NV40VPGetConditionTest;
|
||||
shader->GetCondition = NV40VPGetCondition;
|
||||
shader->GetCondRegSwizzle = NV40VPGetCondRegSwizzle;
|
||||
shader->GetCondRegID = NV40VPGetCondRegID;
|
||||
|
||||
shader->GetBranch = NV40VPGetBranch;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue