nouveau: say goodbye to the old DRI driver...

This commit is contained in:
Stephane Marchesin 2008-07-14 01:03:07 +02:00
parent 4fab47b13c
commit 93115c4b23
63 changed files with 1 additions and 21640 deletions

View file

@ -70,4 +70,4 @@ WINDOW_SYSTEM=dri
# gamma are missing because they have not been converted to use the new
# interface.
DRI_DIRS = i810 i915 mach64 mga r128 r200 r300 radeon s3v \
savage sis tdfx trident unichrome ffb nouveau
savage sis tdfx trident unichrome ffb

View file

@ -1,54 +0,0 @@
# src/mesa/drivers/dri/nouveau/Makefile
TOP = ../../../../..
include $(TOP)/configs/current
LIBNAME = nouveau_dri.so
MINIGLX_SOURCES =
DRIVER_SOURCES = \
nouveau_bufferobj.c \
nouveau_card.c \
nouveau_context.c \
nouveau_driver.c \
nouveau_fbo.c \
nouveau_fifo.c \
nouveau_lock.c \
nouveau_mem.c \
nouveau_object.c \
nouveau_screen.c \
nouveau_span.c \
nouveau_state.c \
nouveau_state_cache.c \
nouveau_shader.c \
nouveau_shader_0.c \
nouveau_shader_1.c \
nouveau_shader_2.c \
nouveau_tex.c \
nouveau_swtcl.c \
nouveau_sync.c \
nouveau_query.c \
nv04_state.c \
nv04_swtcl.c \
nv10_state.c \
nv10_swtcl.c \
nv20_state.c \
nv20_vertprog.c \
nv30_state.c \
nv30_fragprog.c \
nv30_vertprog.c \
nv40_fragprog.c \
nv40_vertprog.c \
nv50_state.c
C_SOURCES = \
$(COMMON_SOURCES) \
$(DRIVER_SOURCES)
ASM_SOURCES =
include ../Makefile.template
symlinks:

View file

@ -1,627 +0,0 @@
#include "bufferobj.h"
#include "enums.h"
#include "nouveau_bufferobj.h"
#include "nouveau_context.h"
#include "nouveau_drm.h"
#include "nouveau_mem.h"
#include "nouveau_msg.h"
#include "nouveau_object.h"
#define NOUVEAU_MEM_FREE(mem) do { \
nouveau_mem_free(ctx, (mem)); \
(mem) = NULL; \
} while(0)
#define DEBUG(fmt,args...) do { \
if (NOUVEAU_DEBUG & DEBUG_BUFFEROBJ) { \
fprintf(stderr, "%s: "fmt, __func__, ##args); \
} \
} while(0)
static GLboolean
nouveau_bo_download_from_screen(GLcontext *ctx, GLuint offset, GLuint size,
struct gl_buffer_object *bo)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
nouveau_mem *in_mem;
DEBUG("bo=%p, offset=%d, size=%d\n", bo, offset, size);
/* If there's a permanent backing store, blit directly into it */
if (nbo->cpu_mem) {
if (nbo->cpu_mem != nbo->gpu_mem) {
DEBUG("..cpu_mem\n");
nouveau_memformat_flat_emit(ctx, nbo->cpu_mem,
nbo->gpu_mem,
offset, offset, size);
}
} else {
DEBUG("..sys_mem\n");
in_mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_AGP, size, 0);
if (in_mem) {
DEBUG("....via GART\n");
/* otherwise, try blitting to faster memory and
* copying from there
*/
nouveau_memformat_flat_emit(ctx, in_mem, nbo->gpu_mem,
0, offset, size);
nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier,
NvSubMemFormat);
_mesa_memcpy(nbo->cpu_mem_sys + offset,
in_mem->map, size);
NOUVEAU_MEM_FREE(in_mem);
} else {
DEBUG("....direct VRAM copy\n");
/* worst case, copy directly from vram */
_mesa_memcpy(nbo->cpu_mem_sys + offset,
nbo->gpu_mem + offset,
size);
}
}
return GL_TRUE;
}
static GLboolean
nouveau_bo_upload_to_screen(GLcontext *ctx, GLuint offset, GLuint size,
struct gl_buffer_object *bo)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
nouveau_mem *out_mem;
DEBUG("bo=%p, offset=%d, size=%d\n", bo, offset, size);
if (nbo->cpu_mem) {
if (nbo->cpu_mem != nbo->gpu_mem) {
DEBUG("..cpu_mem\n");
nouveau_memformat_flat_emit(ctx, nbo->gpu_mem,
nbo->cpu_mem,
offset, offset, size);
}
} else {
out_mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_AGP |
NOUVEAU_MEM_MAPPED,
size, 0);
if (out_mem) {
DEBUG("....via GART\n");
_mesa_memcpy(out_mem->map,
nbo->cpu_mem_sys + offset, size);
nouveau_memformat_flat_emit(ctx, nbo->gpu_mem, out_mem,
offset, 0, size);
nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier,
NvSubMemFormat);
NOUVEAU_MEM_FREE(out_mem);
} else {
DEBUG("....direct VRAM copy\n");
_mesa_memcpy(nbo->gpu_mem->map + offset,
nbo->cpu_mem_sys + offset,
size);
}
}
return GL_TRUE;
}
GLboolean
nouveau_bo_move_in(GLcontext *ctx, struct gl_buffer_object *bo)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
DEBUG("bo=%p\n", bo);
if (bo->OnCard)
return GL_TRUE;
assert(nbo->gpu_mem_flags);
nbo->gpu_mem = nouveau_mem_alloc(ctx, nbo->gpu_mem_flags |
NOUVEAU_MEM_MAPPED,
bo->Size, 0);
assert(nbo->gpu_mem);
if (nbo->cpu_mem_flags) {
if ((nbo->cpu_mem_flags|NOUVEAU_MEM_MAPPED) != nbo->gpu_mem->type) {
DEBUG("..need cpu_mem buffer\n");
nbo->cpu_mem = nouveau_mem_alloc(ctx,
nbo->cpu_mem_flags |
NOUVEAU_MEM_MAPPED,
bo->Size, 0);
if (nbo->cpu_mem) {
DEBUG("....alloc ok, kill sys_mem buffer\n");
_mesa_memcpy(nbo->cpu_mem->map,
nbo->cpu_mem_sys, bo->Size);
FREE(nbo->cpu_mem_sys);
}
} else {
DEBUG("..cpu direct access to GPU buffer\n");
nbo->cpu_mem = nbo->gpu_mem;
}
}
nouveau_bo_upload_to_screen(ctx, 0, bo->Size, bo);
bo->OnCard = GL_TRUE;
return GL_TRUE;
}
GLboolean
nouveau_bo_move_out(GLcontext *ctx, struct gl_buffer_object *bo)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
GLuint nr_dirty;
DEBUG("bo=%p\n", bo);
if (!bo->OnCard)
return GL_TRUE;
nr_dirty = nouveau_bo_download_dirty(ctx, bo);
if (nbo->cpu_mem) {
if (nr_dirty && nbo->cpu_mem != nbo->gpu_mem)
nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier,
NvSubMemFormat);
DEBUG("..destroy cpu_mem buffer\n");
nbo->cpu_mem_sys = malloc(bo->Size);
assert(nbo->cpu_mem_sys);
_mesa_memcpy(nbo->cpu_mem_sys, nbo->cpu_mem->map, bo->Size);
if (nbo->cpu_mem == nbo->gpu_mem)
nbo->cpu_mem = NULL;
else
NOUVEAU_MEM_FREE(nbo->cpu_mem);
}
NOUVEAU_MEM_FREE(nbo->gpu_mem);
bo->OnCard = GL_FALSE;
return GL_TRUE;
}
static void
nouveau_bo_choose_storage_method(GLcontext *ctx, GLenum usage,
struct gl_buffer_object *bo)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
GLuint gpu_type = 0;
GLuint cpu_type = 0;
switch (usage) {
/* Client source, changes often, used by GL many times */
case GL_DYNAMIC_DRAW_ARB:
gpu_type = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE;
cpu_type = NOUVEAU_MEM_AGP;
break;
/* GL source, changes often, client reads many times */
case GL_DYNAMIC_READ_ARB:
/* Client source, specified once, used by GL many times */
case GL_STATIC_DRAW_ARB:
/* GL source, specified once, client reads many times */
case GL_STATIC_READ_ARB:
/* Client source, specified once, used by GL a few times */
case GL_STREAM_DRAW_ARB:
/* GL source, specified once, client reads a few times */
case GL_STREAM_READ_ARB:
/* GL source, changes often, used by GL many times*/
case GL_DYNAMIC_COPY_ARB:
/* GL source, specified once, used by GL many times */
case GL_STATIC_COPY_ARB:
/* GL source, specified once, used by GL a few times */
case GL_STREAM_COPY_ARB:
gpu_type = NOUVEAU_MEM_FB;
break;
default:
assert(0);
}
nbo->gpu_mem_flags = gpu_type;
nbo->cpu_mem_flags = cpu_type;
nbo->usage = usage;
}
void
nouveau_bo_init_storage(GLcontext *ctx, GLuint valid_gpu_access,
GLsizeiptrARB size,
const GLvoid *data,
GLenum usage,
struct gl_buffer_object *bo, int flags)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
DEBUG("bo=%p\n", bo);
/* Free up previous buffers if we can't reuse them */
if (nbo->usage != usage ||
(nbo->gpu_mem && (nbo->gpu_mem->size != size))) {
if (nbo->cpu_mem_sys)
FREE(nbo->cpu_mem_sys);
if (nbo->cpu_mem) {
if (nbo->cpu_mem != nbo->gpu_mem)
NOUVEAU_MEM_FREE(nbo->cpu_mem);
else
nbo->cpu_mem = NULL;
}
if (nbo->gpu_mem)
NOUVEAU_MEM_FREE(nbo->gpu_mem);
bo->OnCard = GL_FALSE;
nbo->cpu_mem_sys = calloc(1, size);
}
nouveau_bo_choose_storage_method(ctx, usage, bo);
/* Force off flags that may not be ok for a given buffer */
nbo->gpu_mem_flags &= valid_gpu_access;
bo->Usage = usage;
bo->Size = size;
if (data) {
GLvoid *map = nouveau_bo_map(ctx, GL_WRITE_ONLY_ARB, bo);
#ifdef MESA_BIG_ENDIAN
int i;
if (flags) {
for (i = 0; i < size; i+=4) {
uint32_t _data = *(unsigned int *)(data+i);
_data = ((_data >> 16) | ((_data & 0xffff) << 16));
*(unsigned int *)(map+i) = _data;
}
} else
#endif
_mesa_memcpy(map, data, size);
(void)flags; /* get rid of warning */
nouveau_bo_dirty_all(ctx, GL_FALSE, bo);
nouveau_bo_unmap(ctx, bo);
}
}
void *
nouveau_bo_map(GLcontext *ctx, GLenum access, struct gl_buffer_object *bo)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
DEBUG("bo=%p, access=%s\n", bo, _mesa_lookup_enum_by_nr(access));
if (bo->OnCard &&
(access == GL_READ_ONLY_ARB || access == GL_READ_WRITE_ARB)) {
GLuint nr_dirty;
DEBUG("..on card\n");
nr_dirty = nouveau_bo_download_dirty(ctx, bo);
/* nouveau_bo_download_dirty won't wait unless it needs to
* free a temp buffer, which isn't the case if cpu_mem is
* present.
*/
if (nr_dirty && nbo->cpu_mem && nbo->cpu_mem != nbo->gpu_mem)
nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier,
NvSubMemFormat);
}
if (nbo->cpu_mem) {
DEBUG("..access via cpu_mem\n");
return nbo->cpu_mem->map;
} else {
DEBUG("..access via cpu_mem_sys\n");
return nbo->cpu_mem_sys;
}
}
void
nouveau_bo_unmap(GLcontext *ctx, struct gl_buffer_object *bo)
{
DEBUG("unmap bo=%p\n", bo);
}
uint32_t
nouveau_bo_gpu_ref(GLcontext *ctx, struct gl_buffer_object *bo)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
assert(nbo->mapped == GL_FALSE);
DEBUG("gpu_ref\n");
if (!bo->OnCard) {
nouveau_bo_move_in(ctx, bo);
bo->OnCard = GL_TRUE;
}
nouveau_bo_upload_dirty(ctx, bo);
return nouveau_mem_gpu_offset_get(ctx, nbo->gpu_mem);
}
void
nouveau_bo_dirty_linear(GLcontext *ctx, GLboolean on_card,
uint32_t offset, uint32_t size,
struct gl_buffer_object *bo)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
nouveau_bufferobj_dirty *dirty;
uint32_t start = offset;
uint32_t end = offset + size;
int i;
if (nbo->cpu_mem == nbo->gpu_mem)
return;
dirty = on_card ? &nbo->gpu_dirty : &nbo->cpu_dirty;
DEBUG("on_card=%d, offset=%d, size=%d, bo=%p\n",
on_card, offset, size, bo);
for (i=0; i<dirty->nr_dirty; i++) {
nouveau_bufferobj_region *r = &dirty->dirty[i];
/* already dirty */
if (start >= r->start && end <= r->end) {
DEBUG("..already dirty\n");
return;
}
/* add to the end of a region */
if (start >= r->start && start <= r->end) {
if (end > r->end) {
DEBUG("..extend end of region\n");
r->end = end;
return;
}
}
/* add to the start of a region */
if (start < r->start && end >= r->end) {
DEBUG("..extend start of region\n");
r->start = start;
/* .. and to the end */
if (end > r->end) {
DEBUG("....and end\n");
r->end = end;
}
return;
}
}
/* new region */
DEBUG("..new dirty\n");
dirty->nr_dirty++;
dirty->dirty = realloc(dirty->dirty,
sizeof(nouveau_bufferobj_region) *
dirty->nr_dirty);
dirty->dirty[dirty->nr_dirty - 1].start = start;
dirty->dirty[dirty->nr_dirty - 1].end = end;
}
void
nouveau_bo_dirty_all(GLcontext *ctx, GLboolean on_card,
struct gl_buffer_object *bo)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
nouveau_bufferobj_dirty *dirty;
dirty = on_card ? &nbo->gpu_dirty : &nbo->cpu_dirty;
DEBUG("dirty all\n");
if (dirty->nr_dirty) {
FREE(dirty->dirty);
dirty->dirty = NULL;
dirty->nr_dirty = 0;
}
nouveau_bo_dirty_linear(ctx, on_card, 0, bo->Size, bo);
}
GLuint
nouveau_bo_upload_dirty(GLcontext *ctx, struct gl_buffer_object *bo)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
nouveau_bufferobj_dirty *dirty = &nbo->cpu_dirty;
GLuint nr_dirty;
int i;
nr_dirty = dirty->nr_dirty;
if (!nr_dirty) {
DEBUG("clean\n");
return nr_dirty;
}
for (i=0; i<nr_dirty; i++) {
nouveau_bufferobj_region *r = &dirty->dirty[i];
DEBUG("dirty %d: o=0x%08x, s=0x%08x\n",
i, r->start, r->end - r->start);
nouveau_bo_upload_to_screen(ctx,
r->start, r->end - r->start, bo);
}
FREE(dirty->dirty);
dirty->dirty = NULL;
dirty->nr_dirty = 0;
return nr_dirty;
}
GLuint
nouveau_bo_download_dirty(GLcontext *ctx, struct gl_buffer_object *bo)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo;
nouveau_bufferobj_dirty *dirty = &nbo->gpu_dirty;
GLuint nr_dirty;
int i;
nr_dirty = dirty->nr_dirty;
if (nr_dirty) {
DEBUG("clean\n");
return nr_dirty;
}
for (i=0; i<nr_dirty; i++) {
nouveau_bufferobj_region *r = &dirty->dirty[i];
DEBUG("dirty %d: o=0x%08x, s=0x%08x\n",
i, r->start, r->end - r->start);
nouveau_bo_download_from_screen(ctx,
r->start,
r->end - r->start, bo);
}
FREE(dirty->dirty);
dirty->dirty = NULL;
dirty->nr_dirty = 0;
return nr_dirty;
}
static void
nouveauBindBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
{
}
static struct gl_buffer_object *
nouveauNewBufferObject(GLcontext *ctx, GLuint buffer, GLenum target)
{
nouveau_buffer_object *nbo;
nbo = CALLOC_STRUCT(nouveau_buffer_object_t);
if (nbo)
_mesa_initialize_buffer_object(&nbo->mesa, buffer, target);
DEBUG("bo=%p\n", nbo);
return nbo ? &nbo->mesa : NULL;
}
static void
nouveauDeleteBuffer(GLcontext *ctx, struct gl_buffer_object *obj)
{
nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
if (nbo->gpu_dirty.nr_dirty)
FREE(nbo->gpu_dirty.dirty);
if (nbo->cpu_dirty.nr_dirty)
FREE(nbo->cpu_dirty.dirty);
if (nbo->cpu_mem) nouveau_mem_free(ctx, nbo->cpu_mem);
if (nbo->gpu_mem) nouveau_mem_free(ctx, nbo->gpu_mem);
_mesa_delete_buffer_object(ctx, obj);
}
static void
nouveauBufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size,
const GLvoid *data, GLenum usage,
struct gl_buffer_object *obj)
{
GLuint gpu_flags;
DEBUG("target=%s, size=%d, data=%p, usage=%s, obj=%p\n",
_mesa_lookup_enum_by_nr(target),
(GLuint)size, data,
_mesa_lookup_enum_by_nr(usage),
obj);
switch (target) {
case GL_ELEMENT_ARRAY_BUFFER_ARB:
gpu_flags = 0;
break;
default:
gpu_flags = NOUVEAU_BO_VRAM_OK | NOUVEAU_BO_GART_OK;
break;
}
nouveau_bo_init_storage(ctx, gpu_flags, size, data, usage, obj, 0);
}
static void
nouveauBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
GLsizeiptrARB size, const GLvoid *data,
struct gl_buffer_object *obj)
{
GLvoid *out;
DEBUG("target=%s, offset=0x%x, size=%d, data=%p, obj=%p\n",
_mesa_lookup_enum_by_nr(target),
(GLuint)offset, (GLuint)size, data, obj);
out = nouveau_bo_map(ctx, GL_WRITE_ONLY_ARB, obj);
_mesa_memcpy(out + offset, data, size);
nouveau_bo_dirty_linear(ctx, GL_FALSE, offset, size, obj);
nouveau_bo_unmap(ctx, obj);
}
static void
nouveauGetBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
GLsizeiptrARB size, GLvoid *data,
struct gl_buffer_object *obj)
{
const GLvoid *in;
DEBUG("target=%s, offset=0x%x, size=%d, data=%p, obj=%p\n",
_mesa_lookup_enum_by_nr(target),
(GLuint)offset, (GLuint)size, data, obj);
in = nouveau_bo_map(ctx, GL_READ_ONLY_ARB, obj);
_mesa_memcpy(data, in + offset, size);
nouveau_bo_unmap(ctx, obj);
}
static void *
nouveauMapBuffer(GLcontext *ctx, GLenum target, GLenum access,
struct gl_buffer_object *obj)
{
DEBUG("target=%s, access=%s, obj=%p\n",
_mesa_lookup_enum_by_nr(target),
_mesa_lookup_enum_by_nr(access),
obj
);
/* Already mapped.. */
if (obj->Pointer)
return NULL;
/* Have to pass READ_WRITE here, nouveau_bo_map will only ensure that
* the cpu_mem buffer is up-to-date if we ask for read access.
*
* However, even if the client only asks for write access, we're still
* forced to reupload the entire buffer. So, we need the cpu_mem buffer
* to have the correct data all the time.
*/
obj->Pointer = nouveau_bo_map(ctx, GL_READ_WRITE_ARB, obj);
/* The GL spec says that a client attempting to write to a bufferobj
* mapped READ_ONLY object may have unpredictable results, possibly
* even program termination.
*
* We're going to use this, and only mark the buffer as dirtied if
* the client asks for write access.
*/
if (target != GL_READ_ONLY_ARB) {
/* We have no way of knowing what was modified by the client,
* so the entire buffer gets dirtied. */
nouveau_bo_dirty_all(ctx, GL_FALSE, obj);
}
return obj->Pointer;
}
static GLboolean
nouveauUnmapBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
{
DEBUG("target=%s, obj=%p\n", _mesa_lookup_enum_by_nr(target), obj);
assert(obj->Pointer);
nouveau_bo_unmap(ctx, obj);
obj->Pointer = NULL;
return GL_TRUE;
}
void
nouveauInitBufferObjects(GLcontext *ctx)
{
ctx->Driver.BindBuffer = nouveauBindBuffer;
ctx->Driver.NewBufferObject = nouveauNewBufferObject;
ctx->Driver.DeleteBuffer = nouveauDeleteBuffer;
ctx->Driver.BufferData = nouveauBufferData;
ctx->Driver.BufferSubData = nouveauBufferSubData;
ctx->Driver.GetBufferSubData = nouveauGetBufferSubData;
ctx->Driver.MapBuffer = nouveauMapBuffer;
ctx->Driver.UnmapBuffer = nouveauUnmapBuffer;
}

View file

@ -1,77 +0,0 @@
#ifndef __NOUVEAU_BUFFEROBJ_H__
#define __NOUVEAU_BUFFEROBJ_H__
#include "mtypes.h"
#include "nouveau_mem.h"
#define NOUVEAU_BO_VRAM_OK (NOUVEAU_MEM_FB | NOUVEAU_MEM_FB_ACCEPTABLE)
#define NOUVEAU_BO_GART_OK (NOUVEAU_MEM_AGP | NOUVEAU_MEM_AGP_ACCEPTABLE)
typedef struct nouveau_bufferobj_region_t {
uint32_t start;
uint32_t end;
} nouveau_bufferobj_region;
typedef struct nouveau_bufferobj_dirty_t {
nouveau_bufferobj_region *dirty;
int nr_dirty;
} nouveau_bufferobj_dirty;
typedef struct nouveau_buffer_object_t {
/* Base class, must be first */
struct gl_buffer_object mesa;
GLboolean mapped;
GLenum usage;
/* Memory used for GPU access to the buffer*/
GLuint gpu_mem_flags;
nouveau_mem * gpu_mem;
nouveau_bufferobj_dirty gpu_dirty;
/* Memory used for CPU access to the buffer */
GLuint cpu_mem_flags;
nouveau_mem * cpu_mem;
GLvoid * cpu_mem_sys;
nouveau_bufferobj_dirty cpu_dirty;
} nouveau_buffer_object;
extern void
nouveau_bo_init_storage(GLcontext *ctx, GLuint valid_gpu_access,
GLsizeiptrARB size, const GLvoid *data, GLenum usage,
struct gl_buffer_object *bo, int flags);
extern GLboolean
nouveau_bo_move_in(GLcontext *ctx, struct gl_buffer_object *bo);
extern GLboolean
nouveau_bo_move_out(GLcontext *ctx, struct gl_buffer_object *bo);
extern void *
nouveau_bo_map(GLcontext *ctx, GLenum usage, struct gl_buffer_object *bo);
extern void
nouveau_bo_unmap(GLcontext *ctx, struct gl_buffer_object *bo);
extern uint32_t
nouveau_bo_gpu_ref(GLcontext *ctx, struct gl_buffer_object *bo);
extern void
nouveau_bo_dirty_linear(GLcontext *ctx, GLboolean on_card,
uint32_t offset, uint32_t size,
struct gl_buffer_object *bo);
extern void
nouveau_bo_dirty_all(GLcontext *ctx, GLboolean on_card,
struct gl_buffer_object *bo);
extern GLuint
nouveau_bo_upload_dirty(GLcontext *ctx, struct gl_buffer_object *bo);
extern GLuint
nouveau_bo_download_dirty(GLcontext *ctx, struct gl_buffer_object *bo);
extern void
nouveauInitBufferObjects(GLcontext *ctx);
#endif

View file

@ -1,17 +0,0 @@
#include "nouveau_card.h"
#include "nouveau_reg.h"
#include "nouveau_drm.h"
#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))
return &(nouveau_card_list[i]);
return NULL;
}

View file

@ -1,49 +0,0 @@
/**************************************************************************
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

View file

@ -1,226 +0,0 @@
static nouveau_card nouveau_card_list[]={
{0x0020, "RIVA TNT", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x0028, "RIVA TNT2/TNT2 Pro", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x0029, "RIVA TNT2 Ultra", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x002A, "Riva TnT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x002B, "Riva TnT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x002C, "Vanta/Vanta LT", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x002D, "RIVA TNT2 Model 64/Model 64 Pro", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x002E, "Vanta", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x002F, "Vanta", NV04_DX5_TEXTURED_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_DX5_TEXTURED_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|0x0400, 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|0x0400, 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},
{0x014C, "Quadro FX 550", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
{0x014D, "Quadro FX 550", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 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_11, 0},
{0x0151, "GeForce2 Ti", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
{0x0152, "GeForce2 Ultra, Bladerunner", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
{0x0153, "Quadro2 Pro", NV11_TCL_PRIMITIVE_3D, NV_11, 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},
{0x01D3, "GeForce 7300 SE", 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, NV_20, 0},
{0x0201, "GeForce3 Ti 200", NV20_TCL_PRIMITIVE_3D, NV_20, 0},
{0x0202, "GeForce3 Ti 500", NV20_TCL_PRIMITIVE_3D, NV_20, 0},
{0x0203, "Quadro DCC", NV20_TCL_PRIMITIVE_3D, 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},
{0x0244, "Geforce 6150 Go", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
{0x0250, "GeForce4 Ti 4600", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0251, "GeForce4 Ti 4400", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0252, "GeForce4 Ti", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0253, "GeForce4 Ti 4200", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0258, "Quadro4 900 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0259, "Quadro4 750 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x025B, "Quadro4 700 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0280, "GeForce4 Ti 4800", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0281, "GeForce4 Ti 4200 AGP 8x", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0282, "GeForce4 Ti 4800 SE", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0286, "GeForce4 Ti 4200 Go AGP 8x", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0288, "Quadro4 980 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x0289, "Quadro4 780 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 0},
{0x028C, "Quadro4 700 GoGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_20, 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, NV_20, 0},
{0x02E1, "GeForce 7600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
{0x0300, "GeForce FX", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0301, "GeForce FX 5800 Ultra", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0302, "GeForce FX 5800", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0308, "Quadro FX 2000", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0309, "Quadro FX 1000", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0311, "GeForce FX 5600 Ultra", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0312, "GeForce FX 5600", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0313, "NV31", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0314, "GeForce FX 5600XT", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0316, "NV31M", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0317, "NV31M Pro", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x031A, "GeForce FX Go5600", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x031B, "GeForce FX Go5650", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x031C, "NVIDIA Quadro FX Go700", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x031D, "NV31GLM", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x031E, "NV31GLM Pro", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x031F, "NV31GLM Pro", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0},
{0x0320, "GeForce FX 5200", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0321, "GeForce FX 5200 Ultra", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0322, "GeForce FX 5200", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0323, "GeForce FX 5200LE", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0324, "GeForce FX Go5200", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0325, "GeForce FX Go5250", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0326, "GeForce FX 5500", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0327, "GeForce FX 5100", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0328, "GeForce FX Go5200 32M/64M", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x0329, "GeForce FX Go5200", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x032A, "Quadro NVS 280 PCI", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x032B, "Quadro FX 500/600 PCI", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x032C, "GeForce FX Go 5300", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x032D, "GeForce FX Go5100", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
{0x032F, "NV34GL", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 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|0x0400, NV_30, 0},
{0x0334, "GeForce FX 5900ZT", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0338, "Quadro FX 3000", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x033F, "Quadro FX 700", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0341, "GeForce FX 5700 Ultra", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0342, "GeForce FX 5700", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0343, "GeForce FX 5700LE", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0344, "GeForce FX 5700VE", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0345, "NV36.5", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0347, "GeForce FX Go5700", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0348, "GeForce FX Go5700", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x0349, "NV36M Pro", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x034B, "NV36MAP", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x034C, "Quadro FX Go1000", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x034E, "Quadro FX 1100", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
{0x034F, "NV36GL", NV30_TCL_PRIMITIVE_3D|0x0400, 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},
{0x0020, "TNT", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x0028, "TNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x0029, "UTNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x002C, "VTNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
{0x00A0, "ITNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0},
};

View file

@ -1,422 +0,0 @@
/**************************************************************************
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 "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 "nouveau_query.h"
#include "nv04_swtcl.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[] =
{
{ "shaders" , DEBUG_SHADERS },
{ "mem" , DEBUG_MEM },
{ "bufferobj" , DEBUG_BUFFEROBJ },
{ NULL , 0 }
};
#define need_GL_ARB_vertex_program
#define need_GL_ARB_occlusion_query
#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 },
{ "GL_ARB_occlusion_query", GL_ARB_occlusion_query_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_FB_SIZE,
&nmesa->vram_size))
return GL_FALSE;
if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_PHYSICAL,
&nmesa->gart_phys))
return GL_FALSE;
if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_SIZE,
&nmesa->gart_size))
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 = (struct drm_nouveau_sarea *)((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->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
/* Initialize the swrast */
_swrast_CreateContext( ctx );
_vbo_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_04:
case NV_05:
nv04TriInitFunctions( ctx );
break;
case NV_10:
case NV_11:
case NV_17:
case NV_20:
case NV_30:
case NV_40:
case NV_44:
case NV_50:
default:
nv10TriInitFunctions( ctx );
break;
}
nouveauInitBufferObjects(ctx);
if (!nouveauSyncInitFuncs(ctx))
return GL_FALSE;
nouveauQueryInitFuncs(ctx);
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;
if (driDrawPriv->swap_interval == (unsigned)-1) {
driDrawPriv->vblFlags =
driGetDefaultVBlankFlags(&nmesa->optionCache);
driDrawableInitVBlank(driDrawPriv);
}
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;
}
void
nouveauDoSwapBuffers(nouveauContextPtr nmesa, __DRIdrawablePrivate *dPriv)
{
struct gl_framebuffer *fb;
nouveauScreenPtr screen = dPriv->driScreenPriv->private;
nouveau_renderbuffer_t *src;
drm_clip_rect_t *box;
int nbox, i;
fb = (struct gl_framebuffer *)dPriv->driverPrivate;
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
src = (nouveau_renderbuffer_t *)
fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
} else {
src = (nouveau_renderbuffer_t *)
fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
}
LOCK_HARDWARE(nmesa);
nbox = dPriv->numClipRects;
box = dPriv->pClipRects;
if (nbox) {
BEGIN_RING_SIZE(NvSubCtxSurf2D,
NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
if (src->mesa._ActualFormat == GL_RGBA8)
OUT_RING (6); /* X8R8G8B8 */
else
OUT_RING (4); /* R5G6B5 */
OUT_RING(((screen->frontPitch * screen->fbFormat) << 16) |
src->pitch);
OUT_RING(src->offset);
OUT_RING(screen->frontOffset);
}
for (i=0; i<nbox; i++, box++) {
BEGIN_RING_SIZE(NvSubImageBlit, NV_IMAGE_BLIT_POINT_IN, 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));
}
FIRE_RING();
UNLOCK_HARDWARE(nmesa);
}
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)
{
}
void nouveauClearBuffer(GLcontext *ctx, nouveau_renderbuffer_t *buffer,
int fill, int mask)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
int dimensions;
if (!buffer) {
return;
}
/* FIXME: only support 32 bits atm */
/* Surface that we will work on */
nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf2D, NvCtxSurf2D);
BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING(0x0b); /* Y32 color format */
OUT_RING((buffer->pitch<<16)|buffer->pitch);
OUT_RING(buffer->offset);
OUT_RING(buffer->offset);
/* Now clear a rectangle */
dimensions = ((buffer->mesa.Height)<<16) | (buffer->mesa.Width);
nouveauObjectOnSubchannel(nmesa, NvSubGdiRectText, NvGdiRectText);
BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
OUT_RING(3); /* SRCCOPY */
BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL1_TL, 5);
OUT_RING(0); /* top left */
OUT_RING(dimensions); /* bottom right */
OUT_RING(fill);
OUT_RING(0); /* top left */
OUT_RING(dimensions); /* bottom right */
}

View file

@ -1,241 +0,0 @@
/**************************************************************************
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_fbo.h"
#include "nouveau_screen.h"
#include "nouveau_shader.h"
#include "nouveau_state_cache.h"
#include "nouveau_sync.h"
#include "xmlconfig.h"
typedef struct nouveau_fifo {
struct drm_nouveau_channel_alloc drm;
uint32_t *pushbuf;
uint32_t *mmio;
uint32_t *notifier_block;
uint32_t current;
uint32_t put;
uint32_t free;
uint32_t max;
} nouveau_fifo_t;
#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_t **color,
nouveau_renderbuffer_t *depth);
/* Update anything that depends on the window position/size */
void (*WindowMoved)(struct nouveau_context *);
/* Update projection matrix */
void (*UpdateProjectionMatrix)(GLcontext *);
/* Update modelview matrix (used for lighting and vertex weight) */
void (*UpdateModelviewMatrix)(GLcontext *);
} nouveau_hw_func;
typedef struct nouveau_context {
/* Mesa context */
GLcontext *glCtx;
/* The per-context fifo */
nouveau_fifo_t fifo;
/* Physical addresses of AGP/VRAM apertures */
uint64_t vram_phys;
uint64_t vram_size;
uint64_t gart_phys;
uint64_t gart_size;
/* Channel synchronisation */
struct drm_nouveau_notifierobj_alloc *syncNotifier;
/* ARB_occlusion_query / EXT_timer_query */
GLuint query_object_max;
GLboolean * query_alloc;
struct drm_nouveau_notifierobj_alloc *queryNotifier;
/* 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;
/* Color and depth renderbuffers */
nouveau_renderbuffer_t *color_buffer;
nouveau_renderbuffer_t *depth_buffer;
/* Depth/stencil clear value */
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;
drm_clip_rect_t osClipRect;
GLuint drawX, drawY, drawW, drawH;
/* 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;
nouveauShader *passthrough_fp;
nouveauScreenRec *screen;
struct drm_nouveau_sarea *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;
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 nouveauDoSwapBuffers(nouveauContextPtr nmesa,
__DRIdrawablePrivate *dPriv);
extern void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv);
extern void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
int x, int y, int w, int h);
extern void nouveauClearBuffer(GLcontext *ctx, nouveau_renderbuffer_t *buffer,
int fill, int mask);
/* Debugging utils: */
extern int NOUVEAU_DEBUG;
#define DEBUG_SHADERS 0x00000001
#define DEBUG_MEM 0x00000002
#define DEBUG_BUFFEROBJ 0x00000004
#endif /* __NOUVEAU_CONTEXT_H__ */

View file

@ -1,44 +0,0 @@
/**************************************************************************
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

View file

@ -1,28 +0,0 @@
#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

View file

@ -1,218 +0,0 @@
/**************************************************************************
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"
#include "colormac.h"
/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa,
unsigned int param,
uint64_t* value)
{
struct drm_nouveau_getparam 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)
{
struct drm_nouveau_setparam 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);
if (ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT)
nouveauDoSwapBuffers(nmesa, nmesa->driDrawable);
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 )
{
uint32_t clear_value;
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
/* FIXME: should we clear front buffer, even if asked to do it? */
if (mask & (BUFFER_BIT_FRONT_LEFT|BUFFER_BIT_BACK_LEFT)) {
GLubyte c[4];
int color_bits = 32;
int color_mask = 0xffffffff;
UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,ctx->Color.ClearColor);
clear_value = PACK_COLOR_8888(c[3],c[0],c[1],c[2]);
if (ctx->DrawBuffer) {
/* FIXME: find correct color buffer, instead of [0] */
if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
color_bits = ctx->DrawBuffer->_ColorDrawBuffers[0]->RedBits;
color_bits += ctx->DrawBuffer->_ColorDrawBuffers[0]->GreenBits;
color_bits += ctx->DrawBuffer->_ColorDrawBuffers[0]->BlueBits;
color_bits += ctx->DrawBuffer->_ColorDrawBuffers[0]->AlphaBits;
}
}
if (color_bits<24) {
clear_value = PACK_COLOR_565(c[0],c[1],c[2]);
color_mask = 0xffff;
}
nouveauClearBuffer(ctx, nmesa->color_buffer,
clear_value, color_mask);
}
if (mask & (BUFFER_BIT_DEPTH)) {
int depth_bits = 24;
int depth_mask;
if (ctx->DrawBuffer) {
if (ctx->DrawBuffer->_DepthBuffer) {
depth_bits = ctx->DrawBuffer->_DepthBuffer->DepthBits;
}
}
switch(depth_bits) {
case 16:
clear_value = (uint32_t) (ctx->Depth.Clear * 32767.0);
depth_mask = 0xffff;
break;
default:
clear_value = ((uint32_t) (ctx->Depth.Clear * 16777215.0)) << 8;
depth_mask = 0xffffff00;
break;
}
nouveauClearBuffer(ctx, nmesa->depth_buffer,
clear_value, depth_mask);
}
if (mask & (BUFFER_BIT_STENCIL)) {
int stencil_bits = 0;
if (ctx->DrawBuffer) {
if (ctx->DrawBuffer->_StencilBuffer) {
stencil_bits = ctx->DrawBuffer->_StencilBuffer->StencilBits;
}
}
if (stencil_bits>0) {
nouveauClearBuffer(ctx, nmesa->depth_buffer,
ctx->Stencil.Clear, (1<<stencil_bits)-1);
}
}
}
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;
}

View file

@ -1,42 +0,0 @@
/**************************************************************************
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__ */

View file

@ -1,289 +0,0 @@
#include "utils.h"
#include "framebuffer.h"
#include "renderbuffer.h"
#include "fbobject.h"
#include "nouveau_context.h"
#include "nouveau_fbo.h"
#include "nouveau_fifo.h"
#include "nouveau_msg.h"
#include "nouveau_object.h"
#include "nouveau_reg.h"
static GLboolean
nouveau_renderbuffer_pixelformat(nouveau_renderbuffer_t * 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_RGB:
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_t *nrb = (nouveau_renderbuffer_t *) 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 (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;
nouveauSpanSetFunctions(nrb);
return GL_TRUE;
}
static void
nouveau_renderbuffer_delete(struct gl_renderbuffer *rb)
{
GET_CURRENT_CONTEXT(ctx);
nouveau_renderbuffer_t *nrb = (nouveau_renderbuffer_t *) rb;
if (nrb->mem)
nouveau_mem_free(ctx, nrb->mem);
FREE(nrb);
}
nouveau_renderbuffer_t *
nouveau_renderbuffer_new(GLenum internalFormat)
{
nouveau_renderbuffer_t *nrb;
nrb = CALLOC_STRUCT(nouveau_renderbuffer);
if (!nrb)
return NULL;
_mesa_init_renderbuffer(&nrb->mesa, 0);
if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) {
fprintf(stderr, "%s: unknown internalFormat\n", __func__);
return GL_FALSE;
}
nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
nrb->mesa.Delete = nouveau_renderbuffer_delete;
return nrb;
}
static void
nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa,
nouveau_renderbuffer_t * nrb)
{
nmesa->numClipRects = 1;
nmesa->pClipRects = &nmesa->osClipRect;
nmesa->osClipRect.x1 = 0;
nmesa->osClipRect.y1 = 0;
nmesa->osClipRect.x2 = nrb->mesa.Width;
nmesa->osClipRect.y2 = nrb->mesa.Height;
nmesa->drawX = 0;
nmesa->drawY = 0;
nmesa->drawW = nrb->mesa.Width;
nmesa->drawH = nrb->mesa.Height;
}
void
nouveau_window_moved(GLcontext * ctx)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_renderbuffer_t *nrb;
nrb = (nouveau_renderbuffer_t *) ctx->DrawBuffer->_ColorDrawBuffers[0];
if (!nrb)
return;
nouveau_cliprects_renderbuffer_set(nmesa, nrb);
/* 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_t *color[MAX_DRAW_BUFFERS];
nouveau_renderbuffer_t *depth;
_mesa_update_framebuffer(ctx);
_mesa_update_draw_buffer_bounds(ctx);
color[0] = (nouveau_renderbuffer_t *) fb->_ColorDrawBuffers[0];
if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped)
depth = (nouveau_renderbuffer_t *) fb->_DepthBuffer->Wrapped;
else
depth = (nouveau_renderbuffer_t *) fb->_DepthBuffer;
if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth))
return GL_FALSE;
nouveau_window_moved(ctx);
return GL_TRUE;
}
static void
nouveauDrawBuffer(GLcontext *ctx, GLenum buffer)
{
nouveau_build_framebuffer(ctx, ctx->DrawBuffer);
}
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_t *nrb;
nrb = CALLOC_STRUCT(nouveau_renderbuffer);
if (!nrb)
return NULL;
_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,
struct gl_framebuffer *fbread)
{
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
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->DrawBuffer = nouveauDrawBuffer;
func->NewFramebuffer = nouveauNewFramebuffer;
func->NewRenderbuffer = nouveauNewRenderbuffer;
func->BindFramebuffer = nouveauBindFramebuffer;
func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer;
func->RenderTexture = nouveauRenderTexture;
func->FinishRenderTexture = nouveauFinishRenderTexture;
}

View file

@ -1,30 +0,0 @@
#ifndef __NOUVEAU_BUFFERS_H__
#define __NOUVEAU_BUFFERS_H__
#include <stdint.h>
#include "mtypes.h"
#include "utils.h"
#include "renderbuffer.h"
#include "nouveau_mem.h"
typedef struct nouveau_renderbuffer {
struct gl_renderbuffer mesa; /* must be first! */
nouveau_mem *mem;
void *map;
int cpp;
uint32_t offset;
uint32_t pitch;
} nouveau_renderbuffer_t;
extern nouveau_renderbuffer_t *nouveau_renderbuffer_new(GLenum internalFormat);
extern void nouveau_window_moved(GLcontext *);
extern GLboolean nouveau_build_framebuffer(GLcontext *,
struct gl_framebuffer *);
extern nouveau_renderbuffer_t *nouveau_current_draw_buffer(GLcontext *);
extern void nouveauInitBufferFuncs(struct dd_function_table *);
#endif

View file

@ -1,153 +0,0 @@
/**************************************************************************
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"
#include "nouveau_object.h"
#include "nouveau_sync.h"
#ifdef NOUVEAU_RING_DEBUG
int nouveau_fifo_remaining=0;
#endif
#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.drm.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 channel to be idle
*/
void nouveauWaitForIdleLocked(nouveauContextPtr nmesa)
{
/* Wait for FIFO idle */
FIRE_RING();
while(RING_AHEAD()>0);
/* Wait on notifier to indicate all commands in the channel have
* been completed.
*/
nouveau_notifier_wait_nop(nmesa->glCtx, nmesa->syncNotifier, NvSub3D);
}
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)
{
int i, ret;
#ifdef NOUVEAU_RING_DEBUG
return GL_TRUE;
#endif
nmesa->fifo.drm.fb_ctxdma_handle = NvDmaFB;
nmesa->fifo.drm.tt_ctxdma_handle = NvDmaTT;
ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_CHANNEL_ALLOC,
&nmesa->fifo.drm, sizeof(nmesa->fifo.drm));
if (ret) {
FATAL("Fifo initialization ioctl failed (returned %d)\n", ret);
return GL_FALSE;
}
ret = drmMap(nmesa->driFd, nmesa->fifo.drm.cmdbuf,
nmesa->fifo.drm.cmdbuf_size, &nmesa->fifo.pushbuf);
if (ret) {
FATAL("Unable to map the fifo (returned %d)\n", ret);
return GL_FALSE;
}
ret = drmMap(nmesa->driFd, nmesa->fifo.drm.ctrl,
nmesa->fifo.drm.ctrl_size, &nmesa->fifo.mmio);
if (ret) {
FATAL("Unable to map the control regs (returned %d)\n", ret);
return GL_FALSE;
}
ret = drmMap(nmesa->driFd, nmesa->fifo.drm.notifier,
nmesa->fifo.drm.notifier_size,
&nmesa->fifo.notifier_block);
if (ret) {
FATAL("Unable to map the notifier block (returned %d)\n", ret);
return GL_FALSE;
}
/* Setup our initial FIFO tracking params */
nmesa->fifo.current = 0;
nmesa->fifo.put = 0;
nmesa->fifo.max = (nmesa->fifo.drm.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", nmesa->fifo.drm.channel);
return GL_TRUE;
}

View file

@ -1,222 +0,0 @@
/**************************************************************************
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"
#include "nouveau_state_cache.h"
//#define NOUVEAU_RING_TRACE
//#define NOUVEAU_RING_DEBUG
//#define NOUVEAU_STATE_CACHE_DISABLE
#ifndef NOUVEAU_RING_TRACE
#define NOUVEAU_RING_TRACE 0
#else
#undef NOUVEAU_RING_TRACE
#define NOUVEAU_RING_TRACE 1
#endif
#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.drm.put_base) >> 2)
#define NV_FIFO_WRITE_PUT(val) do { \
if (NOUVEAU_RING_TRACE) {\
printf("FIRE_RING : 0x%08x\n", nmesa->fifo.current << 2); \
fflush(stdout); \
sleep(1); \
} \
NV_FIFO_WRITE(NV03_FIFO_REGS_DMAPUT, ((val)<<2) + nmesa->fifo.drm.put_base); \
} while(0)
/*
* 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
extern int nouveau_fifo_remaining;
#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))); \
nouveau_fifo_remaining-=sz; \
}while(0)
#define OUT_RING(n) do { \
printf("OUT_RINGn: 0x%08x (%s)\n", n, __func__); \
nouveau_fifo_remaining--; \
}while(0)
#define OUT_RINGf(n) do { \
printf("OUT_RINGf: %.04f (%s)\n", n, __func__); \
nouveau_fifo_remaining--; \
}while(0)
#define BEGIN_RING_SIZE(subchannel,tag,size) do { \
if (nouveau_fifo_remaining!=0) \
printf("RING ERROR : remaining %d\n",nouveau_fifo_remaining); \
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); \
nouveau_fifo_remaining=size; \
}while(0)
#else
#define OUT_RINGp(ptr,sz) do{ \
if (NOUVEAU_RING_TRACE) { \
uint32_t* p=(uint32_t*)(ptr); \
int i; printf("OUT_RINGp: (size 0x%x dwords) (%s)\n",sz, __func__); for(i=0;i<sz;i++) printf(" [0x%08x] 0x%08x %f\n", (nmesa->fifo.current+i) << 2, *(p+i), *((float*)(p+i))); \
} \
memcpy(nmesa->fifo.pushbuf+nmesa->fifo.current,ptr,(sz)*4); \
nmesa->fifo.current+=(sz); \
}while(0)
#define OUT_RING(n) do { \
if (NOUVEAU_RING_TRACE) \
printf("OUT_RINGn: [0x%08x] 0x%08x (%s)\n", nmesa->fifo.current << 2, n, __func__); \
nmesa->fifo.pushbuf[nmesa->fifo.current++]=(n); \
}while(0)
#define OUT_RINGf(n) do { \
if (NOUVEAU_RING_TRACE) \
printf("OUT_RINGf: [0x%08x] %.04f (%s)\n", nmesa->fifo.current << 2, n, __func__); \
*((float*)(nmesa->fifo.pushbuf+nmesa->fifo.current++))=(n); \
}while(0)
#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)
#endif
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))
#define OUT_RING_CACHE_FORCE(n) OUT_RING((n))
#define OUT_RING_CACHE_FORCEf(n) OUT_RINGf((n))
#define OUT_RING_CACHE_FORCEp(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); \
assert(nmesa->state_cache.current_pos + size <= NOUVEAU_STATE_CACHE_ENTRIES); \
}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.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=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 ((*(GLfloat*)(&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.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \
(*(GLfloat*)(&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 { \
GLuint* p=(GLuint*)(ptr); \
int i; \
for(i=0;i<sz;i++) \
OUT_RING_CACHE(*(p+i)); \
}while(0)
#define OUT_RING_CACHE_FORCE(n) do { \
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \
nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value=(n); \
nmesa->state_cache.current_pos++; \
}while(0)
#define OUT_RING_CACHE_FORCEf(n) do { \
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \
nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \
(*(GLfloat*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))=(n);\
nmesa->state_cache.current_pos++; \
}while(0)
#define OUT_RING_CACHE_FORCEp(ptr,sz) do { \
GLuint* p=(GLuint*)(ptr); \
int i; \
for(i=0;i<sz;i++) \
OUT_RING_CACHE_FORCE(*(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 void nouveauWaitForIdleLocked(nouveauContextPtr nmesa);
extern GLboolean nouveauFifoInit(nouveauContextPtr nmesa);
#endif /* __NOUVEAU_FIFO_H__ */

View file

@ -1,81 +0,0 @@
/**************************************************************************
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;
struct drm_nouveau_sarea *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;
}

View file

@ -1,69 +0,0 @@
/**************************************************************************
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__ */

View file

@ -1,144 +0,0 @@
#include "mtypes.h"
#include "nouveau_context.h"
#include "nouveau_fifo.h"
#include "nouveau_mem.h"
#include "nouveau_msg.h"
#include "nouveau_object.h"
#include "nouveau_reg.h"
#define MAX_MEMFMT_LENGTH 32768
/* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */
GLboolean
nouveau_memformat_flat_emit(GLcontext * ctx,
nouveau_mem * dst, nouveau_mem * src,
GLuint dst_offset, GLuint src_offset,
GLuint size)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
uint32_t src_handle, dst_handle;
GLuint count;
if (src_offset + size > src->size) {
MESSAGE("src out of nouveau_mem bounds\n");
return GL_FALSE;
}
if (dst_offset + size > dst->size) {
MESSAGE("dst out of nouveau_mem bounds\n");
return GL_FALSE;
}
src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT;
dst_handle = (dst->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT;
src_offset += nouveau_mem_gpu_offset_get(ctx, src);
dst_offset += nouveau_mem_gpu_offset_get(ctx, dst);
BEGIN_RING_SIZE(NvSubMemFormat,
NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2);
OUT_RING(src_handle);
OUT_RING(dst_handle);
count = (size / MAX_MEMFMT_LENGTH) +
((size % MAX_MEMFMT_LENGTH) ? 1 : 0);
while (count--) {
GLuint length =
(size > MAX_MEMFMT_LENGTH) ? MAX_MEMFMT_LENGTH : size;
BEGIN_RING_SIZE(NvSubMemFormat,
NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
OUT_RING(src_offset);
OUT_RING(dst_offset);
OUT_RING(0); /* pitch in */
OUT_RING(0); /* pitch out */
OUT_RING(length); /* line length */
OUT_RING(1); /* number of lines */
OUT_RING((1 << 8) /* dst_inc */ |(1 << 0) /* src_inc */ );
OUT_RING(0); /* buffer notify? */
FIRE_RING();
src_offset += length;
dst_offset += length;
size -= length;
}
return GL_TRUE;
}
void nouveau_mem_free(GLcontext * ctx, nouveau_mem * mem)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
struct drm_nouveau_mem_free memf;
if (NOUVEAU_DEBUG & DEBUG_MEM) {
fprintf(stderr, "%s: type=0x%x, offset=0x%x, size=0x%x\n",
__func__, mem->type, (GLuint) mem->offset,
(GLuint) mem->size);
}
if (mem->map)
drmUnmap(mem->map, mem->size);
memf.flags = mem->type;
memf.offset = mem->offset;
drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf,
sizeof(memf));
FREE(mem);
}
nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, uint32_t flags, GLuint size,
GLuint align)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
struct drm_nouveau_mem_alloc mema;
nouveau_mem *mem;
int ret;
if (NOUVEAU_DEBUG & DEBUG_MEM) {
fprintf(stderr,
"%s: requested: flags=0x%x, size=0x%x, align=0x%x\n",
__func__, flags, (GLuint) size, align);
}
mem = CALLOC(sizeof(nouveau_mem));
if (!mem)
return NULL;
mema.flags = flags;
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.offset;
mem->type = mema.flags;
if (NOUVEAU_DEBUG & DEBUG_MEM) {
fprintf(stderr,
"%s: actual: type=0x%x, offset=0x%x, size=0x%x\n",
__func__, mem->type, (GLuint) mem->offset,
(GLuint) mem->size);
}
if (flags & NOUVEAU_MEM_MAPPED)
ret = drmMap(nmesa->driFd, mema.map_handle, 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);
return mem->offset;
}

View file

@ -1,23 +0,0 @@
#ifndef __NOUVEAU_MEM_H__
#define __NOUVEAU_MEM_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 *, uint32_t flags,
GLuint size, GLuint align);
extern void nouveau_mem_free(GLcontext *, nouveau_mem *);
extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *, nouveau_mem *);
extern GLboolean nouveau_memformat_flat_emit(GLcontext *,
nouveau_mem *dst,
nouveau_mem *src,
GLuint dst_offset,
GLuint src_offset,
GLuint size);
#endif

View file

@ -1,67 +0,0 @@
/*
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__ */

View file

@ -1,98 +0,0 @@
#include "nouveau_fifo.h"
#include "nouveau_object.h"
#include "nouveau_reg.h"
GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa,
uint32_t handle, int class)
{
struct drm_nouveau_grobj_alloc cto;
int ret;
cto.channel = nmesa->fifo.drm.channel;
cto.handle = handle;
cto.class = class;
ret = drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_GROBJ_ALLOC,
&cto, sizeof(cto));
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
nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d);
if (nmesa->screen->card->type>=NV_10) {
nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV10_CONTEXT_SURFACES_2D);
} else {
nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D);
nouveauCreateContextObject(nmesa, NvCtxSurf3D, NV04_CONTEXT_SURFACES_3D);
}
if (nmesa->screen->card->type>=NV_11) {
nouveauCreateContextObject(nmesa, NvImageBlit, NV11_IMAGE_BLIT);
} else {
nouveauCreateContextObject(nmesa, NvImageBlit, NV_IMAGE_BLIT);
}
if ((nmesa->screen->card->type>=NV_10) && (nmesa->screen->card->type<NV_20)) {
nouveauCreateContextObject(nmesa, NvGdiRectText, NV04_GDI_RECTANGLE_TEXT);
nouveauCreateContextObject(nmesa, NvRasterOp, NV03_PRIMITIVE_RASTER_OP);
nouveauCreateContextObject(nmesa, NvPattern, NV04_IMAGE_PATTERN);
}
nouveauCreateContextObject(nmesa, NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT);
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, NV_IMAGE_BLIT_SET_SURFACES_2D, 1);
OUT_RING(NvCtxSurf2D);
BEGIN_RING_SIZE(NvSubImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
OUT_RING(3); /* SRCCOPY */
if ((nmesa->screen->card->type>=NV_10) && (nmesa->screen->card->type<NV_20)) {
nouveauObjectOnSubchannel(nmesa, NvSubPattern, NvPattern);
BEGIN_RING_SIZE(NvSubPattern, NV04_IMAGE_PATTERN_COLOR_FORMAT, 4);
OUT_RING(1); /* A16R5G6B5 */
OUT_RING(1); /* little endian */
OUT_RING(0); /* 8x8 */
OUT_RING(1); /* monochrome */
nouveauObjectOnSubchannel(nmesa, NvSubRasterOp, NvRasterOp);
BEGIN_RING_SIZE(NvSubRasterOp, NV03_PRIMITIVE_RASTER_OP_DMA_NOTIFY, 1);
OUT_RING(NvSyncNotify);
nouveauObjectOnSubchannel(nmesa, NvSubGdiRectText, NvGdiRectText);
BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_SET_DMA_NOTIFY, 1);
OUT_RING(NvSyncNotify);
BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_PATTERN, 2);
OUT_RING(NvPattern);
OUT_RING(NvRasterOp);
BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
OUT_RING(NvCtxSurf2D);
BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_FORMAT, 2);
OUT_RING(1); /* X1R5G5B5 */
OUT_RING(1); /* little endian */
}
nouveauObjectOnSubchannel(nmesa, NvSubMemFormat, NvMemFormat);
nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
}

View file

@ -1,39 +0,0 @@
#ifndef __NOUVEAU_OBJECT_H__
#define __NOUVEAU_OBJECT_H__
#include "nouveau_context.h"
void nouveauObjectInit(nouveauContextPtr nmesa);
enum DMAObjects {
Nv3D = 0x80000019,
NvCtxSurf2D = 0x80000020,
NvImageBlit = 0x80000021,
NvMemFormat = 0x80000022,
NvCtxSurf3D = 0x80000023,
NvGdiRectText = 0x80000024,
NvPattern = 0x80000025,
NvRasterOp = 0x80000026,
NvDmaFB = 0xD0FB0001,
NvDmaTT = 0xD0AA0001,
NvSyncNotify = 0xD0000001,
NvQueryNotify = 0xD0000002
};
enum DMASubchannel {
NvSubCtxSurf2D = 0,
NvSubImageBlit = 1,
NvSubMemFormat = 2,
NvSubCtxSurf3D = 3,
NvSubGdiRectText= 4,
NvSubPattern = 5,
NvSubRasterOp = 6,
NvSub3D = 7,
};
extern void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle);
extern GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa,
uint32_t handle, int class);
#endif

View file

@ -1,200 +0,0 @@
/*
* Copyright (C) 2007 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.
*
*/
/* GL_ARB_occlusion_query support for NV20/30/40 */
#include "mtypes.h"
#include "nouveau_fifo.h"
#include "nouveau_msg.h"
#include "nouveau_object.h"
#include "nouveau_reg.h"
#include "nouveau_sync.h"
#include "nouveau_query.h"
static struct gl_query_object *
nouveauNewQueryObject(GLcontext *ctx, GLuint id)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_query_object *nq;
int i;
for (i=0; i<nmesa->query_object_max; i++)
if (nmesa->query_alloc[i] == GL_FALSE)
break;
if (i==nmesa->query_object_max)
return NULL;
nq = CALLOC_STRUCT(nouveau_query_object_t);
if (nq) {
nq->notifier_id = i;
nq->mesa.Id = id;
nq->mesa.Result = 0;
nq->mesa.Active = GL_FALSE;
nq->mesa.Ready = GL_TRUE;
}
return (struct gl_query_object *)nq;
}
static void
nouveauBeginQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_query_object *nq = (nouveau_query_object *)q;
nouveau_notifier_reset(ctx, nmesa->queryNotifier, nq->notifier_id);
switch (nmesa->screen->card->type) {
case NV_20:
BEGIN_RING_CACHE(NvSub3D, 0x17c8, 1);
OUT_RING_CACHE (1);
BEGIN_RING_CACHE(NvSub3D, 0x17cc, 1);
OUT_RING_CACHE (1);
break;
case NV_30:
case NV_40:
case NV_44:
/* I don't think this is OCC_QUERY enable, but it *is* needed to make
* the SET_OBJECT7 notifier block work with STORE_RESULT.
*
* Also, this appears to reset the pixel pass counter */
BEGIN_RING_SIZE(NvSub3D,
NV30_TCL_PRIMITIVE_3D_OCC_QUERY_OR_COLOR_BUFF_ENABLE,
1);
OUT_RING (1);
/* Probably OCC_QUERY_ENABLE */
BEGIN_RING_CACHE(NvSub3D, 0x17cc, 1);
OUT_RING_CACHE (1);
break;
default:
WARN_ONCE("no support for this card\n");
break;
}
}
static void
nouveauUpdateQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_query_object *nq = (nouveau_query_object *)q;
int status;
status = nouveau_notifier_status(ctx, nmesa->queryNotifier,
nq->notifier_id);
q->Ready = (status == NV_NOTIFY_STATE_STATUS_COMPLETED);
if (q->Ready)
q->Result = nouveau_notifier_return_val(ctx,
nmesa->queryNotifier,
nq->notifier_id);
}
static void
nouveauWaitQueryResult(GLcontext *ctx, GLenum target, struct gl_query_object *q)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
nouveau_query_object *nq = (nouveau_query_object *)q;
nouveau_notifier_wait_status(ctx, nmesa->queryNotifier, nq->notifier_id,
NV_NOTIFY_STATE_STATUS_COMPLETED, 0);
nouveauUpdateQuery(ctx, target, q);
}
static void
nouveauEndQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q)
{
nouveau_query_object *nq = (nouveau_query_object *)q;
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
switch (nmesa->screen->card->type) {
case NV_20:
BEGIN_RING_SIZE(NvSub3D, 0x17d0, 1);
OUT_RING (0x01000000 | nq->notifier_id*32);
break;
case NV_30:
case NV_40:
case NV_44:
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STORE_RESULT, 1);
OUT_RING (0x01000000 | nq->notifier_id*32);
break;
default:
WARN_ONCE("no support for this card\n");
break;
}
FIRE_RING();
/*XXX: wait for query to complete, mesa doesn't give the driver
* an interface to query the status of a query object so
* this has to stall the channel.
*/
nouveauWaitQueryResult(ctx, target, q);
BEGIN_RING_CACHE(NvSub3D, 0x17cc, 1);
OUT_RING_CACHE (0);
}
void
nouveauQueryInitFuncs(GLcontext *ctx)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
if (nmesa->screen->card->type < NV_20)
return;
/* Reserve half the notifier block for use as query objects */
nmesa->query_object_max = (nmesa->fifo.drm.notifier_size / 2) / 32;
nmesa->queryNotifier =
nouveau_notifier_new(ctx, NvQueryNotify,
nmesa->query_object_max);
nmesa->query_alloc = calloc(nmesa->query_object_max, sizeof(GLboolean));
switch (nmesa->screen->card->type) {
case NV_20:
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
OUT_RING_CACHE (NvQueryNotify);
break;
case NV_30:
case NV_40:
case NV_44:
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT7, 1);
OUT_RING_CACHE (NvQueryNotify);
break;
default:
break;
};
ctx->Driver.NewQueryObject = nouveauNewQueryObject;
ctx->Driver.BeginQuery = nouveauBeginQuery;
ctx->Driver.EndQuery = nouveauEndQuery;
#if 0
ctx->Driver.UpdateQuery = nouveauUpdateQuery;
ctx->Driver.WaitQueryResult = nouveauWaitQueryResult;
#endif
}

View file

@ -1,38 +0,0 @@
/*
* Copyright (C) 2007 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.
*
*/
#ifndef __NOUVEAU_QUERY_H__
#define __NOUVEAU_QUERY_H__
typedef struct nouveau_query_object_t {
struct gl_query_object mesa;
int notifier_id;
} nouveau_query_object;
extern void nouveauQueryInitFuncs(GLcontext *ctx);
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,325 +0,0 @@
/**************************************************************************
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 "nouveau_msg.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;
}
screen->card=nouveau_card_lookup(dri_priv->device_id);
if (!screen->card) {
__driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n",
__func__, dri_priv->device_id >> 16, dri_priv->device_id & 0xFFFF);
FREE(screen);
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->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_t *nrb;
struct gl_framebuffer *fb;
const GLboolean swAccum = mesaVis->accumRedBits > 0;
const GLboolean swStencil = (mesaVis->stencilBits > 0 &&
mesaVis->depthBits != 24);
GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5;
if (isPixmap)
return GL_FALSE; /* not implemented */
fb = _mesa_create_framebuffer(mesaVis);
if (!fb)
return GL_FALSE;
/* Front buffer */
nrb = nouveau_renderbuffer_new(color_format);
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa);
if (mesaVis->doubleBufferMode) {
nrb = nouveau_renderbuffer_new(color_format);
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa);
}
if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT);
_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);
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
} else
if (mesaVis->depthBits == 16) {
nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16);
_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_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
}
static int
nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo)
{
return -1;
}
static __DRIconfig **
nouveauFillInModes( __DRIscreenPrivate *psp,
unsigned pixel_bits, unsigned depth_bits,
unsigned stencil_bits, GLboolean have_back_buffer )
{
unsigned depth_buffer_factor;
unsigned back_buffer_factor;
/* 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;
if (pixel_bits == 16)
return driCreateConfigs(GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
depth_bits_array,
stencil_bits_array,
depth_buffer_factor,
back_buffer_modes,
back_buffer_factor);
else
return driCreateConfigs(GL_RGBA,
GL_UNSIGNED_INT_8_8_8_8_REV,
depth_bits_array,
stencil_bits_array,
depth_buffer_factor,
back_buffer_modes,
back_buffer_factor);
}
/**
* This is the driver specific part of the createNewScreen entry point.
*
* \todo maybe fold this into intelInitDriver
*
* \return the __GLcontextModes supported by this driver
*/
static const __DRIconfig **
nouveauInitScreen(__DRIscreenPrivate *psp)
{
static const __DRIversion ddx_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
static const __DRIversion dri_expected = { 4, 0, 0 };
static const __DRIversion drm_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
WARN_ONCE("\nThis driver is not currently maintained\n\n"
"Current work on 3D is in the gallium-0.1 branch of:\n"
" git://anongit.freedesktop.org/git/nouveau/mesa\n");
#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 10
#error nouveau_drm.h version does not match expected version
#endif
if (!driCheckDriDdxDrmVersions2("nouveau",
&psp->dri_version, & dri_expected,
&psp->ddx_version, & ddx_expected,
&psp->drm_version, & drm_expected))
return NULL;
// temporary lock step versioning
if (drm_expected.patch != psp->drm_version.patch) {
__driUtilMessage("%s: wrong DRM version, expected %d, got %d\n",
__func__,
drm_expected.patch, psp->drm_version.patch);
return NULL;
}
/* 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 );
if (!nouveauInitDriver(psp))
return NULL;
return (const __DRIconfig **)
nouveauFillInModes(psp,
dri_priv->bpp,
(dri_priv->bpp == 16) ? 16 : 24,
(dri_priv->bpp == 16) ? 0 : 8,
1);
}
const struct __DriverAPIRec driDriverAPI = {
.InitScreen = nouveauInitScreen,
.DestroyScreen = nouveauDestroyScreen,
.CreateContext = nouveauCreateContext,
.DestroyContext = nouveauDestroyContext,
.CreateBuffer = nouveauCreateBuffer,
.DestroyBuffer = nouveauDestroyBuffer,
.SwapBuffers = nouveauSwapBuffers,
.MakeCurrent = nouveauMakeCurrent,
.UnbindContext = nouveauUnbindContext,
.GetSwapInfo = nouveauGetSwapInfo,
.GetDrawableMSC = driDrawableGetMSC32,
.WaitForMSC = driWaitForMSC32,
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL,
.CopySubBuffer = nouveauCopySubBuffer
};
const __DRIextension *__driDriverExtensions[] = {
&driCoreExtension.base,
&driLegacyExtension.base,
NULL
};

View file

@ -1,61 +0,0 @@
/**************************************************************************
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__ */

View file

@ -1,833 +0,0 @@
/*
* 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 "shader/program.h"
#include "shader/prog_instruction.h"
/*#include "shader/arbprogparse.h"*/
#include "tnl/tnl.h"
#include "nouveau_context.h"
#include "nouveau_shader.h"
/*****************************************************************************
* Mesa entry points
*/
static void
nouveauBindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog)
{
NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog);
}
static struct gl_program *
nouveauNewProgram(GLcontext *ctx, GLenum target, GLuint id)
{
nouveauShader *nvs;
NVSDBG("target=%s, id=%d\n", _mesa_lookup_enum_by_nr(target), id);
nvs = CALLOC_STRUCT(_nouveauShader);
NVSDBG("prog=%p\n", nvs);
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;
NVSDBG("prog=%p\n", 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;
NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog);
if (nvs->translated)
FREE(nvs->program);
nvs->error = GL_FALSE;
nvs->translated = GL_FALSE;
_tnl_program_string(ctx, target, prog);
}
static GLboolean
nouveauIsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
{
nouveauShader *nvs = (nouveauShader *)prog;
NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog);
return nvs->translated;
}
GLboolean
nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
struct gl_program_parameter_list *plist;
int i;
NVSDBG("prog=%p\n", nvs);
/* Translate to HW format now if necessary */
if (!nvs->translated) {
/* Mesa ASM shader -> nouveauShader */
if (!nouveau_shader_pass0(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<nvs->param_high; i++) {
if (!nvs->params[i].in_use)
continue;
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 (nvs->params[i].source_val) {
/* 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_FRAGMENT_PROGRAM_ARB, 0);
_mesa_parse_arb_fragment_program(ctx,
GL_FRAGMENT_PROGRAM_ARB,
text,
strlen(text),
&nvs->mesa.fp);
}
nouveau_shader_pass0(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);
}
static void
nvsBuildPassthroughFP(GLcontext *ctx)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
const char *fp_text =
"!!ARBfp1.0\n"
"MOV result.color, fragment.color;\n"
"END";
nmesa->passthrough_fp = nvsBuildTextShader(ctx,
GL_FRAGMENT_PROGRAM_ARB,
fp_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);
/* Needed on NV30, even when using swtcl, if you want to get colours */
if (nmesa->screen->card->type >= NV_30)
nvsBuildPassthroughFP(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(nvsFragmentHeader *f, int lvl)
{
while (f) {
switch (f->type) {
case NVS_INSTRUCTION:
nvsDumpInstruction((nvsInstruction*)f, 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");
}

View file

@ -1,454 +0,0 @@
#ifndef __SHADER_COMMON_H__
#define __SHADER_COMMON_H__
#include "mtypes.h"
#include "bufferobj.h"
#define NVSDBG(fmt, args...) do { \
if (NOUVEAU_DEBUG & DEBUG_SHADERS) { \
fprintf(stderr, "%s: "fmt, __func__, ##args); \
} \
} while(0)
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 _nvs_fragment_header {
struct _nvs_fragment_header *parent;
struct _nvs_fragment_header *prev;
struct _nvs_fragment_header *next;
enum {
NVS_INSTRUCTION,
NVS_BRANCH,
NVS_LOOP,
NVS_SUBROUTINE
} type;
} nvsFragmentHeader;
typedef union {
struct {
GLboolean uses_kil;
GLuint num_regs;
} NV30FP;
struct {
uint32_t vp_in_reg;
uint32_t vp_out_reg;
uint32_t clip_enables;
} NV30VP;
} nvsCardPriv;
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 error;
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;
struct gl_buffer_object *program_buffer;
int inst_count;
nvsCardPriv card_priv;
int vp_attrib_map[NVS_MAX_ATTRIBS];
struct {
GLboolean in_use;
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];
int param_high;
/* Pass-private data */
void *pass_rec;
nvsFragmentHeader *program_tree;
} 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 = 0,
NVS_FR_WEIGHT = 1,
NVS_FR_NORMAL = 2,
NVS_FR_COL0 = 3,
NVS_FR_COL1 = 4,
NVS_FR_FOGCOORD = 5,
NVS_FR_TEXCOORD0 = 8,
NVS_FR_TEXCOORD1 = 9,
NVS_FR_TEXCOORD2 = 10,
NVS_FR_TEXCOORD3 = 11,
NVS_FR_TEXCOORD4 = 12,
NVS_FR_TEXCOORD5 = 13,
NVS_FR_TEXCOORD6 = 14,
NVS_FR_TEXCOORD7 = 15,
NVS_FR_BFC0 = 16,
NVS_FR_BFC1 = 17,
NVS_FR_POINTSZ = 18,
NVS_FR_FRAGDATA0 = 19,
NVS_FR_FRAGDATA1 = 20,
NVS_FR_FRAGDATA2 = 21,
NVS_FR_FRAGDATA3 = 22,
NVS_FR_CLIP0 = 23,
NVS_FR_CLIP1 = 24,
NVS_FR_CLIP2 = 25,
NVS_FR_CLIP3 = 26,
NVS_FR_CLIP4 = 27,
NVS_FR_CLIP5 = 28,
NVS_FR_CLIP6 = 29,
NVS_FR_FACING = 30,
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 enum {
NVS_SCALE_1X = 0,
NVS_SCALE_2X = 1,
NVS_SCALE_4X = 2,
NVS_SCALE_8X = 3,
NVS_SCALE_INV_2X = 5,
NVS_SCALE_INV_4X = 6,
NVS_SCALE_INV_8X = 7,
} nvsScale;
/* Arith/TEX instructions */
typedef struct nvs_instruction {
nvsFragmentHeader header;
nvsOpcode op;
unsigned int saturate;
nvsRegister dest;
unsigned int mask;
nvsScale dest_scale;
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;
/* BRA, CAL, IF */
typedef struct nvs_branch {
nvsFragmentHeader header;
nvsOpcode op;
nvsCond cond;
nvsSwzComp cond_swizzle[4];
int cond_test;
nvsFragmentHeader *target_head;
nvsFragmentHeader *target_tail;
nvsFragmentHeader *else_head;
nvsFragmentHeader *else_tail;
} nvsBranch;
/* LOOP+ENDLOOP */
typedef struct {
nvsFragmentHeader header;
int count;
int initial;
int increment;
nvsFragmentHeader *insn_head;
nvsFragmentHeader *insn_tail;
} nvsLoop;
/* label+following instructions */
typedef struct nvs_subroutine {
nvsFragmentHeader header;
char * label;
nvsFragmentHeader *insn_head;
nvsFragmentHeader *insn_tail;
} nvsSubroutine;
#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[];
extern void NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz);
extern nvsSwzComp NV20VP_TX_SWIZZLE[4];
#define SCAP_SRC_ABS (1<<0)
struct _nvsFunc {
nvsCardPriv *card_priv;
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);
int (*SupportsResultScale) (nvsFunc *, nvsScale);
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 (*SetResultScale) (nvsFunc *, nvsScale);
void (*SetSource) (nvsFunc *, nvsRegister *, int pos);
void (*SetTexImageUnit) (nvsFunc *, int unit);
void (*SetSaturate) (nvsFunc *);
void (*SetLastInst) (nvsFunc *);
void (*SetBranchTarget) (nvsFunc *, int addr);
void (*SetBranchElse) (nvsFunc *, int addr);
void (*SetBranchEnd) (nvsFunc *, int addr);
void (*SetLoopParams) (nvsFunc *, int cnt, int init, int inc);
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;
}
#define nvsProgramError(nvs,fmt,args...) do { \
fprintf(stderr, "nvsProgramError (%s): "fmt, __func__, ##args); \
(nvs)->error = GL_TRUE; \
(nvs)->translated = GL_FALSE; \
} while(0)
extern GLboolean nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs);
extern void nvsDisasmHWShader(nvsPtr);
extern void nvsDumpFragmentList(nvsFragmentHeader *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(GLcontext *ctx, nouveauShader *nvs);
extern GLboolean nouveau_shader_pass1(nvsPtr nvs);
extern GLboolean nouveau_shader_pass2(nvsPtr nvs);
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,16 +0,0 @@
#include "glheader.h"
#include "macros.h"
#include "enums.h"
#include "nouveau_context.h"
#include "nouveau_shader.h"
GLboolean
nouveau_shader_pass1(nvsPtr nvs)
{
NVSDBG("start: nvs=%p\n", nvs);
return GL_TRUE;
}

View file

@ -1,264 +0,0 @@
/*
* 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 "shader/prog_parameter.h"
#include "shader/prog_print.h"
#include "nouveau_context.h"
#include "nouveau_shader.h"
#include "nouveau_msg.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 nvsRegister
pass2_mangle_reg(nvsPtr nvs, nvsInstruction *inst, nvsRegister reg)
{
struct pass2_rec *rec = nvs->pass_rec;
if (reg.file == NVS_FILE_TEMP) {
if (rec->temps[reg.index] == -1)
rec->temps[reg.index] = pass2_alloc_hw_temp(nvs);
reg.index = rec->temps[reg.index];
}
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]);
shader->SetSource(shader, &reg, 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);
shader->SetResult(shader, &reg, inst->mask, slot);
if (inst->dest_scale != NVS_SCALE_1X) {
shader->SetResultScale(shader, inst->dest_scale);
}
}
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;
}
static GLboolean
pass2_translate(nvsPtr nvs, nvsFragmentHeader *f)
{
nvsFunc *shader = nvs->func;
GLboolean last;
while (f) {
last = (f == ((nvsSubroutine*)nvs->program_tree)->insn_tail);
switch (f->type) {
case NVS_INSTRUCTION:
if (!pass2_assemble_instruction(nvs,
(nvsInstruction *)f,
last))
return GL_FALSE;
break;
default:
WARN_ONCE("Unimplemented fragment type\n");
return GL_FALSE;
}
f = f->next;
}
return GL_TRUE;
}
/* Translate program into hardware format */
GLboolean
nouveau_shader_pass2(nvsPtr nvs)
{
struct pass2_rec *rec;
int i;
NVSDBG("start: nvs=%p\n", nvs);
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->mesa.vp.Base.NumInstructions * 4;
nvs->program = calloc(nvs->program_alloc_size, sizeof(uint32_t));
nvs->program_size = 0;
nvs->program_current = 0;
if (!pass2_translate(nvs,
((nvsSubroutine*)nvs->program_tree)->insn_head)) {
free(nvs->program);
nvs->program = NULL;
return GL_FALSE;
}
/* 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 (NOUVEAU_DEBUG & DEBUG_SHADERS) {
fflush(stdout); fflush(stderr);
fprintf(stderr, "-----------MESA PROGRAM target=%s, id=0x%x\n",
_mesa_lookup_enum_by_nr(
nvs->mesa.vp.Base.Target),
nvs->mesa.vp.Base.Id);
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, "----------------NV PROGRAM\n");
fflush(stdout); fflush(stderr);
nvsDisasmHWShader(nvs);
fflush(stdout); fflush(stderr);
fprintf(stderr, "^^^^^^^^^^^^^^^^NV PROGRAM\n");
fflush(stdout); fflush(stderr);
}
return GL_TRUE;
}

View file

@ -1,123 +0,0 @@
/**************************************************************************
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 HW_CLIPLOOP() \
do { \
int _nc = nmesa->numClipRects; \
while ( _nc-- ) { \
int minx = nmesa->pClipRects[_nc].x1 - nmesa->drawX; \
int miny = nmesa->pClipRects[_nc].y1 - nmesa->drawY; \
int maxx = nmesa->pClipRects[_nc].x2 - nmesa->drawX; \
int maxy = nmesa->pClipRects[_nc].y2 - nmesa->drawY;
#define LOCAL_VARS \
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); \
nouveau_renderbuffer_t *nrb = (nouveau_renderbuffer_t *)rb; \
GLuint height = nrb->mesa.Height; \
GLubyte *map = (GLubyte *)(nrb->map ? nrb->map : nrb->mem->map) + \
(nmesa->drawY * nrb->pitch) + (nmesa->drawX * nrb->cpp); \
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) (map + (Y)*nrb->pitch + (X)*nrb->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) (map + (Y)*nrb->pitch + (X)*nrb->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_t * nrb)
{
if (nrb->mesa._ActualFormat == GL_RGBA8)
nouveauInitPointers_ARGB8888(&nrb->mesa);
else // if (nrb->mesa._ActualFormat == GL_RGB5)
nouveauInitPointers_RGB565(&nrb->mesa);
}

View file

@ -1,39 +0,0 @@
/**************************************************************************
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_fbo.h"
extern void nouveauSpanInitFunctions(GLcontext *ctx);
extern void nouveauSpanSetFunctions(nouveau_renderbuffer_t *nrb);
#endif /* __NOUVEAU_SPAN_H__ */

View file

@ -1,368 +0,0 @@
/**************************************************************************
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 "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);
const GLfloat *v = ctx->Viewport._WindowMap.m;
GLfloat *m = nmesa->viewport.m;
GLfloat xoffset = nmesa->drawX, yoffset = nmesa->drawY + nmesa->drawH;
nmesa->depth_scale = 1.0 / ctx->DrawBuffer->_DepthMaxF;
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 nouveauUpdateProjectionMatrix(GLcontext *ctx)
{
}
static void nouveauUpdateModelviewMatrix(GLcontext *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)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
if ( new_state & _NEW_PROJECTION ) {
nmesa->hw_func.UpdateProjectionMatrix(ctx);
}
if ( new_state & _NEW_MODELVIEW ) {
nmesa->hw_func.UpdateModelviewMatrix(ctx);
}
_swrast_InvalidateState( ctx, new_state );
_swsetup_InvalidateState( ctx, new_state );
_vbo_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_04:
case NV_05:
nv04InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
break;
case NV_10:
case NV_11:
case NV_17:
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:
nv30InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
break;
case NV_50:
nv50InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
break;
default:
break;
}
nouveau_state_cache_init(nmesa);
}
/* Initialize the driver's state functions */
void nouveauDDInitStateFuncs(GLcontext *ctx)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(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;
/* Matrix updates */
nmesa->hw_func.UpdateProjectionMatrix = nouveauUpdateProjectionMatrix;
nmesa->hw_func.UpdateModelviewMatrix = nouveauUpdateModelviewMatrix;
}
#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(DepthRange)( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
STATE_INIT(Enable)( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
STATE_INIT(Enable)( ctx, GL_BLEND, ctx->Color.BlendEnabled );
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]);
}

View file

@ -1,50 +0,0 @@
/**************************************************************************
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 nv04InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
extern void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
extern void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
extern void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
extern void nv50InitStateFuncs(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

View file

@ -1,69 +0,0 @@
#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.hdirty[i/NOUVEAU_STATE_CACHE_HIER_SIZE]==0)&&(i<NOUVEAU_STATE_CACHE_ENTRIES))
i=(i&~(NOUVEAU_STATE_CACHE_HIER_SIZE-1))+NOUVEAU_STATE_CACHE_HIER_SIZE;
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;
if ((i+j)%NOUVEAU_STATE_CACHE_HIER_SIZE==0)
nmesa->state_cache.hdirty[(i+j)/NOUVEAU_STATE_CACHE_HIER_SIZE-1]=0;
}
i+=run;
}
}
while(i<NOUVEAU_STATE_CACHE_ENTRIES);
nmesa->state_cache.hdirty[NOUVEAU_STATE_CACHE_HIER_SIZE/NOUVEAU_STATE_CACHE_HIER_SIZE-1]=0;
}
// 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;
}

View file

@ -1,29 +0,0 @@
#ifndef __NOUVEAU_STATE_CACHE_H__
#define __NOUVEAU_STATE_CACHE_H__
#include "mtypes.h"
#define NOUVEAU_STATE_CACHE_ENTRIES 2048
// size of a dirty requests block
// you can play with that and tune the value to increase/decrease performance
// but keep it a power of 2 !
#define NOUVEAU_STATE_CACHE_HIER_SIZE 32
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;
// hierarchical dirty flags
uint8_t hdirty[NOUVEAU_STATE_CACHE_ENTRIES/NOUVEAU_STATE_CACHE_HIER_SIZE];
// master dirty flag
uint8_t dirty;
}nouveau_state_cache;
#endif

View file

@ -1,127 +0,0 @@
/**************************************************************************
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) {
//nv04FinishPrimitive(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) {
nv04TriInitFunctions(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 );
}

View file

@ -1,55 +0,0 @@
/**************************************************************************
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__ */

View file

@ -1,198 +0,0 @@
/*
* Copyright (C) 2007 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.
*
*/
#include "vblank.h" /* for DO_USLEEP */
#include "nouveau_context.h"
#include "nouveau_fifo.h"
#include "nouveau_mem.h"
#include "nouveau_msg.h"
#include "nouveau_object.h"
#include "nouveau_reg.h"
#include "nouveau_sync.h"
#define NOTIFIER(__v) \
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); \
volatile uint32_t *__v = (void*)nmesa->fifo.notifier_block + \
notifier->offset
struct drm_nouveau_notifierobj_alloc *
nouveau_notifier_new(GLcontext *ctx, GLuint handle, GLuint count)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
struct drm_nouveau_notifierobj_alloc *notifier;
int ret;
#ifdef NOUVEAU_RING_DEBUG
return NULL;
#endif
notifier = CALLOC_STRUCT(drm_nouveau_notifierobj_alloc);
if (!notifier)
return NULL;
notifier->channel = nmesa->fifo.drm.channel;
notifier->handle = handle;
notifier->count = count;
ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
notifier, sizeof(*notifier));
if (ret) {
MESSAGE("Failed to create notifier 0x%08x: %d\n", handle, ret);
FREE(notifier);
return NULL;
}
return notifier;
}
void
nouveau_notifier_destroy(GLcontext *ctx,
struct drm_nouveau_notifierobj_alloc *notifier)
{
/*XXX: free notifier object.. */
FREE(notifier);
}
void
nouveau_notifier_reset(GLcontext *ctx,
struct drm_nouveau_notifierobj_alloc *notifier,
GLuint id)
{
NOTIFIER(n);
#ifdef NOUVEAU_RING_DEBUG
return;
#endif
n[NV_NOTIFY_TIME_0 /4] = 0x00000000;
n[NV_NOTIFY_TIME_1 /4] = 0x00000000;
n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
n[NV_NOTIFY_STATE /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
NV_NOTIFY_STATE_STATUS_SHIFT);
}
GLuint
nouveau_notifier_status(GLcontext *ctx,
struct drm_nouveau_notifierobj_alloc *notifier,
GLuint id)
{
NOTIFIER(n);
return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
}
GLuint
nouveau_notifier_return_val(GLcontext *ctx,
struct drm_nouveau_notifierobj_alloc *notifier,
GLuint id)
{
NOTIFIER(n);
return n[NV_NOTIFY_RETURN_VALUE/4];
}
GLboolean
nouveau_notifier_wait_status(GLcontext *ctx,
struct drm_nouveau_notifierobj_alloc *notifier,
GLuint id, GLuint status, GLuint timeout)
{
NOTIFIER(n);
unsigned int time = 0;
#ifdef NOUVEAU_RING_DEBUG
return GL_TRUE;
#endif
while (time <= timeout) {
if (n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK) {
MESSAGE("Notifier returned error: 0x%04x\n",
n[NV_NOTIFY_STATE/4] &
NV_NOTIFY_STATE_ERROR_CODE_MASK);
return GL_FALSE;
}
if (((n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_STATUS_MASK) >>
NV_NOTIFY_STATE_STATUS_SHIFT) == status)
return GL_TRUE;
if (timeout) {
DO_USLEEP(1);
time++;
}
}
MESSAGE("Notifier timed out\n");
return GL_FALSE;
}
void
nouveau_notifier_wait_nop(GLcontext *ctx,
struct drm_nouveau_notifierobj_alloc *notifier,
GLuint subc)
{
NOTIFIER(n);
GLboolean ret;
nouveau_notifier_reset(ctx, notifier, 0);
BEGIN_RING_SIZE(subc, NV_NOTIFY, 1);
OUT_RING (NV_NOTIFY_STYLE_WRITE_ONLY);
BEGIN_RING_SIZE(subc, NV_NOP, 1);
OUT_RING (0);
FIRE_RING();
ret = nouveau_notifier_wait_status(ctx, notifier, 0,
NV_NOTIFY_STATE_STATUS_COMPLETED,
0 /* no timeout */);
if (ret == GL_FALSE) MESSAGE("wait on notifier failed\n");
}
GLboolean nouveauSyncInitFuncs(GLcontext *ctx)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
#ifdef NOUVEAU_RING_DEBUG
return GL_TRUE;
#endif
nmesa->syncNotifier = nouveau_notifier_new(ctx, NvSyncNotify, 1);
if (!nmesa->syncNotifier) {
MESSAGE("Failed to create channel sync notifier\n");
return GL_FALSE;
}
/* 0x180 is SET_DMA_NOTIFY, should be correct for all supported 3D
* object classes
*/
BEGIN_RING_CACHE(NvSub3D, 0x180, 1);
OUT_RING_CACHE (NvSyncNotify);
BEGIN_RING_SIZE(NvSubMemFormat,
NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
OUT_RING (NvSyncNotify);
return GL_TRUE;
}

View file

@ -1,69 +0,0 @@
/*
* Copyright (C) 2007 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.
*
*/
#ifndef __NOUVEAU_SYNC_H__
#define __NOUVEAU_SYNC_H__
#define NV_NOTIFIER_SIZE 32
#define NV_NOTIFY_TIME_0 0x00000000
#define NV_NOTIFY_TIME_1 0x00000004
#define NV_NOTIFY_RETURN_VALUE 0x00000008
#define NV_NOTIFY_STATE 0x0000000C
#define NV_NOTIFY_STATE_STATUS_MASK 0xFF000000
#define NV_NOTIFY_STATE_STATUS_SHIFT 24
#define NV_NOTIFY_STATE_STATUS_COMPLETED 0x00
#define NV_NOTIFY_STATE_STATUS_IN_PROCESS 0x01
#define NV_NOTIFY_STATE_ERROR_CODE_MASK 0x0000FFFF
#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT 0
/* Methods that (hopefully) all objects have */
#define NV_NOP 0x00000100
#define NV_NOTIFY 0x00000104
#define NV_NOTIFY_STYLE_WRITE_ONLY 0
extern struct drm_nouveau_notifierobj_alloc *
nouveau_notifier_new(GLcontext *, GLuint handle, GLuint count);
extern void
nouveau_notifier_destroy(GLcontext *, struct drm_nouveau_notifierobj_alloc *);
extern void
nouveau_notifier_reset(GLcontext *, struct drm_nouveau_notifierobj_alloc *,
GLuint id);
extern GLuint
nouveau_notifier_status(GLcontext *, struct drm_nouveau_notifierobj_alloc *,
GLuint id);
extern GLuint
nouveau_notifier_return_val(GLcontext *, struct drm_nouveau_notifierobj_alloc *,
GLuint id);
extern GLboolean
nouveau_notifier_wait_status(GLcontext *, struct drm_nouveau_notifierobj_alloc *,
GLuint id, GLuint status, GLuint timeout);
extern void
nouveau_notifier_wait_nop(GLcontext *ctx, struct drm_nouveau_notifierobj_alloc *,
GLuint subc);
extern GLboolean nouveauSyncInitFuncs(GLcontext *ctx);
#endif

View file

@ -1,49 +0,0 @@
/**************************************************************************
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();
*/
}

View file

@ -1,38 +0,0 @@
/**************************************************************************
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__ */

View file

@ -1,540 +0,0 @@
/**************************************************************************
Copyright 2007 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_object.h"
#include "nouveau_fifo.h"
#include "nouveau_reg.h"
#include "nouveau_msg.h"
#include "tnl/t_pipeline.h"
#include "mtypes.h"
#include "colormac.h"
static uint32_t nv04_compare_func(GLuint f)
{
switch ( f ) {
case GL_NEVER: return 1;
case GL_LESS: return 2;
case GL_EQUAL: return 3;
case GL_LEQUAL: return 4;
case GL_GREATER: return 5;
case GL_NOTEQUAL: return 6;
case GL_GEQUAL: return 7;
case GL_ALWAYS: return 8;
}
WARN_ONCE("Unable to find the function\n");
return 0;
}
static uint32_t nv04_blend_func(GLuint f)
{
switch ( f ) {
case GL_ZERO: return 0x1;
case GL_ONE: return 0x2;
case GL_SRC_COLOR: return 0x3;
case GL_ONE_MINUS_SRC_COLOR: return 0x4;
case GL_SRC_ALPHA: return 0x5;
case GL_ONE_MINUS_SRC_ALPHA: return 0x6;
case GL_DST_ALPHA: return 0x7;
case GL_ONE_MINUS_DST_ALPHA: return 0x8;
case GL_DST_COLOR: return 0x9;
case GL_ONE_MINUS_DST_COLOR: return 0xA;
case GL_SRC_ALPHA_SATURATE: return 0xB;
}
WARN_ONCE("Unable to find the function 0x%x\n",f);
return 0;
}
static void nv04_emit_control(GLcontext *ctx)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
uint32_t control,cull;
GLubyte alpha_ref;
CLAMPED_FLOAT_TO_UBYTE(alpha_ref, ctx->Color.AlphaRef);
control=alpha_ref;
control|=(nv04_compare_func(ctx->Color.AlphaFunc)<<8);
control|=(ctx->Color.AlphaEnabled<<12);
control|=(1<<13);
control|=(ctx->Depth.Test<<14);
control|=(nv04_compare_func(ctx->Depth.Func)<<16);
if ((ctx->Polygon.CullFlag)&&(ctx->Polygon.CullFaceMode!=GL_FRONT_AND_BACK))
{
if ((ctx->Polygon.FrontFace==GL_CW)&&(ctx->Polygon.CullFaceMode==GL_FRONT))
cull=2;
if ((ctx->Polygon.FrontFace==GL_CW)&&(ctx->Polygon.CullFaceMode==GL_BACK))
cull=3;
if ((ctx->Polygon.FrontFace==GL_CCW)&&(ctx->Polygon.CullFaceMode==GL_FRONT))
cull=3;
if ((ctx->Polygon.FrontFace==GL_CCW)&&(ctx->Polygon.CullFaceMode==GL_BACK))
cull=2;
}
else
if (ctx->Polygon.CullFaceMode==GL_FRONT_AND_BACK)
cull=0;
else
cull=1;
control|=(cull<<20);
control|=(ctx->Color.DitherFlag<<22);
if ((ctx->Depth.Test)&&(ctx->Depth.Mask))
control|=(1<<24);
control|=(1<<30); // integer zbuffer format
BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1);
OUT_RING_CACHE(control);
}
static void nv04_emit_blend(GLcontext *ctx)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
uint32_t blend;
blend=0x4; // texture MODULATE_ALPHA
blend|=0x20; // alpha is MSB
switch(ctx->Light.ShadeModel) {
case GL_SMOOTH:blend|=(1<<6);break;
case GL_FLAT: blend|=(2<<6);break;
default:break;
}
if (ctx->Hint.PerspectiveCorrection!=GL_FASTEST)
blend|=(1<<8);
blend|=(ctx->Fog.Enabled<<16);
blend|=(ctx->Color.BlendEnabled<<20);
blend|=(nv04_blend_func(ctx->Color.BlendSrcRGB)<<24);
blend|=(nv04_blend_func(ctx->Color.BlendDstRGB)<<28);
BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1);
OUT_RING_CACHE(blend);
}
static void nv04_emit_fog_color(GLcontext *ctx)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte c[4];
c[0] = FLOAT_TO_UBYTE( ctx->Fog.Color[0] );
c[1] = FLOAT_TO_UBYTE( ctx->Fog.Color[1] );
c[2] = FLOAT_TO_UBYTE( ctx->Fog.Color[2] );
c[3] = FLOAT_TO_UBYTE( ctx->Fog.Color[3] );
BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_FOG_COLOR, 1);
OUT_RING_CACHE(PACK_COLOR_8888_REV(c[0],c[1],c[2],c[3]));
}
static void nv04AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
{
nv04_emit_control(ctx);
}
static void nv04BlendColor(GLcontext *ctx, const GLfloat color[4])
{
nv04_emit_blend(ctx);
}
static void nv04BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
{
nv04_emit_blend(ctx);
}
static void nv04BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
GLenum sfactorA, GLenum dfactorA)
{
nv04_emit_blend(ctx);
}
static void nv04Clear(GLcontext *ctx, GLbitfield mask)
{
/* TODO */
}
static void nv04ClearColor(GLcontext *ctx, const GLfloat color[4])
{
/* TODO */
}
static void nv04ClearDepth(GLcontext *ctx, GLclampd d)
{
/* TODO */
}
static void nv04ClearStencil(GLcontext *ctx, GLint s)
{
/* TODO */
}
static void nv04ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
{
/* TODO */
}
static void nv04ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
GLboolean bmask, GLboolean amask )
{
/* TODO */
}
static void nv04ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
{
/* TODO I need love */
}
static void nv04CullFace(GLcontext *ctx, GLenum mode)
{
nv04_emit_control(ctx);
}
static void nv04FrontFace(GLcontext *ctx, GLenum mode)
{
/* TODO */
}
static void nv04DepthFunc(GLcontext *ctx, GLenum func)
{
nv04_emit_control(ctx);
}
static void nv04DepthMask(GLcontext *ctx, GLboolean flag)
{
/* TODO */
}
static void nv04DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
{
/* TODO */
}
/** 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 nv04Enable(GLcontext *ctx, GLenum cap, GLboolean state)
{
switch(cap)
{
case GL_ALPHA_TEST:
nv04_emit_control(ctx);
break;
// case GL_AUTO_NORMAL:
case GL_BLEND:
nv04_emit_blend(ctx);
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:
// case GL_COLOR_LOGIC_OP:
// 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:
nv04_emit_control(ctx);
break;
case GL_DEPTH_TEST:
nv04_emit_control(ctx);
break;
case GL_DITHER:
nv04_emit_control(ctx);
break;
case GL_FOG:
nv04_emit_blend(ctx);
nv04_emit_fog_color(ctx);
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:
// case GL_LIGHTING:
// 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:
// case GL_POINT_SMOOTH:
// case GL_POLYGON_OFFSET_POINT:
// case GL_POLYGON_OFFSET_LINE:
// case GL_POLYGON_OFFSET_FILL:
// case GL_POLYGON_SMOOTH:
// 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:
// 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 nv04Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
{
nv04_emit_blend(ctx);
nv04_emit_fog_color(ctx);
}
static void nv04Hint(GLcontext *ctx, GLenum target, GLenum mode)
{
switch(target)
{
case GL_PERSPECTIVE_CORRECTION_HINT:nv04_emit_blend(ctx);break;
default:break;
}
}
static void nv04LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
{
/* TODO not even in your dreams */
}
static void nv04LineWidth(GLcontext *ctx, GLfloat width)
{
/* TODO */
}
static void nv04LogicOpcode(GLcontext *ctx, GLenum opcode)
{
/* TODO */
}
static void nv04PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
{
/* TODO */
}
static void nv04PointSize(GLcontext *ctx, GLfloat size)
{
/* TODO */
}
static void nv04PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
{
/* TODO */
}
/** Set the scale and units used to calculate depth values */
static void nv04PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units)
{
/* TODO */
}
/** Set the polygon stippling pattern */
static void nv04PolygonStipple(GLcontext *ctx, const GLubyte *mask )
{
/* TODO */
}
/* 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 nv04Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
/* TODO */
}
/** Select flat or smooth shading */
static void nv04ShadeModel(GLcontext *ctx, GLenum mode)
{
nv04_emit_blend(ctx);
}
/** OpenGL 2.0 two-sided StencilFunc */
static void nv04StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
GLint ref, GLuint mask)
{
/* TODO */
}
/** OpenGL 2.0 two-sided StencilMask */
static void nv04StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
{
/* TODO */
}
/** OpenGL 2.0 two-sided StencilOp */
static void nv04StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
GLenum zfail, GLenum zpass)
{
/* TODO */
}
/** 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);
/* Update anything that depends on the window position/size */
static void nv04WindowMoved(nouveauContextPtr nmesa)
{
}
/* Initialise any card-specific non-GL related state */
static GLboolean nv04InitCard(nouveauContextPtr nmesa)
{
nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf3D, NvCtxSurf3D);
BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_DMA_NOTIFY, 3);
OUT_RING(NvDmaFB);
OUT_RING(NvDmaFB);
OUT_RING(NvDmaFB);
BEGIN_RING_SIZE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_SURFACE, 1);
OUT_RING(NvCtxSurf3D);
return GL_TRUE;
}
/* Update buffer offset/pitch/format */
static GLboolean nv04BindBuffers(nouveauContextPtr nmesa, int num_color,
nouveau_renderbuffer_t **color,
nouveau_renderbuffer_t *depth)
{
GLuint x, y, w, h;
uint32_t depth_pitch=(depth?depth->pitch:0+15)&~15+16;
if (depth_pitch<256) depth_pitch=256;
w = color[0]->mesa.Width;
h = color[0]->mesa.Height;
x = nmesa->drawX;
y = nmesa->drawY;
BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_FORMAT, 1);
if (color[0]->mesa._ActualFormat == GL_RGBA8)
OUT_RING(0x108/*A8R8G8B8*/);
else
OUT_RING(0x103/*R5G6B5*/);
/* FIXME pitches have to be aligned ! */
BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_PITCH, 2);
OUT_RING(color[0]->pitch|(depth_pitch<<16));
OUT_RING(color[0]->offset);
if (depth) {
BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1);
OUT_RING(depth->offset);
}
// BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL, 2);
// OUT_RING((w<<16)|x);
// OUT_RING((h<<16)|y);
/* FIXME not sure... */
/* BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_CLIP_SIZE, 1);
OUT_RING((h<<16)|w);*/
return GL_TRUE;
}
void nv04InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
func->AlphaFunc = nv04AlphaFunc;
func->BlendColor = nv04BlendColor;
func->BlendEquationSeparate = nv04BlendEquationSeparate;
func->BlendFuncSeparate = nv04BlendFuncSeparate;
func->Clear = nv04Clear;
func->ClearColor = nv04ClearColor;
func->ClearDepth = nv04ClearDepth;
func->ClearStencil = nv04ClearStencil;
func->ClipPlane = nv04ClipPlane;
func->ColorMask = nv04ColorMask;
func->ColorMaterial = nv04ColorMaterial;
func->CullFace = nv04CullFace;
func->FrontFace = nv04FrontFace;
func->DepthFunc = nv04DepthFunc;
func->DepthMask = nv04DepthMask;
func->DepthRange = nv04DepthRange;
func->Enable = nv04Enable;
func->Fogfv = nv04Fogfv;
func->Hint = nv04Hint;
/* func->Lightfv = nv04Lightfv;*/
/* func->LightModelfv = nv04LightModelfv; */
func->LineStipple = nv04LineStipple; /* Not for NV04 */
func->LineWidth = nv04LineWidth;
func->LogicOpcode = nv04LogicOpcode;
func->PointParameterfv = nv04PointParameterfv;
func->PointSize = nv04PointSize;
func->PolygonMode = nv04PolygonMode;
func->PolygonOffset = nv04PolygonOffset;
func->PolygonStipple = nv04PolygonStipple; /* Not for NV04 */
/* func->ReadBuffer = nv04ReadBuffer;*/
/* func->RenderMode = nv04RenderMode;*/
func->Scissor = nv04Scissor;
func->ShadeModel = nv04ShadeModel;
func->StencilFuncSeparate = nv04StencilFuncSeparate;
func->StencilMaskSeparate = nv04StencilMaskSeparate;
func->StencilOpSeparate = nv04StencilOpSeparate;
/* func->TexGen = nv04TexGen;*/
/* func->TexParameter = nv04TexParameter;*/
/* func->TextureMatrix = nv04TextureMatrix;*/
nmesa->hw_func.InitCard = nv04InitCard;
nmesa->hw_func.BindBuffers = nv04BindBuffers;
nmesa->hw_func.WindowMoved = nv04WindowMoved;
}

View file

@ -1,619 +0,0 @@
/*
* Copyright 2007 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 NV04, NV05, NV06 */
#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 "nv04_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 nv04RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
static void nv04RenderPrimitive( GLcontext *ctx, GLenum prim );
static void nv04ResetLineStipple( GLcontext *ctx );
static INLINE void nv04_2triangles(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2,nouveauVertex* v3,nouveauVertex* v4,nouveauVertex* v5)
{
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
OUT_RINGp(v0,8);
OUT_RINGp(v1,8);
OUT_RINGp(v2,8);
OUT_RINGp(v3,8);
OUT_RINGp(v4,8);
OUT_RINGp(v5,8);
OUT_RING(0xFEDCBA);
}
static INLINE void nv04_1triangle(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2)
{
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
OUT_RINGp(v0,8);
OUT_RINGp(v1,8);
OUT_RINGp(v2,8);
OUT_RING(0xFED);
}
static INLINE void nv04_1quad(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2,nouveauVertex* v3)
{
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
OUT_RINGp(v0,8);
OUT_RINGp(v1,8);
OUT_RINGp(v2,8);
OUT_RINGp(v3,8);
OUT_RING(0xFECEDC);
}
static INLINE void nv04_render_points(GLcontext *ctx,GLuint first,GLuint last)
{
WARN_ONCE("Unimplemented\n");
}
static INLINE void nv04_render_line(GLcontext *ctx,GLuint v1,GLuint v2)
{
WARN_ONCE("Unimplemented\n");
}
static INLINE void nv04_render_triangle(GLcontext *ctx,GLuint v1,GLuint v2,GLuint v3)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
nv04_1triangle(nmesa,
(nouveauVertex*)(vertptr+v1*vertsize),
(nouveauVertex*)(vertptr+v2*vertsize),
(nouveauVertex*)(vertptr+v3*vertsize)
);
}
static INLINE void nv04_render_quad(GLcontext *ctx,GLuint v1,GLuint v2,GLuint v3,GLuint v4)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
nv04_1quad(nmesa,
(nouveauVertex*)(vertptr+v1*vertsize),
(nouveauVertex*)(vertptr+v2*vertsize),
(nouveauVertex*)(vertptr+v3*vertsize),
(nouveauVertex*)(vertptr+v4*vertsize)
);
}
/**********************************************************************/
/* Render unclipped begin/end objects */
/**********************************************************************/
static void nv04_render_points_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
// erm
}
static void nv04_render_lines_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
// umm
}
static void nv04_render_line_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
// yeah
}
static void nv04_render_line_loop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
// right
}
static void nv04_render_triangles_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
int i;
for(i=start;i<count-5;i+=6)
nv04_2triangles(nmesa,
(nouveauVertex*)(vertptr+(i+0)*vertsize),
(nouveauVertex*)(vertptr+(i+1)*vertsize),
(nouveauVertex*)(vertptr+(i+2)*vertsize),
(nouveauVertex*)(vertptr+(i+3)*vertsize),
(nouveauVertex*)(vertptr+(i+4)*vertsize),
(nouveauVertex*)(vertptr+(i+5)*vertsize)
);
if (i!=count)
{
nv04_1triangle(nmesa,
(nouveauVertex*)(vertptr+(i+0)*vertsize),
(nouveauVertex*)(vertptr+(i+1)*vertsize),
(nouveauVertex*)(vertptr+(i+2)*vertsize)
);
i+=3;
}
if (i!=count)
printf("oops\n");
}
static void nv04_render_tri_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
int i,j;
for(i=start;i<count;i+=14)
{
int numvert=MIN2(16,count-i);
int numtri=numvert-2;
if (numvert<3)
break;
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert*8);
for(j=0;j<numvert;j++)
OUT_RINGp((nouveauVertex*)(vertptr+(i+j)*vertsize),8);
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
for(j=0;j<numtri/2;j++)
OUT_RING(striptbl[j]);
if (numtri%2)
OUT_RING(striptbl[numtri/2]&0xFFF);
}
}
static void nv04_render_tri_fan_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
int i,j;
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8);
OUT_RINGp((nouveauVertex*)(vertptr+start*vertsize),8);
for(i=start+1;i<count;i+=14)
{
int numvert=MIN2(15,count-i);
int numtri=numvert-1;
if (numvert<3)
break;
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert*8);
for(j=0;j<numvert;j++)
OUT_RINGp((nouveauVertex*)(vertptr+(i+j)*vertsize),8);
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
for(j=0;j<numtri/2;j++)
OUT_RING(fantbl[j]);
if (numtri%2)
OUT_RING(fantbl[numtri/2]&0xFFF);
}
}
static void nv04_render_quads_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
int i;
for(i=start;i<count;i+=4)
nv04_1quad(nmesa,
(nouveauVertex*)(vertptr+(i+0)*vertsize),
(nouveauVertex*)(vertptr+(i+1)*vertsize),
(nouveauVertex*)(vertptr+(i+2)*vertsize),
(nouveauVertex*)(vertptr+(i+3)*vertsize)
);
}
static void nv04_render_noop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
}
static void (*nv04_render_tab_verts[GL_POLYGON+2])(GLcontext *,
GLuint,
GLuint,
GLuint) =
{
nv04_render_points_verts,
nv04_render_lines_verts,
nv04_render_line_loop_verts,
nv04_render_line_strip_verts,
nv04_render_triangles_verts,
nv04_render_tri_strip_verts,
nv04_render_tri_fan_verts,
nv04_render_quads_verts,
nv04_render_tri_strip_verts, //nv04_render_quad_strip_verts
nv04_render_tri_fan_verts, //nv04_render_poly_verts
nv04_render_noop_verts,
};
static void nv04_render_points_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
// erm
}
static void nv04_render_lines_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
// umm
}
static void nv04_render_line_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
// yeah
}
static void nv04_render_line_loop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
// right
}
static void nv04_render_triangles_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
int i;
for(i=start;i<count-5;i+=6)
nv04_2triangles(nmesa,
(nouveauVertex*)(vertptr+elt[i+0]*vertsize),
(nouveauVertex*)(vertptr+elt[i+1]*vertsize),
(nouveauVertex*)(vertptr+elt[i+2]*vertsize),
(nouveauVertex*)(vertptr+elt[i+3]*vertsize),
(nouveauVertex*)(vertptr+elt[i+4]*vertsize),
(nouveauVertex*)(vertptr+elt[i+5]*vertsize)
);
if (i!=count)
{
nv04_1triangle(nmesa,
(nouveauVertex*)(vertptr+elt[i+0]*vertsize),
(nouveauVertex*)(vertptr+elt[i+1]*vertsize),
(nouveauVertex*)(vertptr+elt[i+2]*vertsize)
);
i+=3;
}
if (i!=count)
printf("oops\n");
}
static void nv04_render_tri_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
int i,j;
for(i=start;i<count;i+=14)
{
int numvert=MIN2(16,count-i);
int numtri=numvert-2;
if (numvert<3)
break;
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert*8);
for(j=0;j<numvert;j++)
OUT_RINGp((nouveauVertex*)(vertptr+elt[i+j]*vertsize),8);
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
for(j=0;j<numtri/2;j++)
OUT_RING(striptbl[j]);
if (numtri%2)
OUT_RING(striptbl[numtri/2]&0xFFF);
}
}
static void nv04_render_tri_fan_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
int i,j;
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8);
OUT_RINGp((nouveauVertex*)(vertptr+elt[start]*vertsize),8);
for(i=start+1;i<count;i+=14)
{
int numvert=MIN2(15,count-i);
int numtri=numvert-2;
if (numvert<3)
break;
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert*8);
for(j=0;j<numvert;j++)
OUT_RINGp((nouveauVertex*)(vertptr+elt[i+j]*vertsize),8);
BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
for(j=0;j<numtri/2;j++)
OUT_RING(fantbl[j]);
if (numtri%2)
OUT_RING(fantbl[numtri/2]&0xFFF);
}
}
static void nv04_render_quads_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte *vertptr = (GLubyte *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
int i;
for(i=start;i<count;i+=4)
nv04_1quad(nmesa,
(nouveauVertex*)(vertptr+elt[i+0]*vertsize),
(nouveauVertex*)(vertptr+elt[i+1]*vertsize),
(nouveauVertex*)(vertptr+elt[i+2]*vertsize),
(nouveauVertex*)(vertptr+elt[i+3]*vertsize)
);
}
static void nv04_render_noop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
{
}
static void (*nv04_render_tab_elts[GL_POLYGON+2])(GLcontext *,
GLuint,
GLuint,
GLuint) =
{
nv04_render_points_elts,
nv04_render_lines_elts,
nv04_render_line_loop_elts,
nv04_render_line_strip_elts,
nv04_render_triangles_elts,
nv04_render_tri_strip_elts,
nv04_render_tri_fan_elts,
nv04_render_quads_elts,
nv04_render_tri_strip_elts, // nv04_render_quad_strip_elts,
nv04_render_tri_fan_elts, // nv04_render_poly_elts,
nv04_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)
#define EMIT_PAD( N ) \
do { \
nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = 0; \
nmesa->vertex_attrs[nmesa->vertex_attr_count].format = EMIT_PAD; \
nmesa->vertex_attrs[nmesa->vertex_attr_count].offset = (N); \
nmesa->vertex_attr_count++; \
} while (0)
static void nv04_render_clipped_line(GLcontext *ctx,GLuint ii,GLuint jj)
{
}
static void nv04_render_clipped_poly(GLcontext *ctx,const GLuint *elts,GLuint n)
{
}
static void nv04ChooseRenderState(GLcontext *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->Driver.Render.PrimTabVerts = nv04_render_tab_verts;
tnl->Driver.Render.PrimTabElts = nv04_render_tab_elts;
tnl->Driver.Render.ClippedLine = nv04_render_clipped_line;
tnl->Driver.Render.ClippedPolygon = nv04_render_clipped_poly;
tnl->Driver.Render.Points = nv04_render_points;
tnl->Driver.Render.Line = nv04_render_line;
tnl->Driver.Render.Triangle = nv04_render_triangle;
tnl->Driver.Render.Quad = nv04_render_quad;
}
static INLINE void nv04OutputVertexFormat(struct nouveau_context* nmesa)
{
GLcontext* ctx=nmesa->glCtx;
DECLARE_RENDERINPUTS(index);
/*
* Tell t_vertex about the vertex format
*/
nmesa->vertex_attr_count = 0;
RENDERINPUTS_COPY(index, nmesa->render_inputs_bitset);
// SX SY SZ INVW
// FIXME : we use W instead of INVW, but since W=1 it doesn't matter
if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_POS))
EMIT_ATTR(_TNL_ATTRIB_POS,EMIT_4F_VIEWPORT);
else
EMIT_PAD(4*sizeof(float));
// COLOR
if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_COLOR0))
EMIT_ATTR(_TNL_ATTRIB_COLOR0,EMIT_4UB_4F_ABGR);
else
EMIT_PAD(4);
// SPECULAR
if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_COLOR1))
EMIT_ATTR(_TNL_ATTRIB_COLOR1,EMIT_4UB_4F_ABGR);
else
EMIT_PAD(4);
// TEXTURE
if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_TEX0))
EMIT_ATTR(_TNL_ATTRIB_TEX0,EMIT_2F);
else
EMIT_PAD(2*sizeof(float));
nmesa->vertex_size=_tnl_install_attrs( ctx,
nmesa->vertex_attrs,
nmesa->vertex_attr_count,
nmesa->viewport.m, 0 );
}
static void nv04ChooseVertexState( 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);
nv04OutputVertexFormat(nmesa);
}
}
/**********************************************************************/
/* High level hooks for t_vb_render.c */
/**********************************************************************/
static void nv04RenderStart(GLcontext *ctx)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
if (nmesa->new_state) {
nmesa->new_render_state |= nmesa->new_state;
}
if (nmesa->new_render_state) {
nv04ChooseVertexState(ctx);
nv04ChooseRenderState(ctx);
nmesa->new_render_state = 0;
}
}
static void nv04RenderFinish(GLcontext *ctx)
{
}
/* System to flush dma and emit state changes based on the rasterized
* primitive.
*/
void nv04RasterPrimitive(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 nv04RenderPrimitive( GLcontext *ctx, GLuint prim )
{
nv04RasterPrimitive( ctx, prim, hw_prim[prim] );
}
static void nv04ResetLineStipple( GLcontext *ctx )
{
/* FIXME do something here */
WARN_ONCE("Unimplemented nv04ResetLineStipple\n");
}
/**********************************************************************/
/* Initialization. */
/**********************************************************************/
void nv04TriInitFunctions(GLcontext *ctx)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->Driver.RunPipeline = nouveauRunPipeline;
tnl->Driver.Render.Start = nv04RenderStart;
tnl->Driver.Render.Finish = nv04RenderFinish;
tnl->Driver.Render.PrimitiveNotify = nv04RenderPrimitive;
tnl->Driver.Render.ResetLineStipple = nv04ResetLineStipple;
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, 32 );
nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
}

View file

@ -1,12 +0,0 @@
#ifndef __NV04_SWTCL_H__
#define __NV04_SWTCL_H__
#include "mtypes.h"
extern void nv04Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
extern void nv04FinishPrimitive(struct nouveau_context *nmesa);
extern void nv04TriInitFunctions(GLcontext *ctx);
#define FALLBACK( nmesa, bit, mode ) nouveauFallback( nmesa->glCtx, bit, mode )
#endif /* __NV04_SWTCL_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,714 +0,0 @@
/*
* 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, NV50 */
#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 );
static const int default_attr_size[8]={3,3,3,4,3,1,4,4};
/* Mesa requires us to put pos attribute as the first attribute of the
* vertex, but on NV10 it is the last attribute.
* To fix that we put the pos attribute first, and we swap the pos
* attribute before sending it to the card.
* Speed cost of the swap seems negligeable
*/
#if 0
/* old stuff where pos attribute isn't put first for mesa.
* Usefull for speed comparaison
*/
#define INV_VERT(i) i
#define OUT_RING_VERTp(nmesa, ptr,sz, vertex_size) OUT_RINGp(ptr,sz)
#define OUT_RING_VERT(nmesa, ptr, vertex_size) OUT_RINGp(ptr,vertex_size)
#else
#define INV_VERT(i) (i==0?7:i-1)
#define OUT_RING_VERT_RAW(ptr,vertex_size) do{ \
/* if the vertex size is not null, we have at least pos attribute */ \
OUT_RINGp((GLfloat *)(ptr) + default_attr_size[_TNL_ATTRIB_POS], (vertex_size) - default_attr_size[_TNL_ATTRIB_POS]); \
OUT_RINGp((GLfloat *)(ptr), default_attr_size[_TNL_ATTRIB_POS]); \
}while(0)
#define OUT_RING_VERT(nmesa,ptr,vertex_size) do{ \
if (nmesa->screen->card->type>=NV_20) \
OUT_RINGp(ptr, vertex_size); \
else \
OUT_RING_VERT_RAW(ptr, vertex_size); \
}while(0)
#define OUT_RING_VERTp(nmesa, ptr,sz, vertex_size) do{ \
int nb_vert; \
if (nmesa->screen->card->type>=NV_20) \
OUT_RINGp(ptr, sz); \
else \
for (nb_vert = 0; nb_vert < (sz)/(vertex_size); nb_vert++) { \
OUT_RING_VERT_RAW((GLfloat*)(ptr)+nb_vert*(vertex_size), vertex_size); \
} \
}while(0)
#endif
static INLINE void nv10StartPrimitive(struct nouveau_context* nmesa,GLuint primitive,GLuint size)
{
if ((nmesa->screen->card->type>=NV_10) && (nmesa->screen->card->type<=NV_17))
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) && (nmesa->screen->card->type<=NV_17))
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);
}
void nv10FinishPrimitive(struct nouveau_context *nmesa)
{
if ((nmesa->screen->card->type>=NV_10) && (nmesa->screen->card->type<=NV_17))
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);
}
}
/**********************************************************************/
/* 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);
GLfloat *vertptr = (GLfloat *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
GLuint size_dword = vertsize*(count-start);
nv10ExtendPrimitive(nmesa, size_dword);
nv10StartPrimitive(nmesa,prim+1,size_dword);
OUT_RING_VERTp(nmesa, (nouveauVertex*)(vertptr+(start*vertsize)),size_dword, vertsize);
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);
GLfloat *vertptr = (GLfloat *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
GLuint size_dword = vertsize*(count-start);
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_RING_VERT(nmesa, (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 INLINE void nv10_render_point(GLcontext *ctx, GLfloat *vertptr)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLuint vertsize = nmesa->vertex_size;
GLuint size_dword = vertsize;
nv10ExtendPrimitive(nmesa, size_dword);
nv10StartPrimitive(nmesa,GL_POINTS+1,size_dword);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr),vertsize);
nv10FinishPrimitive(nmesa);
}
static INLINE void nv10_render_points(GLcontext *ctx,GLuint first,GLuint last)
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLfloat *vertptr = (GLfloat *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
GLuint i;
if (VB->Elts) {
for (i = first; i < last; i++)
if (VB->ClipMask[VB->Elts[i]] == 0)
nv10_render_point(ctx, vertptr + (VB->Elts[i]*vertsize));
}
else {
for (i = first; i < last; i++)
if (VB->ClipMask[i] == 0)
nv10_render_point(ctx, vertptr + (i*vertsize));
}
}
static INLINE void nv10_render_line(GLcontext *ctx,GLuint v1,GLuint v2)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLfloat *vertptr = (GLfloat *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
GLuint size_dword = vertsize*2;
nv10ExtendPrimitive(nmesa, size_dword);
nv10StartPrimitive(nmesa,GL_LINES+1,size_dword);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v1*vertsize)),vertsize);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v2*vertsize)),vertsize);
nv10FinishPrimitive(nmesa);
}
static INLINE void nv10_render_triangle(GLcontext *ctx,GLuint v1,GLuint v2,GLuint v3)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLfloat *vertptr = (GLfloat *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
GLuint size_dword = vertsize*3;
nv10ExtendPrimitive(nmesa, size_dword);
nv10StartPrimitive(nmesa,GL_TRIANGLES+1,size_dword);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v1*vertsize)),vertsize);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v2*vertsize)),vertsize);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v3*vertsize)),vertsize);
nv10FinishPrimitive(nmesa);
}
static INLINE void nv10_render_quad(GLcontext *ctx,GLuint v1,GLuint v2,GLuint v3,GLuint v4)
{
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
GLfloat *vertptr = (GLfloat *)nmesa->verts;
GLuint vertsize = nmesa->vertex_size;
GLuint size_dword = vertsize*4;
nv10ExtendPrimitive(nmesa, size_dword);
nv10StartPrimitive(nmesa,GL_QUADS+1,size_dword);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v1*vertsize)),vertsize);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v2*vertsize)),vertsize);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v3*vertsize)),vertsize);
OUT_RING_VERT(nmesa, (nouveauVertex*)(vertptr+(v4*vertsize)),vertsize);
nv10FinishPrimitive(nmesa);
}
static void nv10ChooseRenderState(GLcontext *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
tnl->Driver.Render.PrimTabVerts = nv10_render_tab_verts;
tnl->Driver.Render.PrimTabElts = nv10_render_tab_elts;
tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
tnl->Driver.Render.Points = nv10_render_points;
tnl->Driver.Render.Line = nv10_render_line;
tnl->Driver.Render.Triangle = nv10_render_triangle;
tnl->Driver.Render.Quad = nv10_render_quad;
}
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];
const int nv10_vtx_attribs[8]={
_TNL_ATTRIB_FOG, _TNL_ATTRIB_WEIGHT,
_TNL_ATTRIB_NORMAL, _TNL_ATTRIB_TEX1,
_TNL_ATTRIB_TEX0, _TNL_ATTRIB_COLOR1,
_TNL_ATTRIB_COLOR0, _TNL_ATTRIB_POS
};
int i;
int slots=0;
int total_size=0;
nmesa->vertex_attr_count = 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
*/
if ((nmesa->screen->card->type>=NV_10) && (nmesa->screen->card->type<=NV_17)) {
for(i=0;i<8;i++) {
int j = nv10_vtx_attribs[INV_VERT(i)];
if (RENDERINPUTS_TEST(index, j)) {
switch(attr_size[j])
{
case 1:
EMIT_ATTR(j,EMIT_1F);
break;
case 2:
EMIT_ATTR(j,EMIT_2F);
break;
case 3:
EMIT_ATTR(j,EMIT_3F);
break;
case 4:
EMIT_ATTR(j,EMIT_4F);
break;
}
total_size+=attr_size[j];
}
}
} else {
for(i=0;i<16;i++)
{
if (RENDERINPUTS_TEST(index, i))
{
slots=i+1;
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,
NULL, 0 );
/* OUT_RINGp wants size in DWORDS */
nmesa->vertex_size = nmesa->vertex_size / 4;
assert(nmesa->vertex_size==total_size);
/*
* Tell the hardware about the vertex format
*/
if ((nmesa->screen->card->type>=NV_10) && (nmesa->screen->card->type<=NV_17)) {
int total_stride = 0;
#define NV_VERTEX_ATTRIBUTE_TYPE_FLOAT 2
for(i=0;i<8;i++) {
int j = nv10_vtx_attribs[i];
int size;
int stride = attr_size[j] << 2;
if (j==_TNL_ATTRIB_POS) {
stride += total_stride;
}
size = attr_size[j] << 4;
size |= stride << 8;
size |= NV_VERTEX_ATTRIBUTE_TYPE_FLOAT;
BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VERTEX_ATTR((7-i)),1);
OUT_RING_CACHE(size);
total_stride += stride;
}
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,NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR8_TX0,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_30) {
nouveauShader *fp;
if (ctx->FragmentProgram.Enabled) {
fp = (nouveauShader *) ctx->FragmentProgram.Current;
nvsUpdateShader(ctx, fp);
} else
nvsUpdateShader(ctx, nmesa->passthrough_fp);
}
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);
/* 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->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;
}

View file

@ -1,40 +0,0 @@
/**************************************************************************
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__ */

View file

@ -1,121 +0,0 @@
/* 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 */

View file

@ -1,824 +0,0 @@
/**************************************************************************
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);
OUT_RING_CACHE(ubRef);
}
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 nv20Clear(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_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS, 1);
OUT_RING_CACHE(hw_bufs);
}
}
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:
/* No enable bit, nv20Scissor 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, 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_NO_UPDATE,
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 spotlight_update = SPOTLIGHT_NO_UPDATE;
/* 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:
spotlight_update = SPOTLIGHT_UPDATE_DIRECTION;
break;
case GL_SPOT_EXPONENT:
spotlight_update = SPOTLIGHT_UPDATE_EXPONENT;
break;
case GL_SPOT_CUTOFF:
spotlight_update = 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(spotlight_update) {
case SPOTLIGHT_UPDATE_DIRECTION:
{
GLfloat x,y,z;
GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
x = spot_light_coef_a * l->_NormDirection[0];
y = spot_light_coef_a * l->_NormDirection[1];
z = spot_light_coef_a * 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;
GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
cc = 1.0; /* FIXME: These need to be correctly computed */
lc = 0.0;
qc = 2.0;
x = spot_light_coef_a * l->_NormDirection[0];
y = spot_light_coef_a * l->_NormDirection[1];
z = spot_light_coef_a * l->_NormDirection[2];
c = spot_light_coef_a + 1.0;
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 */
static void nv20PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
OUT_RING_CACHEf(factor);
OUT_RING_CACHEf(units);
}
/** Set the polygon stippling pattern */
static void nv20PolygonStipple(GLcontext *ctx, const GLubyte *mask )
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV20_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 nv20Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
/* 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;
} else {
x += nmesa->drawX;
y += nmesa->drawY;
}
/*BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SCISSOR_X2_X1, 1);
OUT_RING_CACHE((w << 16) | x );
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SCISSOR_Y2_Y1, 1);
OUT_RING_CACHE((h << 16) | y );*/
}
/** 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);
static void nv20TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16);
/*XXX: This SHOULD work.*/
OUT_RING_CACHEp(mat->m, 16);
}
/* Update anything that depends on the window position/size */
static void nv20WindowMoved(nouveauContextPtr nmesa)
{
GLcontext *ctx = nmesa->glCtx;
GLfloat *v = nmesa->viewport.m;
GLuint w = ctx->Viewport.Width;
GLuint h = ctx->Viewport.Height;
GLuint x = ctx->Viewport.X + nmesa->drawX;
GLuint y = ctx->Viewport.Y + nmesa->drawY;
int i;
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
OUT_RING_CACHE((w << 16) | x);
OUT_RING_CACHE((h << 16) | y);
BEGIN_RING_SIZE(NvSub3D, 0x02b4, 1);
OUT_RING(0);
BEGIN_RING_CACHE(NvSub3D,
NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 1);
OUT_RING_CACHE((4095 << 16) | 0);
BEGIN_RING_CACHE(NvSub3D,
NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(0), 1);
OUT_RING_CACHE((4095 << 16) | 0);
for (i=1; i<8; i++) {
BEGIN_RING_CACHE(NvSub3D,
NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 1);
OUT_RING_CACHE(0);
BEGIN_RING_CACHE(NvSub3D,
NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(i), 1);
OUT_RING_CACHE(0);
}
ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height);
/* TODO: recalc viewport scale coefs */
}
/* Initialise any card-specific non-GL related state */
static GLboolean nv20InitCard(nouveauContextPtr nmesa)
{
nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SET_OBJECT1, 2);
OUT_RING(NvDmaFB); /* 184 dma_object1 */
OUT_RING(NvDmaFB); /* 188 dma_object2 */
BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SET_OBJECT3, 2);
OUT_RING(NvDmaFB); /* 194 dma_object3 */
OUT_RING(NvDmaFB); /* 198 dma_object4 */
BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
OUT_RING(NvDmaFB); /* 1a8 dma_object8 */
BEGIN_RING_SIZE(NvSub3D, 0x17e0, 3);
OUT_RINGf(0.0);
OUT_RINGf(0.0);
OUT_RINGf(1.0);
BEGIN_RING_SIZE(NvSub3D, 0x1e6c, 1);
OUT_RING(0x0db6);
BEGIN_RING_SIZE(NvSub3D, 0x0290, 1);
OUT_RING(0x00100001);
BEGIN_RING_SIZE(NvSub3D, 0x09fc, 1);
OUT_RING(0);
BEGIN_RING_SIZE(NvSub3D, 0x1d80, 1);
OUT_RING(1);
BEGIN_RING_SIZE(NvSub3D, 0x09f8, 1);
OUT_RING(4);
BEGIN_RING_SIZE(NvSub3D, 0x17ec, 3);
OUT_RINGf(0.0);
OUT_RINGf(1.0);
OUT_RINGf(0.0);
BEGIN_RING_SIZE(NvSub3D, 0x1d88, 1);
OUT_RING(3);
/* FIXME: More dma objects to setup ? */
BEGIN_RING_SIZE(NvSub3D, 0x1e98, 1);
OUT_RING(0);
BEGIN_RING_SIZE(NvSub3D, 0x120, 3);
OUT_RING(0);
OUT_RING(1);
OUT_RING(2);
return GL_TRUE;
}
/* Update buffer offset/pitch/format */
static GLboolean nv20BindBuffers(nouveauContextPtr nmesa, int num_color,
nouveau_renderbuffer_t **color,
nouveau_renderbuffer_t *depth)
{
GLuint x, y, w, h;
GLuint pitch, format, depth_pitch;
w = color[0]->mesa.Width;
h = color[0]->mesa.Height;
x = nmesa->drawX;
y = nmesa->drawY;
if (num_color != 1)
return GL_FALSE;
BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 6);
OUT_RING_CACHE((w << 16) | x);
OUT_RING_CACHE((h << 16) | y);
depth_pitch = (depth ? depth->pitch : color[0]->pitch);
pitch = (depth_pitch<<16) | color[0]->pitch;
format = 0x128;
if (color[0]->mesa._ActualFormat != GL_RGBA8) {
format = 0x123; /* R5G6B5 color buffer */
}
OUT_RING_CACHE(format);
OUT_RING_CACHE(pitch);
OUT_RING_CACHE(color[0]->offset);
OUT_RING_CACHE(depth ? depth->offset : color[0]->offset);
if (depth) {
BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH, 2);
/* TODO: use a different buffer */
OUT_RING(depth->pitch);
OUT_RING(depth->offset);
}
/* Always set to bottom left of buffer */
/*BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_X, 4);
OUT_RING_CACHEf (0.0);
OUT_RING_CACHEf ((GLfloat) h);
OUT_RING_CACHEf (0.0);
OUT_RING_CACHEf (0.0);*/
return GL_TRUE;
}
void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
func->AlphaFunc = nv20AlphaFunc;
func->BlendColor = nv20BlendColor;
func->BlendEquationSeparate = nv20BlendEquationSeparate;
func->BlendFuncSeparate = nv20BlendFuncSeparate;
func->Clear = nv20Clear;
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;
func->PolygonOffset = nv20PolygonOffset;
func->PolygonStipple = nv20PolygonStipple;
/* func->ReadBuffer = nv20ReadBuffer;*/
/* func->RenderMode = nv20RenderMode;*/
func->Scissor = nv20Scissor;
func->ShadeModel = nv20ShadeModel;
func->StencilFuncSeparate = nv20StencilFuncSeparate;
func->StencilMaskSeparate = nv20StencilMaskSeparate;
func->StencilOpSeparate = nv20StencilOpSeparate;
/* func->TexGen = nv20TexGen;*/
/* func->TexParameter = nv20TexParameter;*/
func->TextureMatrix = nv20TextureMatrix;
nmesa->hw_func.InitCard = nv20InitCard;
nmesa->hw_func.BindBuffers = nv20BindBuffers;
nmesa->hw_func.WindowMoved = nv20WindowMoved;
}

View file

@ -1,447 +0,0 @@
#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;
}

View file

@ -1,742 +0,0 @@
#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_bufferobj.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);
nvsCardPriv *priv = &nvs->card_priv;
uint32_t offset;
if (!nvs->program_buffer)
nvs->program_buffer = ctx->Driver.NewBufferObject(ctx, 0,
GL_ARRAY_BUFFER_ARB);
/* Should use STATIC_DRAW_ARB if shader doesn't use changable params */
nouveau_bo_init_storage(ctx, NOUVEAU_BO_VRAM_OK,
nvs->program_size * sizeof(uint32_t),
(const GLvoid *)nvs->program,
GL_DYNAMIC_DRAW_ARB,
nvs->program_buffer, 1);
offset = nouveau_bo_gpu_ref(ctx, nvs->program_buffer);
/* Not using state cache here, updated programs at the same address don't
* seem to take effect unless the ACTIVE_PROGRAM method is called again.
* HW caches the program somewhere?
*/
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1);
OUT_RING (offset | 1);
if (nmesa->screen->card->type == NV_30) {
BEGIN_RING_SIZE(NvSub3D,
0x1d60 /*NV30_TCL_PRIMITIVE_3D_FP_CONTROL*/, 1);
OUT_RING ((priv->NV30FP.uses_kil << 7));
BEGIN_RING_SIZE(NvSub3D, 0x1450, 1);
OUT_RING (priv->NV30FP.num_regs << 16);
} else {
BEGIN_RING_SIZE(NvSub3D,
0x1d60 /*NV30_TCL_PRIMITIVE_3D_FP_CONTROL*/, 1);
OUT_RING ((priv->NV30FP.uses_kil << 7) |
(priv->NV30FP.num_regs << 24));
}
}
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)
{
if (opcode == NV30_FP_OP_OPCODE_KIL)
shader->card_priv->NV30FP.uses_kil = GL_TRUE;
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
NV30FPSetHighReg(nvsFunc *shader, int id)
{
if (shader->card_priv->NV30FP.num_regs < (id+1)) {
if (id == 0)
id = 1; /* necessary? */
shader->card_priv->NV30FP.num_regs = (id+1);
}
}
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;
}
NV30FPSetHighReg(shader, hwreg);
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);
NV30FPSetHighReg(shader, reg->index);
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;
}

View file

@ -1,379 +0,0 @@
#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

File diff suppressed because it is too large Load diff

View file

@ -1,367 +0,0 @@
#include "nouveau_context.h"
#include "nouveau_object.h"
#include "nouveau_fifo.h"
#include "nouveau_reg.h"
#include "nouveau_shader.h"
#include "nv30_shader.h"
/*****************************************************************************
* 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);
BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_IN_REG, 2);
OUT_RING(nvs->card_priv.NV30VP.vp_in_reg);
OUT_RING(nvs->card_priv.NV30VP.vp_out_reg);
BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_CLIPPING_PLANES, 1);
OUT_RING_CACHE (nvs->card_priv.NV30VP.clip_enables);
}
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
*/
static void
NV30VPSetBranchTarget(nvsFunc *shader, int addr)
{
shader->inst[2] &= ~NV30_VP_INST_IADDR_MASK;
shader->inst[2] |= (addr << NV30_VP_INST_IADDR_SHIFT);
}
/*****************************************************************************
* 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;
shader->SetBranchTarget = NV30VPSetBranchTarget;
}

View file

@ -1,224 +0,0 @@
#include "nouveau_shader.h"
#include "nv40_shader.h"
/* branching ops */
unsigned int NVFP_TX_BOP_COUNT = 5;
struct _op_xlat NVFP_TX_BOP[64];
/*****************************************************************************
* Assembly routines
* - These extend the NV30 routines, which are almost identical. NV40
* just has branching hacked into the instruction set.
*/
static int
NV40FPSupportsResultScale(nvsFunc *shader, nvsScale scale)
{
switch (scale) {
case NVS_SCALE_1X:
case NVS_SCALE_2X:
case NVS_SCALE_4X:
case NVS_SCALE_8X:
case NVS_SCALE_INV_2X:
case NVS_SCALE_INV_4X:
case NVS_SCALE_INV_8X:
return 1;
default:
return 0;
}
}
static void
NV40FPSetResultScale(nvsFunc *shader, nvsScale scale)
{
shader->inst[2] &= ~NV40_FP_OP_DST_SCALE_MASK;
shader->inst[2] |= ((unsigned int)scale << NV40_FP_OP_DST_SCALE_SHIFT);
}
static void
NV40FPSetBranchTarget(nvsFunc *shader, int addr)
{
shader->inst[2] &= ~NV40_FP_OP_IADDR_MASK;
shader->inst[2] |= (addr << NV40_FP_OP_IADDR_SHIFT);
}
static void
NV40FPSetBranchElse(nvsFunc *shader, int addr)
{
shader->inst[2] &= ~NV40_FP_OP_ELSE_ID_MASK;
shader->inst[2] |= (addr << NV40_FP_OP_ELSE_ID_SHIFT);
}
static void
NV40FPSetBranchEnd(nvsFunc *shader, int addr)
{
shader->inst[3] &= ~NV40_FP_OP_END_ID_MASK;
shader->inst[3] |= (addr << NV40_FP_OP_END_ID_SHIFT);
}
static void
NV40FPSetLoopParams(nvsFunc *shader, int count, int initial, int increment)
{
shader->inst[2] &= ~(NV40_FP_OP_LOOP_COUNT_MASK |
NV40_FP_OP_LOOP_INDEX_MASK |
NV40_FP_OP_LOOP_INCR_MASK);
shader->inst[2] |= ((count << NV40_FP_OP_LOOP_COUNT_SHIFT) |
(initial << NV40_FP_OP_LOOP_INDEX_SHIFT) |
(increment << NV40_FP_OP_LOOP_INCR_SHIFT));
}
/*****************************************************************************
* Disassembly routines
*/
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);
shader->SupportsResultScale = NV40FPSupportsResultScale;
shader->SetResultScale = NV40FPSetResultScale;
/* 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;
shader->SetBranchTarget = NV40FPSetBranchTarget;
shader->SetBranchElse = NV40FPSetBranchElse;
shader->SetBranchEnd = NV40FPSetBranchEnd;
shader->SetLoopParams = NV40FPSetLoopParams;
}

View file

@ -1,467 +0,0 @@
#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_DST_SCALE_SHIFT 28
#define NV40_FP_OP_DST_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

View file

@ -1,778 +0,0 @@
#include "nouveau_shader.h"
#include "nouveau_msg.h"
#include "nv40_shader.h"
/*****************************************************************************
* 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);
}
/* these just exist here until nouveau_reg.h has them. */
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_COL0 (1<<0)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_COL1 (1<<1)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_BFC0 (1<<2)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_BFC1 (1<<3)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_FOGC (1<<4)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_PSZ (1<<5)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP0 (1<<6)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP1 (1<<7)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP2 (1<<8)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP3 (1<<9)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP4 (1<<10)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP5 (1<<11)
#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_TEX0 (1<<14)
static unsigned int
NV40VPTranslateResultReg(nvsFunc *shader, nvsFixedReg result,
unsigned int *mask_ret)
{
unsigned int *out_reg = &shader->card_priv->NV30VP.vp_out_reg;
unsigned int *clip_en = &shader->card_priv->NV30VP.clip_enables;
*mask_ret = 0xf;
switch (result) {
case NVS_FR_POSITION:
/* out_reg POS implied */
return NV40_VP_INST_DEST_POS;
case NVS_FR_COL0:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_COL0;
return NV40_VP_INST_DEST_COL0;
case NVS_FR_COL1:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_COL1;
return NV40_VP_INST_DEST_COL1;
case NVS_FR_BFC0:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_BFC0;
return NV40_VP_INST_DEST_BFC0;
case NVS_FR_BFC1:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_BFC1;
return NV40_VP_INST_DEST_BFC1;
case NVS_FR_FOGCOORD:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_FOGC;
*mask_ret = 0x8;
return NV40_VP_INST_DEST_FOGC;
case NVS_FR_CLIP0:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP0;
(*clip_en) |= 0x00000002;
*mask_ret = 0x4;
return NV40_VP_INST_DEST_FOGC;
case NVS_FR_CLIP1:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP1;
(*clip_en) |= 0x00000020;
*mask_ret = 0x2;
return NV40_VP_INST_DEST_FOGC;
case NVS_FR_CLIP2:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP2;
(*clip_en) |= 0x00000200;
*mask_ret = 0x1;
return NV40_VP_INST_DEST_FOGC;
case NVS_FR_POINTSZ:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_PSZ;
*mask_ret = 0x8;
return NV40_VP_INST_DEST_PSZ;
case NVS_FR_CLIP3:
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP3;
(*clip_en) |= 0x00002000;
*mask_ret = 0x4;
return NV40_VP_INST_DEST_PSZ;
case NVS_FR_CLIP4:
(*clip_en) |= 0x00020000;
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP4;
*mask_ret = 0x2;
return NV40_VP_INST_DEST_PSZ;
case NVS_FR_CLIP5:
(*clip_en) |= 0x00200000;
(*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP5;
*mask_ret = 0x1;
return NV40_VP_INST_DEST_PSZ;
case NVS_FR_TEXCOORD0:
case NVS_FR_TEXCOORD1:
case NVS_FR_TEXCOORD2:
case NVS_FR_TEXCOORD3:
case NVS_FR_TEXCOORD4:
case NVS_FR_TEXCOORD5:
case NVS_FR_TEXCOORD6:
case NVS_FR_TEXCOORD7:
{
int unit = result - NVS_FR_TEXCOORD0;
(*out_reg) |= (NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_TEX0 << unit);
return NV40_VP_INST_DEST_TC(unit);
}
default:
WARN_ONCE("unknown vp output %d\n", result);
return NV40_VP_INST_DEST_POS;
}
}
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) {
unsigned int valid_mask;
int hwidx;
hwidx = NV40VPTranslateResultReg(shader, dest->index, &valid_mask);
if (hwmask & ~valid_mask)
WARN_ONCE("writing invalid components of result reg\n");
hwmask &= valid_mask;
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);
shader->card_priv->NV30VP.vp_in_reg |= (1 << src->index);
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
NV40VPSetBranchTarget(nvsFunc *shader, int addr)
{
shader->inst[2] &= ~NV40_VP_INST_IADDRH_MASK;
shader->inst[2] |= ((addr & 0xf8) >> 3) << NV40_VP_INST_IADDRH_SHIFT;
shader->inst[3] &= ~NV40_VP_INST_IADDRL_MASK;
shader->inst[3] |= ((addr & 0x07) << NV40_VP_INST_IADDRL_SHIFT);
}
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->SetBranchTarget = NV40VPSetBranchTarget;
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;
}

View file

@ -1,641 +0,0 @@
/**************************************************************************
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"
static void nv50AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
GLubyte ubRef;
CLAMPED_FLOAT_TO_UBYTE(ubRef, ref);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF, 2);
OUT_RING_CACHE(ubRef);
OUT_RING_CACHE(func);
}
static void nv50BlendColor(GLcontext *ctx, const GLfloat color[4])
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_R, 4);
OUT_RING_CACHEf(color[0]);
OUT_RING_CACHEf(color[1]);
OUT_RING_CACHEf(color[2]);
OUT_RING_CACHEf(color[3]);
}
static void nv50BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_EQUATION_RGB, 1);
OUT_RING_CACHE(modeRGB);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_EQUATION_ALPHA, 1);
OUT_RING_CACHE(modeA);
}
static void nv50BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
GLenum sfactorA, GLenum dfactorA)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC_RGB, 2);
OUT_RING_CACHE(sfactorRGB); /* FIXME, sometimes has |0x4000 */
OUT_RING_CACHE(dfactorRGB); /* FIXME, sometimes has |0x4000 */
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC_ALPHA, 2);
OUT_RING_CACHE(sfactorA); /* FIXME, sometimes has |0x4000 */
OUT_RING_CACHE(dfactorA); /* FIXME, sometimes has |0x4000 */
}
static void nv50Clear(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 |= 0x3c;
if (mask & (BUFFER_BIT_STENCIL))
hw_bufs |= 0x02;
if (mask & (BUFFER_BIT_DEPTH))
hw_bufs |= 0x01;
if (hw_bufs) {
BEGIN_RING_SIZE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CLEAR_BUFFERS, 1);
OUT_RING(hw_bufs);
}
}
static void nv50ClearColor(GLcontext *ctx, const GLfloat color[4])
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_R, 4);
OUT_RING_CACHEf(color[0]);
OUT_RING_CACHEf(color[1]);
OUT_RING_CACHEf(color[2]);
OUT_RING_CACHEf(color[3]);
}
static void nv50ClearDepth(GLcontext *ctx, GLclampd d)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CLEAR_DEPTH, 1);
OUT_RING_CACHEf(d);
}
/* we're don't support indexed buffers
void (*ClearIndex)(GLcontext *ctx, GLuint index)
*/
static void nv50ClearStencil(GLcontext *ctx, GLint s)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CLEAR_STENCIL, 1);
OUT_RING_CACHE(s);
}
static void nv50ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
{
/* Only using shaders */
}
static void nv50ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
GLboolean bmask, GLboolean amask )
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
int i;
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_COLOR_MASK(0), 8);
for (i=0; i<8; i++) {
OUT_RING_CACHE(((amask && 0x01) << 12) | ((bmask && 0x01) << 8) | ((gmask && 0x01)<< 4) | ((rmask && 0x01) << 0));
}
}
static void nv50ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
{
// TODO I need love
}
static void nv50CullFace(GLcontext *ctx, GLenum mode)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CULL_FACE, 1);
OUT_RING_CACHE(mode);
}
static void nv50FrontFace(GLcontext *ctx, GLenum mode)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_FRONT_FACE, 1);
OUT_RING_CACHE(mode);
}
static void nv50DepthFunc(GLcontext *ctx, GLenum func)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
OUT_RING_CACHE(func);
}
static void nv50DepthMask(GLcontext *ctx, GLboolean flag)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
OUT_RING_CACHE(flag);
}
static void nv50DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_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 nv50Enable(GLcontext *ctx, GLenum cap, GLboolean state)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
switch(cap)
{
case GL_ALPHA_TEST:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
OUT_RING_CACHE(state);
break;
// case GL_AUTO_NORMAL:
// case GL_BLEND:
// case GL_CLIP_PLANE0:
// case GL_CLIP_PLANE1:
// case GL_CLIP_PLANE2:
// case GL_CLIP_PLANE3:
// case GL_CLIP_PLANE4:
// case GL_CLIP_PLANE5:
case GL_COLOR_LOGIC_OP:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_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, NV50_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
OUT_RING_CACHE(state);
break;
case GL_DEPTH_TEST:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
OUT_RING_CACHE(state);
break;
// case GL_DITHER:
// case GL_FOG:
// 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:
// case GL_LIGHTING:
case GL_LINE_SMOOTH:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
OUT_RING_CACHE(state);
break;
case GL_LINE_STIPPLE:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LINE_STIPPLE_ENABLE, 1);
OUT_RING_CACHE(state);
break;
// 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:
// case GL_POINT_SMOOTH:
case GL_POLYGON_OFFSET_POINT:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1);
OUT_RING_CACHE(state);
break;
case GL_POLYGON_OFFSET_LINE:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1);
OUT_RING_CACHE(state);
break;
case GL_POLYGON_OFFSET_FILL:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1);
OUT_RING_CACHE(state);
break;
case GL_POLYGON_SMOOTH:
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
OUT_RING_CACHE(state);
break;
case GL_POLYGON_STIPPLE:
BEGIN_RING_CACHE(NvSub3D, NV50_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, nv50Scissor 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, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
OUT_RING_CACHE(state);
BEGIN_RING_CACHE(NvSub3D, NV50_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 nv50Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
{
/* Only using shaders */
}
static void nv50Hint(GLcontext *ctx, GLenum target, GLenum mode)
{
// TODO I need love (fog and line_smooth hints)
}
// void (*IndexMask)(GLcontext *ctx, GLuint mask);
static void nv50Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
{
/* Only with shaders */
}
/** Set the lighting model parameters */
void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
static void nv50LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1);
OUT_RING_CACHE((pattern << 8) | factor);
}
static void nv50LineWidth(GLcontext *ctx, GLfloat width)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LINE_WIDTH, 1);
OUT_RING_CACHEf(width);
}
static void nv50LogicOpcode(GLcontext *ctx, GLenum opcode)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LOGIC_OP_OP, 1);
OUT_RING_CACHE(opcode);
}
static void nv50PointParameterfv(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 nv50PointSize(GLcontext *ctx, GLfloat size)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
OUT_RING_CACHEf(size);
}
/** Select a polygon rasterization mode */
static void nv50PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1);
OUT_RING_CACHE(mode);
}
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1);
OUT_RING_CACHE(mode);
}
}
/** Set the scale and units used to calculate depth values */
static void nv50PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 1);
OUT_RING_CACHEf(factor);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS, 1);
OUT_RING_CACHEf(units);
}
/** Set the polygon stippling pattern */
static void nv50PolygonStipple(GLcontext *ctx, const GLubyte *mask )
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_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 nv50Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
/* 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 = 8191;
} else {
x += nmesa->drawX;
y += nmesa->drawY;
}
BEGIN_RING_CACHE(NvSub3D, NV50_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 nv50ShadeModel(GLcontext *ctx, GLenum mode)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
OUT_RING_CACHE(mode);
}
/** OpenGL 2.0 two-sided StencilFunc */
static void nv50StencilFuncSeparate(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, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC, 1);
OUT_RING_CACHE(func);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_REF, 1);
OUT_RING_CACHE(ref);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_MASK, 1);
OUT_RING_CACHE(mask);
}
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC, 2);
OUT_RING_CACHE(func);
OUT_RING_CACHE(ref);
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_MASK, 1);
OUT_RING_CACHE(mask);
}
}
/** OpenGL 2.0 two-sided StencilMask */
static void nv50StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK, 1);
OUT_RING_CACHE(mask);
}
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK, 1);
OUT_RING_CACHE(mask);
}
}
/** OpenGL 2.0 two-sided StencilOp */
static void nv50StencilOpSeparate(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, NV50_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, NV50_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 nv50TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
{
/* Only with shaders */
}
static void nv50WindowMoved(nouveauContextPtr nmesa)
{
GLcontext *ctx = nmesa->glCtx;
GLfloat *v = nmesa->viewport.m;
GLuint w = ctx->Viewport.Width;
GLuint h = ctx->Viewport.Height;
GLuint x = ctx->Viewport.X + nmesa->drawX;
GLuint y = ctx->Viewport.Y + nmesa->drawY;
int i;
BEGIN_RING_CACHE(NvSub3D,
NV50_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 2);
OUT_RING_CACHE((8191 << 16) | 0);
OUT_RING_CACHE((8191 << 16) | 0);
for (i=1; i<8; i++) {
BEGIN_RING_CACHE(NvSub3D,
NV50_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 2);
OUT_RING_CACHE(0);
OUT_RING_CACHE(0);
}
ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height);
}
static GLboolean nv50InitCard(nouveauContextPtr nmesa)
{
int i,j;
nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
BEGIN_RING_SIZE(NvSub3D, 0x1558, 1);
OUT_RING(1);
BEGIN_RING_SIZE(NvSub3D, NV50_TCL_PRIMITIVE_3D_SET_OBJECT_1(0), 8);
for (i=0; i<8; i++) {
OUT_RING(NvDmaFB);
}
BEGIN_RING_SIZE(NvSub3D, NV50_TCL_PRIMITIVE_3D_SET_OBJECT_0(0), 12);
for (i=0; i<12; i++) {
OUT_RING(NvDmaFB);
}
BEGIN_RING_SIZE(NvSub3D, 0x121c, 1);
OUT_RING(1);
for (i=0; i<8; i++) {
BEGIN_RING_SIZE(NvSub3D, 0x0200 + (i*0x20), 5);
for (j=0; j<5; j++) {
OUT_RING(0);
}
}
BEGIN_RING_SIZE(NvSub3D, 0x0fe0, 5);
OUT_RING(0);
OUT_RING(0);
OUT_RING(0x16);
OUT_RING(0);
OUT_RING(0);
return GL_FALSE;
}
static GLboolean
nv50BindBuffers(nouveauContextPtr nmesa, int num_color,
nouveau_renderbuffer_t **color, nouveau_renderbuffer_t *depth)
{
return GL_FALSE;
}
void nv50InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
{
nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
func->AlphaFunc = nv50AlphaFunc;
func->BlendColor = nv50BlendColor;
func->BlendEquationSeparate = nv50BlendEquationSeparate;
func->BlendFuncSeparate = nv50BlendFuncSeparate;
func->Clear = nv50Clear;
func->ClearColor = nv50ClearColor;
func->ClearDepth = nv50ClearDepth;
func->ClearStencil = nv50ClearStencil;
func->ClipPlane = nv50ClipPlane;
func->ColorMask = nv50ColorMask;
func->ColorMaterial = nv50ColorMaterial;
func->CullFace = nv50CullFace;
func->FrontFace = nv50FrontFace;
func->DepthFunc = nv50DepthFunc;
func->DepthMask = nv50DepthMask;
func->DepthRange = nv50DepthRange;
func->Enable = nv50Enable;
func->Fogfv = nv50Fogfv;
func->Hint = nv50Hint;
func->Lightfv = nv50Lightfv;
/* func->LightModelfv = nv50LightModelfv; */
func->LineStipple = nv50LineStipple;
func->LineWidth = nv50LineWidth;
func->LogicOpcode = nv50LogicOpcode;
func->PointParameterfv = nv50PointParameterfv;
func->PointSize = nv50PointSize;
func->PolygonMode = nv50PolygonMode;
func->PolygonOffset = nv50PolygonOffset;
func->PolygonStipple = nv50PolygonStipple;
/* func->ReadBuffer = nv50ReadBuffer; */
/* func->RenderMode = nv50RenderMode; */
func->Scissor = nv50Scissor;
func->ShadeModel = nv50ShadeModel;
func->StencilFuncSeparate = nv50StencilFuncSeparate;
func->StencilMaskSeparate = nv50StencilMaskSeparate;
func->StencilOpSeparate = nv50StencilOpSeparate;
/* func->TexGen = nv50TexGen; */
/* func->TexParameter = nv50TexParameter; */
func->TextureMatrix = nv50TextureMatrix;
nmesa->hw_func.InitCard = nv50InitCard;
nmesa->hw_func.BindBuffers = nv50BindBuffers;
nmesa->hw_func.WindowMoved = nv50WindowMoved;
}