nvfx: completely remove this driver (GeForce FX/6/7)

This driver hasn't been maintained properly for a very long time, and for
many very good reasons.  It's horrible.

A new driver supporting these chipsets will appear with the commits that
port vieux/nv50/nvc0 to libdrm_nouveau-2.0.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2012-02-16 22:08:41 +10:00
parent f3d8bd3f7b
commit 66c7dc5688
47 changed files with 6 additions and 14901 deletions

View File

@ -1917,7 +1917,7 @@ if test "x$with_gallium_drivers" != x; then
;;
xnouveau)
PKG_CHECK_MODULES([NOUVEAU], [libdrm_nouveau >= $LIBDRM_NOUVEAU_REQUIRED])
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50 nvc0"
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nv50 nvc0"
gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" "" "xvmc-nouveau" "vdpau-nouveau"
;;
xswrast)

View File

@ -27,8 +27,6 @@
#include "nouveau_context.h"
#include "nouveau_video.h"
#include "nvfx/nvfx_context.h"
#include "nvfx/nvfx_resource.h"
#include "nouveau/nouveau_bo.h"
#include "nouveau/nouveau_buffer.h"
#include "util/u_video.h"
@ -37,15 +35,6 @@
#include "nouveau/nouveau_device.h"
#include "nouveau_winsys.h"
static bool
nouveau_video_is_nvfx(struct nouveau_decoder *dec) {
if (dec->screen->device->chipset < 0x50)
return true;
if (dec->screen->device->chipset >= 0x60 && dec->screen->device->chipset < 0x70)
return true;
return false;
}
static int
nouveau_vpe_init(struct nouveau_decoder *dec) {
int ret;
@ -396,7 +385,8 @@ nouveau_decoder_surface_index(struct nouveau_decoder *dec,
{
struct nouveau_video_buffer *buf = (struct nouveau_video_buffer *)buffer;
struct nouveau_channel *chan = dec->screen->channel;
struct nouveau_bo *bo_y, *bo_c;
struct nouveau_bo *bo_y = ((struct nv04_resource *)buf->resources[0])->bo;
struct nouveau_bo *bo_c = ((struct nv04_resource *)buf->resources[1])->bo;
unsigned i;
if (!buf)
@ -409,13 +399,6 @@ nouveau_decoder_surface_index(struct nouveau_decoder *dec,
dec->surfaces[i] = buf;
dec->num_surfaces++;
if (nouveau_video_is_nvfx(dec)) {
bo_y = ((struct nvfx_resource *)buf->resources[0])->bo;
bo_c = ((struct nvfx_resource *)buf->resources[1])->bo;
} else {
bo_y = ((struct nv04_resource *)buf->resources[0])->bo;
bo_c = ((struct nv04_resource *)buf->resources[1])->bo;
}
MARK_RING(chan, 3, 2);
BEGIN_RING(chan, dec->mpeg, NV31_MPEG_IMAGE_Y_OFFSET(i), 2);
OUT_RELOCl(chan, bo_y, 0, NOUVEAU_BO_RDWR);
@ -856,35 +839,6 @@ nouveau_screen_init_vdec(struct nouveau_screen *screen)
screen->base.is_video_format_supported = vl_video_buffer_is_format_supported;
}
static struct pipe_video_decoder *
nvfx_context_create_decoder(struct pipe_context *context,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height,
unsigned max_references, bool expect_chunked_decode)
{
struct nouveau_screen *screen = &nvfx_context(context)->screen->base;
return nouveau_create_decoder(context, screen, profile, entrypoint,
chroma_format, width, height,
max_references, expect_chunked_decode);
}
static struct pipe_video_buffer *
nvfx_context_video_buffer_create(struct pipe_context *pipe,
const struct pipe_video_buffer *templat)
{
struct nouveau_screen *screen = &nvfx_context(pipe)->screen->base;
return nouveau_video_buffer_create(pipe, screen, templat);
}
void
nvfx_context_init_vdec(struct nvfx_context *nv)
{
nv->pipe.create_video_decoder = nvfx_context_create_decoder;
nv->pipe.create_video_buffer = nvfx_context_video_buffer_create;
}
static struct pipe_video_decoder *
nouveau_context_create_decoder(struct pipe_context *context,
enum pipe_video_profile profile,

View File

@ -41,9 +41,6 @@ nouveau_screen_transfer_flags(unsigned pipe)
return flags;
}
extern struct pipe_screen *
nvfx_screen_create(struct nouveau_device *);
extern struct pipe_screen *
nv50_screen_create(struct nouveau_device *);

View File

@ -1,37 +0,0 @@
# Mesa 3-D graphics library
#
# Copyright (C) 2011 Chia-I Wu <olvaffe@gmail.com>
# Copyright (C) 2011 LunarG Inc.
#
# 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 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 AUTHORS OR COPYRIGHT HOLDERS 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.
LOCAL_PATH := $(call my-dir)
# get C_SOURCES
include $(LOCAL_PATH)/Makefile.sources
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(C_SOURCES)
LOCAL_C_INCLUDES := $(DRM_TOP)
LOCAL_MODULE := libmesa_pipe_nvfx
include $(GALLIUM_COMMON_MK)
include $(BUILD_STATIC_LIBRARY)

View File

@ -1,16 +0,0 @@
TOP = ../../../..
include $(TOP)/configs/current
LIBNAME = nvfx
# get C_SOURCES
include Makefile.sources
LIBRARY_INCLUDES = \
$(LIBDRM_CFLAGS) \
-I$(TOP)/src/gallium/drivers/nouveau/include
include ../../Makefile.template
# FIXME: Remove when this driver is converted to automake.
all: default

View File

@ -1,22 +0,0 @@
C_SOURCES := \
nv04_2d.c \
nvfx_buffer.c \
nvfx_context.c \
nvfx_clear.c \
nvfx_draw.c \
nvfx_fragprog.c \
nvfx_fragtex.c \
nv30_fragtex.c \
nv40_fragtex.c \
nvfx_miptree.c \
nvfx_push.c \
nvfx_query.c \
nvfx_resource.c \
nvfx_screen.c \
nvfx_state.c \
nvfx_state_emit.c \
nvfx_state_fb.c \
nvfx_surface.c \
nvfx_transfer.c \
nvfx_vbo.c \
nvfx_vertprog.c

View File

@ -1,14 +0,0 @@
Import('*')
env = env.Clone()
env.PrependUnique(delete_existing=1, CPPPATH = [
'#/src/gallium/drivers',
])
nvfx = env.ConvenienceLibrary(
target = 'nvfx',
source = env.ParseSourceList('Makefile.sources', 'C_SOURCES')
)
Export('nvfx')

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
/**************************************************************************
*
* Copyright 2009 Ben Skeggs
* Copyright 2009 Younes Manton
* Copyright 2010 Luca Barbieri
* 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 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 THE COPYRIGHT HOLDERS, AUTHORS
* 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
/* this code has no Mesa or Gallium dependency and can be reused in the classic Mesa driver or DDX */
#ifndef __NV04_2D_H__
#define __NV04_2D_H__
struct nv04_2d_context;
struct nouveau_channel;
struct nouveau_bo;
// NOTE: all functions taking this as a parameter will CLOBBER it (except for ->bo)
struct nv04_region {
struct nouveau_bo* bo;
int offset;
unsigned pitch; // 0 -> swizzled
unsigned bpps; // bpp shift (0, 1, 2; 3, 4 for fp/compressed)
unsigned one_bits; // number of high bits read and written as ones (for "no-alpha" optimization)
unsigned x, y, z;
unsigned w, h, d;
};
static inline void
nv04_region_try_to_linearize(struct nv04_region* rgn)
{
assert(!rgn->pitch);
if(rgn->d <= 1)
{
if(rgn->h <= 1 || rgn->w <= 2)
rgn->pitch = rgn->w << rgn->bpps;
}
else
{
if(rgn->h <= 2 && rgn->w <= 2)
{
rgn->pitch = rgn->w << rgn->bpps;
rgn->offset += rgn->z * rgn->h * rgn->pitch;
}
}
}
void
nv04_memcpy(struct nv04_2d_context *ctx,
struct nouveau_bo* dstbo, int dstoff,
struct nouveau_bo* srcbo, int srcoff,
unsigned size);
unsigned
nv04_region_begin(struct nv04_region* rgn, unsigned w, unsigned h);
unsigned
nv04_region_end(struct nv04_region* rgn, unsigned w, unsigned h);
void
nv04_2d_context_takedown(struct nv04_2d_context *pctx);
struct nv04_2d_context *
nv04_2d_context_init(struct nouveau_channel* chan);
void
nv04_region_copy_cpu(struct nv04_region* dst, struct nv04_region* src, int w, int h);
void
nv04_region_fill_cpu(struct nv04_region* dst, int w, int h, unsigned value);
int
nv04_region_copy_2d(struct nv04_2d_context *ctx,
struct nv04_region* dst, struct nv04_region* src,
int w, int h,
int dst_to_gpu, int src_on_gpu);
int
nv04_region_fill_2d(struct nv04_2d_context *ctx,
struct nv04_region *dst,
int w, int h,
unsigned value);
#endif

View File

@ -1,70 +0,0 @@
#ifndef T
{
if(dst->bpps == 0)
#define T uint8_t
#include "nv04_2d_loops.h"
#undef T
else if(dst->bpps == 1)
#define T uint16_t
#include "nv04_2d_loops.h"
#undef T
else if(dst->bpps == 2)
#define T uint32_t
#include "nv04_2d_loops.h"
#undef T
else
assert(0);
}
#else
#ifdef SWIZZLED_COPY_LOOPS
{
if(!dst->pitch)
{
if(!src->pitch)
{
LOOP_Y
{
T* pdst = (T*)mdst + dswy[iy];
T* psrc = (T*)msrc + sswy[iy];
LOOP_X
{
assert((char*)&psrc[sswx[ix] + 1] <= ((char*)src->bo->map + src->bo->size));
assert((char*)&pdst[dswx[ix] + 1] <= ((char*)dst->bo->map + dst->bo->size));
pdst[dswx[ix]] = psrc[sswx[ix]];
}
}
}
else
{
T* psrc = (T*)(msrc + ((dir > 0) ? src->y : (src->y + h - 1)) * src->pitch) + src->x;
LOOP_Y
{
T* pdst = (T*)mdst + dswy[iy];
LOOP_X
{
assert((char*)&psrc[ix + 1] <= ((char*)src->bo->map + src->bo->size));
assert((char*)&pdst[dswx[ix] + 1] <= ((char*)dst->bo->map + dst->bo->size));
pdst[dswx[ix]] = psrc[ix];
}
psrc = (T*)((char*)psrc + dir * src->pitch);
}
}
}
else
{
T* pdst = (T*)(mdst + ((dir > 0) ? dst->y : (dst->y + h - 1)) * dst->pitch) + dst->x;
LOOP_Y
{
T* psrc = (T*)msrc + sswy[iy];
LOOP_X
{
assert((char*)&psrc[sswx[ix] + 1] <= ((char*)src->bo->map + src->bo->size));
assert((char*)&pdst[ix + 1] <= ((char*)dst->bo->map + dst->bo->size));
pdst[ix] = psrc[sswx[ix]];
}
pdst = (T*)((char*)pdst + dir * dst->pitch);
}
}
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,117 +0,0 @@
#include "util/u_format.h"
#include "nvfx_context.h"
#include "nvfx_tex.h"
#include "nvfx_resource.h"
void
nv30_sampler_state_init(struct pipe_context *pipe,
struct nvfx_sampler_state *ps,
const struct pipe_sampler_state *cso)
{
if (cso->max_anisotropy >= 2)
{
if (cso->max_anisotropy >= 8)
ps->en |= NV30_3D_TEX_ENABLE_ANISO_8X;
else if (cso->max_anisotropy >= 4)
ps->en |= NV30_3D_TEX_ENABLE_ANISO_4X;
else if (cso->max_anisotropy >= 2)
ps->en |= NV30_3D_TEX_ENABLE_ANISO_2X;
}
ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
ps->max_lod = (int)CLAMP(cso->max_lod, 0.0, 15.0);
ps->min_lod = (int)CLAMP(cso->min_lod, 0.0, 15.0);
ps->en |= NV30_3D_TEX_ENABLE_ENABLE;
}
void
nv30_sampler_view_init(struct pipe_context *pipe,
struct nvfx_sampler_view *sv)
{
struct pipe_resource* pt = sv->base.texture;
struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format];
unsigned txf;
unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.u.tex.first_level;
assert(tf->fmt[0] >= 0);
txf = sv->u.init_fmt;
txf |= (level != sv->base.u.tex.last_level ? NV30_3D_TEX_FORMAT_MIPMAP : 0);
txf |= util_logbase2(u_minify(pt->width0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT;
txf |= util_logbase2(u_minify(pt->height0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT;
txf |= util_logbase2(u_minify(pt->depth0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_W__SHIFT;
txf |= 0x10000;
sv->u.nv30.fmt[0] = tf->fmt[0] | txf;
sv->u.nv30.fmt[1] = tf->fmt[1] | txf;
sv->u.nv30.fmt[2] = tf->fmt[2] | txf;
sv->u.nv30.fmt[3] = tf->fmt[3] | txf;
sv->swizzle |= (nvfx_subresource_pitch(pt, 0) << NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT);
if(pt->height0 <= 1 || util_format_is_compressed(sv->base.format))
sv->u.nv30.rect = -1;
else
sv->u.nv30.rect = !!(pt->flags & NOUVEAU_RESOURCE_FLAG_LINEAR);
sv->lod_offset = sv->base.u.tex.first_level - level;
sv->max_lod_limit = sv->base.u.tex.last_level - level;
}
void
nv30_fragtex_set(struct nvfx_context *nvfx, int unit)
{
struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
unsigned txf;
unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
unsigned use_rect;
unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod) ;
if(sv->u.nv30.rect < 0)
{
/* in the case of compressed or 1D textures, we can get away with this,
* since the layout is the same
*/
use_rect = ps->fmt;
}
else
{
static boolean warned = FALSE;
if( !!ps->fmt != sv->u.nv30.rect && !warned) {
warned = TRUE;
fprintf(stderr,
"Unimplemented: coordinate normalization mismatch. Possible reasons:\n"
"1. ARB_texture_non_power_of_two is being used despite the fact it isn't supported\n"
"2. The state tracker is not using the appropriate coordinate normalization\n"
"3. The state tracker is not supported\n");
}
use_rect = sv->u.nv30.rect;
}
txf = sv->u.nv30.fmt[ps->compare + (use_rect ? 2 : 0)];
MARK_RING(chan, 9, 2);
BEGIN_RING(chan, eng3d, NV30_3D_TEX_OFFSET(unit), 8);
OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
OUT_RELOC(chan, bo, txf,
tex_flags | NOUVEAU_BO_OR,
NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
OUT_RING(chan, ps->en | (min_lod << NV30_3D_TEX_ENABLE_MIPMAP_MIN_LOD__SHIFT) | (max_lod << NV30_3D_TEX_ENABLE_MIPMAP_MAX_LOD__SHIFT));
OUT_RING(chan, sv->swizzle);
OUT_RING(chan, ps->filt | sv->filt);
OUT_RING(chan, sv->npot_size);
OUT_RING(chan, ps->bcol);
nvfx->hw_txf[unit] = txf;
nvfx->hw_samplers |= (1 << unit);
}

View File

@ -1,176 +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 */
/* guess that this is the same as nv40 */
#define NV30_VP_INST_INDEX_INPUT (1 << 27)
#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_VEC_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_VEC_DEST_TEMP_MASK (0x1F << 16)
#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_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_VEC_OPCODE_SHIFT 23
#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23)
#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_SRC0H_SHIFT 0 /*NV20*/
#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/
/* Please note: the IADDR fields overlap other fields because they are used
* only for branch instructions. See Branching: label above
*
* DWORD 2
*/
#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/
#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /* NV30_VP_SRC0_LOW_MASK << 26 */
#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) /* NV30_VP_SRC2_HIGH_MASK >> 4*/
#define NV30_VP_INST_IADDR_SHIFT 2
#define NV30_VP_INST_IADDR_MASK (0x1FF << 2) /* NV30_VP_SRC2_LOW_MASK << 28 */
/* 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_SHIFT 2
#define NV30_VP_INST_DEST_MASK (0x1F << 2)
# define NV30_VP_INST_DEST_POS 0
# define NV30_VP_INST_DEST_BFC0 1
# define NV30_VP_INST_DEST_BFC1 2
# define NV30_VP_INST_DEST_COL0 3
# define NV30_VP_INST_DEST_COL1 4
# define NV30_VP_INST_DEST_FOGC 5
# define NV30_VP_INST_DEST_PSZ 6
# define NV30_VP_INST_DEST_TC(n) (8+(n))
# define NV30_VP_INST_DEST_CLP(n) (17 + (n))
/* guess that this is the same as nv40 */
#define NV30_VP_INST_INDEX_CONST (1 << 1)
/* Useful to split the source selection regs into their pieces */
#define NV30_VP_SRC0_HIGH_SHIFT 6
#define NV30_VP_SRC0_HIGH_MASK 0x00007FC0
#define NV30_VP_SRC0_LOW_MASK 0x0000003F
#define NV30_VP_SRC2_HIGH_SHIFT 4
#define NV30_VP_SRC2_HIGH_MASK 0x00007FF0
#define NV30_VP_SRC2_LOW_MASK 0x0000000F
/* Source-register definition - matches NV20 exactly */
#define NV30_VP_SRC_NEGATE (1<<14)
#define NV30_VP_SRC_SWZ_X_SHIFT 12
#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12)
#define NV30_VP_SRC_SWZ_Y_SHIFT 10
#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10)
#define NV30_VP_SRC_SWZ_Z_SHIFT 8
#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8)
#define NV30_VP_SRC_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_TEMP_SRC_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 */
#include "nvfx_shader.h"
#endif

View File

@ -1,104 +0,0 @@
#include "util/u_format.h"
#include "nvfx_context.h"
#include "nvfx_tex.h"
#include "nvfx_resource.h"
void
nv40_sampler_state_init(struct pipe_context *pipe,
struct nvfx_sampler_state *ps,
const struct pipe_sampler_state *cso)
{
if (cso->max_anisotropy >= 2) {
/* no idea, binary driver sets it, works without it.. meh.. */
ps->wrap |= (1 << 5);
if (cso->max_anisotropy >= 16)
ps->en |= NV40_3D_TEX_ENABLE_ANISO_16X;
else if (cso->max_anisotropy >= 12)
ps->en |= NV40_3D_TEX_ENABLE_ANISO_12X;
else if (cso->max_anisotropy >= 10)
ps->en |= NV40_3D_TEX_ENABLE_ANISO_10X;
else if (cso->max_anisotropy >= 8)
ps->en |= NV40_3D_TEX_ENABLE_ANISO_8X;
else if (cso->max_anisotropy >= 6)
ps->en |= NV40_3D_TEX_ENABLE_ANISO_6X;
else if (cso->max_anisotropy >= 4)
ps->en |= NV40_3D_TEX_ENABLE_ANISO_4X;
else
ps->en |= NV40_3D_TEX_ENABLE_ANISO_2X;
}
ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
ps->max_lod = (int)(CLAMP(cso->max_lod, 0.0, 15.0 + (255.0 / 256.0)) * 256.0);
ps->min_lod = (int)(CLAMP(cso->min_lod, 0.0, 15.0 + (255.0 / 256.0)) * 256.0);
ps->en |= NV40_3D_TEX_ENABLE_ENABLE;
}
void
nv40_sampler_view_init(struct pipe_context *pipe,
struct nvfx_sampler_view *sv)
{
struct pipe_resource* pt = sv->base.texture;
struct nvfx_miptree* mt = (struct nvfx_miptree*)pt;
struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format];
unsigned txf;
unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.u.tex.first_level;
assert(tf->fmt[4] >= 0);
txf = sv->u.init_fmt;
txf |= 0x8000;
if(pt->target == PIPE_TEXTURE_CUBE)
txf |= ((pt->last_level + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT);
else
txf |= (((sv->base.u.tex.last_level - sv->base.u.tex.first_level) + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT);
if (!mt->linear_pitch)
sv->u.nv40.npot_size2 = 0;
else {
sv->u.nv40.npot_size2 = mt->linear_pitch;
txf |= NV40_3D_TEX_FORMAT_LINEAR;
}
sv->u.nv40.fmt[0] = tf->fmt[4] | txf;
sv->u.nv40.fmt[1] = tf->fmt[5] | txf;
sv->u.nv40.npot_size2 |= (u_minify(pt->depth0, level) << NV40_3D_TEX_SIZE1_DEPTH__SHIFT);
sv->lod_offset = (sv->base.u.tex.first_level - level) * 256;
sv->max_lod_limit = (sv->base.u.tex.last_level - level) * 256;
}
void
nv40_fragtex_set(struct nvfx_context *nvfx, int unit)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
unsigned txf;
unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod);
txf = sv->u.nv40.fmt[ps->compare] | ps->fmt;
MARK_RING(chan, 11, 2);
BEGIN_RING(chan, eng3d, NV30_3D_TEX_OFFSET(unit), 8);
OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR,
NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
OUT_RING(chan, ps->en | (min_lod << 19) | (max_lod << 7));
OUT_RING(chan, sv->swizzle);
OUT_RING(chan, ps->filt | sv->filt);
OUT_RING(chan, sv->npot_size);
OUT_RING(chan, ps->bcol);
BEGIN_RING(chan, eng3d, NV40_3D_TEX_SIZE1(unit), 1);
OUT_RING(chan, sv->u.nv40.npot_size2);
nvfx->hw_txf[unit] = txf;
nvfx->hw_samplers |= (1 << unit);
}

View File

@ -1,178 +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_SATURATE (1 << 26)
#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 (0x3F << 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_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_SCA_OPCODE_SHIFT 27
#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27)
#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_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 (0x3F << 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_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
#include "nvfx_shader.h"
#endif

View File

@ -1,98 +0,0 @@
#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "nouveau/nouveau_screen.h"
#include "nouveau/nouveau_winsys.h"
#include "nvfx_resource.h"
#include "nvfx_screen.h"
void nvfx_buffer_destroy(struct pipe_screen *pscreen,
struct pipe_resource *presource)
{
struct nvfx_buffer *buffer = nvfx_buffer(presource);
if(!(buffer->base.base.flags & NVFX_RESOURCE_FLAG_USER))
align_free(buffer->data);
nouveau_screen_bo_release(pscreen, buffer->base.bo);
FREE(buffer);
}
struct pipe_resource *
nvfx_buffer_create(struct pipe_screen *pscreen,
const struct pipe_resource *template)
{
struct nvfx_screen* screen = nvfx_screen(pscreen);
struct nvfx_buffer* buffer;
buffer = CALLOC_STRUCT(nvfx_buffer);
if (!buffer)
return NULL;
buffer->base.base = *template;
buffer->base.base.flags |= NOUVEAU_RESOURCE_FLAG_LINEAR;
pipe_reference_init(&buffer->base.base.reference, 1);
buffer->base.base.screen = pscreen;
buffer->size = util_format_get_stride(template->format, template->width0);
buffer->bytes_to_draw_until_static = buffer->size * screen->static_reuse_threshold;
buffer->data = align_malloc(buffer->size, 16);
return &buffer->base.base;
}
struct pipe_resource *
nvfx_user_buffer_create(struct pipe_screen *pscreen,
void *ptr,
unsigned bytes,
unsigned usage)
{
struct nvfx_screen* screen = nvfx_screen(pscreen);
struct nvfx_buffer* buffer;
buffer = CALLOC_STRUCT(nvfx_buffer);
if (!buffer)
return NULL;
pipe_reference_init(&buffer->base.base.reference, 1);
buffer->base.base.flags =
NOUVEAU_RESOURCE_FLAG_LINEAR | NVFX_RESOURCE_FLAG_USER;
buffer->base.base.screen = pscreen;
buffer->base.base.format = PIPE_FORMAT_R8_UNORM;
buffer->base.base.usage = PIPE_USAGE_IMMUTABLE;
buffer->base.base.bind = usage;
buffer->base.base.width0 = bytes;
buffer->base.base.height0 = 1;
buffer->base.base.depth0 = 1;
buffer->base.base.array_size = 1;
buffer->data = ptr;
buffer->size = bytes;
buffer->bytes_to_draw_until_static = bytes * screen->static_reuse_threshold;
buffer->dirty_end = bytes;
return &buffer->base.base;
}
void nvfx_buffer_upload(struct nvfx_buffer* buffer)
{
unsigned dirty = buffer->dirty_end - buffer->dirty_begin;
if(!buffer->base.bo)
{
buffer->base.bo = nouveau_screen_bo_new(buffer->base.base.screen,
16,
buffer->base.base.usage,
buffer->base.base.bind,
buffer->base.base.width0);
}
if(dirty)
{
// TODO: may want to use a temporary in some cases
nouveau_bo_map(buffer->base.bo, NOUVEAU_BO_WR
| (buffer->dirty_unsynchronized ? NOUVEAU_BO_NOSYNC : 0));
memcpy((uint8_t*)buffer->base.bo->map + buffer->dirty_begin, buffer->data + buffer->dirty_begin, dirty);
nouveau_bo_unmap(buffer->base.bo);
buffer->dirty_begin = buffer->dirty_end = 0;
}
}

View File

@ -1,14 +0,0 @@
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "util/u_clear.h"
#include "nvfx_context.h"
void
nvfx_clear(struct pipe_context *pipe, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil)
{
util_clear(pipe, &nvfx_context(pipe)->framebuffer, buffers, color, depth,
stencil);
}

View File

@ -1,124 +0,0 @@
#include "draw/draw_context.h"
#include "pipe/p_defines.h"
#include "util/u_framebuffer.h"
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
#include "nvfx_context.h"
#include "nvfx_screen.h"
#include "nvfx_resource.h"
static void
nvfx_flush(struct pipe_context *pipe,
struct pipe_fence_handle **fence)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nvfx_screen *screen = nvfx->screen;
struct nouveau_channel *chan = screen->base.channel;
/*struct nouveau_grobj *eng3d = screen->eng3d;*/
/* XXX: we need to actually be intelligent here */
/* XXX This flag wasn't set by the state tracker anyway. */
/*if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
BEGIN_RING(chan, eng3d, 0x1fd8, 1);
OUT_RING(chan, 2);
BEGIN_RING(chan, eng3d, 0x1fd8, 1);
OUT_RING(chan, 1);
}*/
if (fence) {
/* horrific hack to make glFinish() work in the absence of
* having proper fences in nvfx. a pending rewrite will
* fix this properly, but may be a while off.
*/
MARK_RING(chan, 1, 1);
OUT_RELOC(chan, screen->fence, 0, NOUVEAU_BO_WR |
NOUVEAU_BO_DUMMY, 0, 0);
FIRE_RING(chan);
nouveau_bo_map(screen->fence, NOUVEAU_BO_RDWR);
nouveau_bo_unmap(screen->fence);
*fence = NULL;
} else {
FIRE_RING(chan);
}
}
static void
nvfx_destroy(struct pipe_context *pipe)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
if(nvfx->dummy_fs)
pipe->delete_fs_state(pipe, nvfx->dummy_fs);
for(unsigned i = 0; i < nvfx->vtxbuf_nr; ++i)
pipe_resource_reference(&nvfx->vtxbuf[i].buffer, 0);
pipe_resource_reference(&nvfx->idxbuf.buffer, 0);
util_unreference_framebuffer_state(&nvfx->framebuffer);
for(unsigned i = 0; i < PIPE_MAX_SAMPLERS; ++i)
pipe_sampler_view_reference(&nvfx->fragment_sampler_views[i], 0);
if (nvfx->draw)
draw_destroy(nvfx->draw);
if(nvfx->screen->cur_ctx == nvfx)
nvfx->screen->cur_ctx = NULL;
FREE(nvfx);
}
struct pipe_context *
nvfx_create(struct pipe_screen *pscreen, void *priv)
{
struct nvfx_screen *screen = nvfx_screen(pscreen);
struct nvfx_context *nvfx;
nvfx = CALLOC(1, sizeof(struct nvfx_context));
if (!nvfx)
return NULL;
nvfx->screen = screen;
nvfx->pipe.screen = pscreen;
nvfx->pipe.priv = priv;
nvfx->pipe.destroy = nvfx_destroy;
nvfx->pipe.draw_vbo = nvfx_draw_vbo;
nvfx->pipe.clear = nvfx_clear;
nvfx->pipe.flush = nvfx_flush;
nvfx->is_nv4x = screen->is_nv4x;
nvfx->use_nv4x = screen->use_nv4x;
/* TODO: it seems that nv30 might have fixed function clipping usable with vertex programs
* However, my code for that doesn't work, so use vp clipping for all cards, which works.
*/
nvfx->use_vp_clipping = TRUE;
nvfx_init_query_functions(nvfx);
nvfx_init_surface_functions(nvfx);
nvfx_init_state_functions(nvfx);
nvfx_init_sampling_functions(nvfx);
nvfx_init_vbo_functions(nvfx);
nvfx_init_fragprog_functions(nvfx);
nvfx_init_vertprog_functions(nvfx);
nvfx_init_resource_functions(&nvfx->pipe);
nvfx_init_transfer_functions(&nvfx->pipe);
/* Create, configure, and install fallback swtnl path */
nvfx->draw = draw_create(&nvfx->pipe);
draw_wide_point_threshold(nvfx->draw, 9999999.0);
draw_wide_line_threshold(nvfx->draw, 9999999.0);
draw_enable_line_stipple(nvfx->draw, FALSE);
draw_enable_point_sprites(nvfx->draw, FALSE);
draw_set_rasterize_stage(nvfx->draw, nvfx_draw_render_stage(nvfx));
/* set these to that we init them on first validation */
nvfx->state.scissor_enabled = ~0;
nvfx->hw_pointsprite_control = -1;
nvfx->hw_vp_output = -1;
nvfx->use_vertex_buffers = -1;
nvfx->relocs_needed = NVFX_RELOCATE_ALL;
LIST_INITHEAD(&nvfx->render_cache);
nvfx_context_init_vdec(nvfx);
return &nvfx->pipe;
}

View File

@ -1,375 +0,0 @@
#ifndef __NVFX_CONTEXT_H__
#define __NVFX_CONTEXT_H__
#include <stdio.h>
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "pipe/p_compiler.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_inlines.h"
#include "util/u_double_list.h"
#include "draw/draw_vertex.h"
#include "util/u_blitter.h"
#include "nouveau/nouveau_winsys.h"
#include "nouveau/nouveau_gldefs.h"
#include "nouveau/nouveau_resource.h"
#include "nv30-40_3d.xml.h"
#include "nvfx_state.h"
#define NOUVEAU_ERR(fmt, args...) \
fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args);
#define NOUVEAU_MSG(fmt, args...) \
fprintf(stderr, "nouveau: "fmt, ##args);
#include "nvfx_screen.h"
#define NVFX_NEW_BLEND (1 << 0)
#define NVFX_NEW_RAST (1 << 1)
#define NVFX_NEW_ZSA (1 << 2)
#define NVFX_NEW_SAMPLER (1 << 3)
#define NVFX_NEW_FB (1 << 4)
#define NVFX_NEW_STIPPLE (1 << 5)
#define NVFX_NEW_SCISSOR (1 << 6)
#define NVFX_NEW_VIEWPORT (1 << 7)
#define NVFX_NEW_BCOL (1 << 8)
#define NVFX_NEW_VERTPROG (1 << 9)
#define NVFX_NEW_FRAGPROG (1 << 10)
#define NVFX_NEW_ARRAYS (1 << 11)
#define NVFX_NEW_UCP (1 << 12)
#define NVFX_NEW_SR (1 << 13)
#define NVFX_NEW_VERTCONST (1 << 14)
#define NVFX_NEW_FRAGCONST (1 << 15)
#define NVFX_NEW_INDEX (1 << 16)
#define NVFX_NEW_SPRITE (1 << 17)
#define NVFX_RELOCATE_FRAMEBUFFER (1 << 0)
#define NVFX_RELOCATE_FRAGTEX (1 << 1)
#define NVFX_RELOCATE_FRAGPROG (1 << 2)
#define NVFX_RELOCATE_VTXBUF (1 << 3)
#define NVFX_RELOCATE_IDXBUF (1 << 4)
#define NVFX_RELOCATE_ALL 0x1f
struct nvfx_rasterizer_state {
struct pipe_rasterizer_state pipe;
unsigned sb_len;
uint32_t sb[34];
};
struct nvfx_zsa_state {
struct pipe_depth_stencil_alpha_state pipe;
unsigned sb_len;
uint32_t sb[24];
};
struct nvfx_blend_state {
struct pipe_blend_state pipe;
unsigned sb_len;
uint32_t sb[13];
};
struct nvfx_state {
unsigned scissor_enabled;
unsigned fp_samplers;
unsigned render_temps;
};
struct nvfx_per_vertex_element {
unsigned idx;
unsigned vertex_buffer_index;
unsigned src_offset;
};
struct nvfx_low_frequency_element {
unsigned idx;
unsigned vertex_buffer_index;
unsigned src_offset;
void (*fetch_rgba_float)(float *dst, const uint8_t *src, unsigned i, unsigned j);
unsigned ncomp;
};
struct nvfx_per_instance_element {
struct nvfx_low_frequency_element base;
unsigned instance_divisor;
};
struct nvfx_per_vertex_buffer_info
{
unsigned vertex_buffer_index;
unsigned per_vertex_size;
};
struct nvfx_vtxelt_state {
struct pipe_vertex_element pipe[16];
unsigned num_elements;
unsigned vtxfmt[16];
unsigned num_per_vertex_buffer_infos;
struct nvfx_per_vertex_buffer_info per_vertex_buffer_info[16];
unsigned num_per_vertex;
struct nvfx_per_vertex_element per_vertex[16];
unsigned num_per_instance;
struct nvfx_per_instance_element per_instance[16];
unsigned num_constant;
struct nvfx_low_frequency_element constant[16];
boolean needs_translate;
struct translate* translate;
unsigned vertex_length;
unsigned max_vertices_per_packet;
};
struct nvfx_render_target {
struct nouveau_bo* bo;
unsigned offset;
unsigned pitch;
};
struct nvfx_context {
struct pipe_context pipe;
struct nvfx_screen *screen;
unsigned is_nv4x; /* either 0 or ~0 */
unsigned use_nv4x; /* either 0 or ~0 */
boolean use_vp_clipping;
struct draw_context *draw;
/* one is for user-requested operations, the other is for temporary copying inside them */
struct blitter_context* blitter[2];
unsigned blitters_in_use;
struct list_head render_cache;
/* HW state derived from pipe states */
struct nvfx_state state;
enum {
HW, SWTNL, SWRAST
} render_mode;
unsigned fallback_swtnl;
/* Context state */
unsigned dirty, draw_dirty;
struct pipe_scissor_state scissor;
unsigned stipple[32];
struct pipe_clip_state clip;
struct nvfx_pipe_vertex_program *vertprog;
struct nvfx_pipe_fragment_program *fragprog;
struct pipe_resource *constbuf[PIPE_SHADER_TYPES];
unsigned constbuf_nr[PIPE_SHADER_TYPES];
struct nvfx_rasterizer_state *rasterizer;
struct nvfx_zsa_state *zsa;
struct nvfx_blend_state *blend;
struct pipe_blend_color blend_colour;
struct pipe_stencil_ref stencil_ref;
struct pipe_viewport_state viewport;
struct pipe_framebuffer_state framebuffer;
struct pipe_index_buffer idxbuf;
struct nvfx_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
struct nvfx_pipe_fragment_program* dummy_fs;
struct pipe_query* query;
unsigned nr_samplers;
unsigned nr_textures;
unsigned dirty_samplers;
struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
unsigned vtxbuf_nr;
struct nvfx_vtxelt_state *vtxelt;
int base_vertex;
boolean use_index_buffer;
/* -1 = hardware input setup is outdated
* 0 = hardware input setup is for inline vertices
* 1 = hardware input setup is for hardware vertices
*/
int use_vertex_buffers;
unsigned hw_vtxelt_nr;
unsigned hw_samplers;
uint32_t hw_txf[16];
struct nvfx_render_target hw_rt[4];
struct nvfx_render_target hw_zeta;
int hw_pointsprite_control;
int hw_vp_output;
struct nvfx_fragment_program* hw_fragprog;
struct nvfx_vertex_program* hw_vertprog;
unsigned relocs_needed;
};
static INLINE struct nvfx_context *
nvfx_context(struct pipe_context *pipe)
{
return (struct nvfx_context *)pipe;
}
extern struct nvfx_state_entry nvfx_state_blend;
extern struct nvfx_state_entry nvfx_state_blend_colour;
extern struct nvfx_state_entry nvfx_state_fragprog;
extern struct nvfx_state_entry nvfx_state_fragtex;
extern struct nvfx_state_entry nvfx_state_framebuffer;
extern struct nvfx_state_entry nvfx_state_rasterizer;
extern struct nvfx_state_entry nvfx_state_scissor;
extern struct nvfx_state_entry nvfx_state_sr;
extern struct nvfx_state_entry nvfx_state_stipple;
extern struct nvfx_state_entry nvfx_state_vbo;
extern struct nvfx_state_entry nvfx_state_vertprog;
extern struct nvfx_state_entry nvfx_state_viewport;
extern struct nvfx_state_entry nvfx_state_vtxfmt;
extern struct nvfx_state_entry nvfx_state_zsa;
extern void nvfx_init_query_functions(struct nvfx_context *nvfx);
extern void nvfx_init_surface_functions(struct nvfx_context *nvfx);
/* nvfx_context.c */
struct pipe_context *
nvfx_create(struct pipe_screen *pscreen, void *priv);
/* nvfx_clear.c */
extern void nvfx_clear(struct pipe_context *pipe, unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil);
/* nvfx_draw.c */
extern struct draw_stage *nvfx_draw_render_stage(struct nvfx_context *nvfx);
extern void nvfx_draw_vbo_swtnl(struct pipe_context *pipe, const struct pipe_draw_info* info);
extern void nvfx_vtxfmt_validate(struct nvfx_context *nvfx);
/* nvfx_fb.c */
extern int nvfx_framebuffer_prepare(struct nvfx_context *nvfx);
extern void nvfx_framebuffer_validate(struct nvfx_context *nvfx);
void
nvfx_framebuffer_relocate(struct nvfx_context *nvfx);
/* nvfx_fragprog.c */
extern void nvfx_fragprog_destroy(struct nvfx_context *,
struct nvfx_fragment_program *);
extern void nvfx_fragprog_validate(struct nvfx_context *nvfx);
extern void nvfx_fragprog_relocate(struct nvfx_context *nvfx);
extern void nvfx_init_fragprog_functions(struct nvfx_context *nvfx);
/* nvfx_fragtex.c */
extern void nvfx_init_sampling_functions(struct nvfx_context *nvfx);
extern void nvfx_fragtex_validate(struct nvfx_context *nvfx);
extern void nvfx_fragtex_relocate(struct nvfx_context *nvfx);
struct nvfx_sampler_view;
/* nv30_fragtex.c */
extern void
nv30_sampler_state_init(struct pipe_context *pipe,
struct nvfx_sampler_state *ps,
const struct pipe_sampler_state *cso);
extern void
nv30_sampler_view_init(struct pipe_context *pipe,
struct nvfx_sampler_view *sv);
extern void nv30_fragtex_set(struct nvfx_context *nvfx, int unit);
/* nv40_fragtex.c */
extern void
nv40_sampler_state_init(struct pipe_context *pipe,
struct nvfx_sampler_state *ps,
const struct pipe_sampler_state *cso);
extern void
nv40_sampler_view_init(struct pipe_context *pipe,
struct nvfx_sampler_view *sv);
extern void nv40_fragtex_set(struct nvfx_context *nvfx, int unit);
/* nvfx_state.c */
extern void nvfx_init_state_functions(struct nvfx_context *nvfx);
extern void nvfx_state_scissor_validate(struct nvfx_context *nvfx);
extern void nvfx_state_stipple_validate(struct nvfx_context *nvfx);
extern void nvfx_state_blend_validate(struct nvfx_context *nvfx);
extern void nvfx_state_blend_colour_validate(struct nvfx_context *nvfx);
extern void nvfx_state_viewport_validate(struct nvfx_context *nvfx);
extern void nvfx_state_rasterizer_validate(struct nvfx_context *nvfx);
extern void nvfx_state_sr_validate(struct nvfx_context *nvfx);
extern void nvfx_state_zsa_validate(struct nvfx_context *nvfx);
/* nvfx_state_emit.c */
extern void nvfx_state_relocate(struct nvfx_context *nvfx, unsigned relocs);
extern boolean nvfx_state_validate(struct nvfx_context *nvfx);
extern boolean nvfx_state_validate_swtnl(struct nvfx_context *nvfx);
static inline void
nvfx_state_emit(struct nvfx_context *nvfx)
{
unsigned relocs = NVFX_RELOCATE_FRAMEBUFFER | NVFX_RELOCATE_FRAGTEX | NVFX_RELOCATE_FRAGPROG;
if (nvfx->render_mode == HW)
{
relocs |= NVFX_RELOCATE_VTXBUF;
if(nvfx->use_index_buffer)
relocs |= NVFX_RELOCATE_IDXBUF;
}
relocs &= nvfx->relocs_needed;
if(relocs)
nvfx_state_relocate(nvfx, relocs);
}
/* nvfx_transfer.c */
extern void nvfx_init_transfer_functions(struct pipe_context *pipe);
/* nvfx_vbo.c */
extern boolean nvfx_vbo_validate(struct nvfx_context *nvfx);
extern void nvfx_vbo_swtnl_validate(struct nvfx_context *nvfx);
extern void nvfx_vbo_relocate(struct nvfx_context *nvfx);
extern void nvfx_idxbuf_validate(struct nvfx_context* nvfx);
extern void nvfx_idxbuf_relocate(struct nvfx_context* nvfx);
extern void nvfx_draw_vbo(struct pipe_context *pipe,
const struct pipe_draw_info *info);
extern void nvfx_init_vbo_functions(struct nvfx_context *nvfx);
extern unsigned nvfx_vertex_formats[];
/* nvfx_vertprog.c */
extern boolean nvfx_vertprog_validate(struct nvfx_context *nvfx);
extern void nvfx_vertprog_destroy(struct nvfx_context *,
struct nvfx_vertex_program *);
extern void nvfx_init_vertprog_functions(struct nvfx_context *nvfx);
/* nvfx_push.c */
extern void nvfx_push_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info);
extern void nvfx_context_init_vdec(struct nvfx_context *);
static inline void nvfx_emit_vtx_attr(struct nouveau_channel* chan,
struct nouveau_grobj *eng3d, unsigned attrib, const float* v,
unsigned ncomp)
{
switch (ncomp) {
case 4:
BEGIN_RING(chan, eng3d, NV30_3D_VTX_ATTR_4F_X(attrib), 4);
OUT_RING(chan, fui(v[0]));
OUT_RING(chan, fui(v[1]));
OUT_RING(chan, fui(v[2]));
OUT_RING(chan, fui(v[3]));
break;
case 3:
BEGIN_RING(chan, eng3d, NV30_3D_VTX_ATTR_3F_X(attrib), 3);
OUT_RING(chan, fui(v[0]));
OUT_RING(chan, fui(v[1]));
OUT_RING(chan, fui(v[2]));
break;
case 2:
BEGIN_RING(chan, eng3d, NV30_3D_VTX_ATTR_2F_X(attrib), 2);
OUT_RING(chan, fui(v[0]));
OUT_RING(chan, fui(v[1]));
break;
case 1:
BEGIN_RING(chan, eng3d, NV30_3D_VTX_ATTR_1F(attrib), 1);
OUT_RING(chan, fui(v[0]));
break;
}
}
#endif

View File

@ -1,191 +0,0 @@
#include "pipe/p_shader_tokens.h"
#include "util/u_inlines.h"
#include "util/u_pack_color.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pipe.h"
#include "nvfx_context.h"
#include "nvfx_resource.h"
struct nvfx_render_stage {
struct draw_stage stage;
struct nvfx_context *nvfx;
unsigned prim;
};
static INLINE struct nvfx_render_stage *
nvfx_render_stage(struct draw_stage *stage)
{
return (struct nvfx_render_stage *)stage;
}
static void
nvfx_render_flush(struct draw_stage *stage, unsigned flags)
{
struct nvfx_render_stage *rs = nvfx_render_stage(stage);
struct nvfx_context *nvfx = rs->nvfx;
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
if (rs->prim != NV30_3D_VERTEX_BEGIN_END_STOP) {
BEGIN_RING(chan, eng3d, NV30_3D_VERTEX_BEGIN_END, 1);
OUT_RING(chan, NV30_3D_VERTEX_BEGIN_END_STOP);
rs->prim = NV30_3D_VERTEX_BEGIN_END_STOP;
}
}
static INLINE void
nvfx_render_prim(struct draw_stage *stage, struct prim_header *prim,
unsigned mode, unsigned count)
{
struct nvfx_render_stage *rs = nvfx_render_stage(stage);
struct nvfx_context *nvfx = rs->nvfx;
struct nvfx_screen *screen = nvfx->screen;
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *eng3d = screen->eng3d;
boolean no_elements = nvfx->vertprog->draw_no_elements;
unsigned num_attribs = nvfx->vertprog->draw_elements;
/* we need to account the flush as well here even if it is done afterthis
* function
*/
if (AVAIL_RING(chan) < ((1 + count * num_attribs * 4) + 6 + 64)) {
nvfx_render_flush(stage, 0);
FIRE_RING(chan);
nvfx_state_emit(nvfx);
assert(AVAIL_RING(chan) >= ((1 + count * num_attribs * 4) + 6 + 64));
}
/* Switch primitive modes if necessary */
if (rs->prim != mode) {
if (rs->prim != NV30_3D_VERTEX_BEGIN_END_STOP) {
BEGIN_RING(chan, eng3d, NV30_3D_VERTEX_BEGIN_END, 1);
OUT_RING(chan, NV30_3D_VERTEX_BEGIN_END_STOP);
}
/* XXX: any command a lot of times seems to (mostly) fix corruption that would otherwise happen */
/* this seems to cause issues on nv3x, and also be unneeded there */
if(nvfx->is_nv4x)
{
int i;
for(i = 0; i < 32; ++i)
{
BEGIN_RING(chan, eng3d, 0x1dac, 1);
OUT_RING(chan, 0);
}
}
BEGIN_RING(chan, eng3d, NV30_3D_VERTEX_BEGIN_END, 1);
OUT_RING (chan, mode);
rs->prim = mode;
}
if(no_elements) {
BEGIN_RING_NI(chan, eng3d, NV30_3D_VERTEX_DATA, 4);
OUT_RING(chan, 0);
OUT_RING(chan, 0);
OUT_RING(chan, 0);
OUT_RING(chan, 0);
} else {
BEGIN_RING_NI(chan, eng3d, NV30_3D_VERTEX_DATA, num_attribs * 4 * count);
for (unsigned i = 0; i < count; ++i)
{
struct vertex_header* v = prim->v[i];
/* TODO: disable divide where it's causing the problem, and remove this hack */
OUT_RING(chan, fui(v->data[0][0] / v->data[0][3]));
OUT_RING(chan, fui(v->data[0][1] / v->data[0][3]));
OUT_RING(chan, fui(v->data[0][2] / v->data[0][3]));
OUT_RING(chan, fui(1.0f / v->data[0][3]));
OUT_RINGp(chan, &v->data[1][0], 4 * (num_attribs - 1));
}
}
}
static void
nvfx_render_point(struct draw_stage *draw, struct prim_header *prim)
{
nvfx_render_prim(draw, prim, NV30_3D_VERTEX_BEGIN_END_POINTS, 1);
}
static void
nvfx_render_line(struct draw_stage *draw, struct prim_header *prim)
{
nvfx_render_prim(draw, prim, NV30_3D_VERTEX_BEGIN_END_LINES, 2);
}
static void
nvfx_render_tri(struct draw_stage *draw, struct prim_header *prim)
{
nvfx_render_prim(draw, prim, NV30_3D_VERTEX_BEGIN_END_TRIANGLES, 3);
}
static void
nvfx_render_reset_stipple_counter(struct draw_stage *draw)
{
/* this doesn't really seem to work, but it matters rather little */
nvfx_render_flush(draw, 0);
}
static void
nvfx_render_destroy(struct draw_stage *draw)
{
FREE(draw);
}
struct draw_stage *
nvfx_draw_render_stage(struct nvfx_context *nvfx)
{
struct nvfx_render_stage *render = CALLOC_STRUCT(nvfx_render_stage);
render->nvfx = nvfx;
render->stage.draw = nvfx->draw;
render->stage.point = nvfx_render_point;
render->stage.line = nvfx_render_line;
render->stage.tri = nvfx_render_tri;
render->stage.flush = nvfx_render_flush;
render->stage.reset_stipple_counter = nvfx_render_reset_stipple_counter;
render->stage.destroy = nvfx_render_destroy;
return &render->stage;
}
void
nvfx_draw_vbo_swtnl(struct pipe_context *pipe, const struct pipe_draw_info* info)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
unsigned i;
void *map;
if (!nvfx_state_validate_swtnl(nvfx))
return;
nvfx_state_emit(nvfx);
/* these must be passed without adding the offsets */
for (i = 0; i < nvfx->vtxbuf_nr; i++) {
map = nvfx_buffer(nvfx->vtxbuf[i].buffer)->data;
draw_set_mapped_vertex_buffer(nvfx->draw, i, map);
}
map = NULL;
if (info->indexed && nvfx->idxbuf.buffer)
map = nvfx_buffer(nvfx->idxbuf.buffer)->data;
draw_set_mapped_index_buffer(nvfx->draw, map);
if (nvfx->constbuf[PIPE_SHADER_VERTEX]) {
const unsigned nr = nvfx->constbuf_nr[PIPE_SHADER_VERTEX];
map = nvfx_buffer(nvfx->constbuf[PIPE_SHADER_VERTEX])->data;
draw_set_mapped_constant_buffer(nvfx->draw, PIPE_SHADER_VERTEX, 0,
map, nr);
}
draw_vbo(nvfx->draw, info);
draw_flush(nvfx->draw);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,355 +0,0 @@
#include "nvfx_context.h"
#include "nvfx_resource.h"
#include "nvfx_tex.h"
static void *
nvfx_sampler_state_create(struct pipe_context *pipe,
const struct pipe_sampler_state *cso)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nvfx_sampler_state *ps;
ps = MALLOC(sizeof(struct nvfx_sampler_state));
/* on nv30, we use this as an internal flag */
ps->fmt = cso->normalized_coords ? 0 : NV40_3D_TEX_FORMAT_RECT;
ps->en = 0;
ps->filt = nvfx_tex_filter(cso) | 0x2000; /*voodoo*/
ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV30_3D_TEX_WRAP_S__SHIFT) |
(nvfx_tex_wrap_mode(cso->wrap_t) << NV30_3D_TEX_WRAP_T__SHIFT) |
(nvfx_tex_wrap_mode(cso->wrap_r) << NV30_3D_TEX_WRAP_R__SHIFT);
ps->compare = FALSE;
if(cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE)
{
ps->wrap |= nvfx_tex_wrap_compare_mode(cso->compare_func);
ps->compare = TRUE;
}
ps->bcol = nvfx_tex_border_color(cso->border_color.f);
if(nvfx->is_nv4x)
nv40_sampler_state_init(pipe, ps, cso);
else
nv30_sampler_state_init(pipe, ps, cso);
return (void *)ps;
}
static void
nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
{
FREE(hwcso);
}
static void
nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
unsigned unit;
for (unit = 0; unit < nr; unit++) {
nvfx->tex_sampler[unit] = sampler[unit];
nvfx->dirty_samplers |= (1 << unit);
}
for (unit = nr; unit < nvfx->nr_samplers; unit++) {
nvfx->tex_sampler[unit] = NULL;
nvfx->dirty_samplers |= (1 << unit);
}
nvfx->nr_samplers = nr;
nvfx->dirty |= NVFX_NEW_SAMPLER;
}
static struct pipe_sampler_view *
nvfx_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *pt,
const struct pipe_sampler_view *templ)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nvfx_sampler_view *sv = CALLOC_STRUCT(nvfx_sampler_view);
struct nvfx_texture_format *tf = &nvfx_texture_formats[templ->format];
unsigned txf;
if (!sv)
return NULL;
sv->base = *templ;
sv->base.reference.count = 1;
sv->base.texture = NULL;
pipe_resource_reference(&sv->base.texture, pt);
sv->base.context = pipe;
txf = NV30_3D_TEX_FORMAT_NO_BORDER;
switch (pt->target) {
case PIPE_TEXTURE_CUBE:
txf |= NV30_3D_TEX_FORMAT_CUBIC;
/* fall-through */
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
txf |= NV30_3D_TEX_FORMAT_DIMS_2D;
break;
case PIPE_TEXTURE_3D:
txf |= NV30_3D_TEX_FORMAT_DIMS_3D;
break;
case PIPE_TEXTURE_1D:
txf |= NV30_3D_TEX_FORMAT_DIMS_1D;
break;
default:
assert(0);
}
sv->u.init_fmt = txf;
sv->swizzle = 0
| (tf->src[sv->base.swizzle_r] << NV30_3D_TEX_SWIZZLE_S0_Z__SHIFT)
| (tf->src[sv->base.swizzle_g] << NV30_3D_TEX_SWIZZLE_S0_Y__SHIFT)
| (tf->src[sv->base.swizzle_b] << NV30_3D_TEX_SWIZZLE_S0_X__SHIFT)
| (tf->src[sv->base.swizzle_a] << NV30_3D_TEX_SWIZZLE_S0_W__SHIFT)
| (tf->comp[sv->base.swizzle_r] << NV30_3D_TEX_SWIZZLE_S1_Z__SHIFT)
| (tf->comp[sv->base.swizzle_g] << NV30_3D_TEX_SWIZZLE_S1_Y__SHIFT)
| (tf->comp[sv->base.swizzle_b] << NV30_3D_TEX_SWIZZLE_S1_X__SHIFT)
| (tf->comp[sv->base.swizzle_a] << NV30_3D_TEX_SWIZZLE_S1_W__SHIFT);
sv->filt = tf->sign;
sv->wrap = tf->wrap;
sv->wrap_mask = ~0;
if (pt->target == PIPE_TEXTURE_CUBE)
{
sv->offset = 0;
sv->npot_size = (pt->width0 << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | pt->height0;
}
else
{
sv->offset = nvfx_subresource_offset(pt, 0, sv->base.u.tex.first_level, 0);
sv->npot_size = (u_minify(pt->width0, sv->base.u.tex.first_level) << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | u_minify(pt->height0, sv->base.u.tex.first_level);
/* apparently, we need to ignore the t coordinate for 1D textures to fix piglit tex1d-2dborder */
if(pt->target == PIPE_TEXTURE_1D)
{
sv->wrap_mask &=~ NV30_3D_TEX_WRAP_T__MASK;
sv->wrap |= NV30_3D_TEX_WRAP_T_REPEAT;
}
}
if(nvfx->is_nv4x)
nv40_sampler_view_init(pipe, sv);
else
nv30_sampler_view_init(pipe, sv);
return &sv->base;
}
static void
nvfx_sampler_view_destroy(struct pipe_context *pipe,
struct pipe_sampler_view *view)
{
pipe_resource_reference(&view->texture, NULL);
FREE(view);
}
static void
nvfx_set_fragment_sampler_views(struct pipe_context *pipe,
unsigned nr,
struct pipe_sampler_view **views)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
unsigned unit;
for (unit = 0; unit < nr; unit++) {
pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit],
views[unit]);
nvfx->dirty_samplers |= (1 << unit);
}
for (unit = nr; unit < nvfx->nr_textures; unit++) {
pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit],
NULL);
nvfx->dirty_samplers |= (1 << unit);
}
nvfx->nr_textures = nr;
nvfx->dirty |= NVFX_NEW_SAMPLER;
}
void
nvfx_fragtex_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
unsigned samplers, unit;
samplers = nvfx->dirty_samplers;
if(!samplers)
return;
while (samplers) {
unit = ffs(samplers) - 1;
samplers &= ~(1 << unit);
if(nvfx->fragment_sampler_views[unit] && nvfx->tex_sampler[unit]) {
if(!nvfx->is_nv4x)
nv30_fragtex_set(nvfx, unit);
else
nv40_fragtex_set(nvfx, unit);
} else {
/* this is OK for nv40 too */
BEGIN_RING(chan, eng3d, NV30_3D_TEX_ENABLE(unit), 1);
OUT_RING(chan, 0);
nvfx->hw_samplers &= ~(1 << unit);
}
}
nvfx->dirty_samplers = 0;
nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGTEX;
}
void
nvfx_fragtex_relocate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
unsigned samplers, unit;
unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
samplers = nvfx->hw_samplers;
while (samplers) {
struct nvfx_miptree* mt;
struct nouveau_bo *bo;
unit = ffs(samplers) - 1;
samplers &= ~(1 << unit);
mt = (struct nvfx_miptree*)nvfx->fragment_sampler_views[unit]->texture;
bo = mt->base.bo;
MARK_RING(chan, 3, 3);
OUT_RELOC(chan, bo, RING_3D(NV30_3D_TEX_OFFSET(unit), 2), tex_flags | NOUVEAU_BO_DUMMY, 0, 0);
OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_DUMMY, 0, 0);
OUT_RELOC(chan, bo, nvfx->hw_txf[unit], tex_flags | NOUVEAU_BO_OR | NOUVEAU_BO_DUMMY,
NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
}
nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGTEX;
}
void
nvfx_init_sampling_functions(struct nvfx_context *nvfx)
{
nvfx->pipe.create_sampler_state = nvfx_sampler_state_create;
nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind;
nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete;
nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views;
nvfx->pipe.create_sampler_view = nvfx_create_sampler_view;
nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy;
}
#define NV30_3D_TEX_FORMAT_FORMAT_DXT1_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT1
#define NV30_3D_TEX_FORMAT_FORMAT_DXT3_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT3
#define NV30_3D_TEX_FORMAT_FORMAT_DXT5_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT5
#define NV40_3D_TEX_FORMAT_FORMAT_HILO16 NV40_3D_TEX_FORMAT_FORMAT_A16L16
#define NV30_3D_TEX_FORMAT_FORMAT_RGBA16F 0x00004a00
#define NV30_3D_TEX_FORMAT_FORMAT_RGBA16F_RECT NV30_3D_TEX_FORMAT_FORMAT_RGBA16F
#define NV30_3D_TEX_FORMAT_FORMAT_RGBA32F 0x00004b00
#define NV30_3D_TEX_FORMAT_FORMAT_RGBA32F_RECT NV30_3D_TEX_FORMAT_FORMAT_RGBA32F
#define NV30_3D_TEX_FORMAT_FORMAT_R32F 0x00004c00
#define NV30_3D_TEX_FORMAT_FORMAT_R32F_RECT NV30_3D_TEX_FORMAT_FORMAT_R32F
// TODO: guess!
#define NV40_3D_TEX_FORMAT_FORMAT_R32F 0x00001c00
#define SRGB 0x00700000
#define __(m,tf,tfc,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign,wrap) \
[PIPE_FORMAT_##m] = { \
{NV30_3D_TEX_FORMAT_FORMAT_##tf, \
NV30_3D_TEX_FORMAT_FORMAT_##tfc, \
NV30_3D_TEX_FORMAT_FORMAT_##tf##_RECT, \
NV30_3D_TEX_FORMAT_FORMAT_##tfc##_RECT, \
NV40_3D_TEX_FORMAT_FORMAT_##tf, \
NV40_3D_TEX_FORMAT_FORMAT_##tfc}, \
sign, wrap, \
{ts0z, ts0y, ts0x, ts0w, 0, 1}, {ts1z, ts1y, ts1x, ts1w, 0, 0} \
}
#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign, wrap) \
__(m,tf,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign, wrap)
/* Depth formats works by reading the depth value most significant 8/16 bits.
* We are losing precision, but nVidia loses even more by using A8R8G8B8 instead of HILO16
* There is no 32-bit integer texture support, so other things are infeasible.
*
* TODO: is it possible to read 16 bits for Z16? A16 doesn't seem to work, either due to normalization or endianness issues
*/
#define T 2
#define X 3
#define Y 2
#define Z 1
#define W 0
#define SNORM ((NV30_3D_TEX_FILTER_SIGNED_RED) | (NV30_3D_TEX_FILTER_SIGNED_GREEN) | (NV30_3D_TEX_FILTER_SIGNED_BLUE) | (NV30_3D_TEX_FILTER_SIGNED_ALPHA))
#define UNORM 0
struct nvfx_texture_format
nvfx_texture_formats[PIPE_FORMAT_COUNT] = {
[0 ... PIPE_FORMAT_COUNT - 1] = {{-1, -1, -1, -1, -1, -1}},
_(B8G8R8X8_UNORM, A8R8G8B8, T, T, T, 1, X, Y, Z, W, UNORM, 0),
_(B8G8R8X8_SRGB, A8R8G8B8, T, T, T, 1, X, Y, Z, W, UNORM, SRGB),
_(B8G8R8A8_UNORM, A8R8G8B8, T, T, T, T, X, Y, Z, W, UNORM, 0),
_(B8G8R8A8_SRGB, A8R8G8B8, T, T, T, T, X, Y, Z, W, UNORM, SRGB),
_(R8G8B8A8_UNORM, A8R8G8B8, T, T, T, T, Z, Y, X, W, UNORM, 0),
_(R8G8B8A8_SRGB, A8R8G8B8, T, T, T, T, Z, Y, X, W, UNORM, SRGB),
_(R8G8B8X8_UNORM, A8R8G8B8, T, T, T, 1, Z, Y, X, W, UNORM, 0),
_(A8R8G8B8_UNORM, A8R8G8B8, T, T, T, T, W, Z, Y, X, UNORM, 0),
_(A8R8G8B8_SRGB, A8R8G8B8, T, T, T, T, W, Z, Y, X, UNORM, SRGB),
_(A8B8G8R8_UNORM, A8R8G8B8, T, T, T, T, W, X, Y, Z, UNORM, 0),
_(A8B8G8R8_SRGB, A8R8G8B8, T, T, T, T, W, X, Y, Z, UNORM, SRGB),
_(X8R8G8B8_UNORM, A8R8G8B8, T, T, T, 1, W, Z, Y, X, UNORM, 0),
_(X8R8G8B8_SRGB, A8R8G8B8, T, T, T, 1, W, Z, Y, X, UNORM, SRGB),
_(B5G5R5A1_UNORM, A1R5G5B5, T, T, T, T, X, Y, Z, W, UNORM, 0),
_(B5G5R5X1_UNORM, A1R5G5B5, T, T, T, 1, X, Y, Z, W, UNORM, 0),
_(B4G4R4A4_UNORM, A4R4G4B4, T, T, T, T, X, Y, Z, W, UNORM, 0),
_(B4G4R4X4_UNORM, A4R4G4B4, T, T, T, 1, X, Y, Z, W, UNORM, 0),
_(B5G6R5_UNORM, R5G6B5, T, T, T, 1, X, Y, Z, W, UNORM, 0),
_(R8_UNORM, L8, T, 0, 0, 1, X, X, X, X, UNORM, 0),
_(R8_SNORM, L8, T, 0, 0, 1, X, X, X, X, SNORM, 0),
_(L8_UNORM, L8, T, T, T, 1, X, X, X, X, UNORM, 0),
_(L8_SRGB, L8, T, T, T, 1, X, X, X, X, UNORM, SRGB),
_(A8_UNORM, L8, 0, 0, 0, T, X, X, X, X, UNORM, 0),
_(I8_UNORM, L8, T, T, T, T, X, X, X, X, UNORM, 0),
_(R8G8_UNORM, A8L8, T, T, T, T, X, X, X, W, UNORM, 0),
_(R8G8_SNORM, A8L8, T, T, T, T, X, X, X, W, SNORM, 0),
_(L8A8_UNORM, A8L8, T, T, T, T, X, X, X, W, UNORM, 0),
_(L8A8_SRGB, A8L8, T, T, T, T, X, X, X, W, UNORM, SRGB),
_(DXT1_RGB, DXT1, T, T, T, 1, X, Y, Z, W, UNORM, 0),
_(DXT1_SRGB, DXT1, T, T, T, 1, X, Y, Z, W, UNORM, SRGB),
_(DXT1_RGBA, DXT1, T, T, T, T, X, Y, Z, W, UNORM, 0),
_(DXT1_SRGBA, DXT1, T, T, T, T, X, Y, Z, W, UNORM, SRGB),
_(DXT3_RGBA, DXT3, T, T, T, T, X, Y, Z, W, UNORM, 0),
_(DXT3_SRGBA, DXT3, T, T, T, T, X, Y, Z, W, UNORM, SRGB),
_(DXT5_RGBA, DXT5, T, T, T, T, X, Y, Z, W, UNORM, 0),
_(DXT5_SRGBA, DXT5, T, T, T, T, X, Y, Z, W, UNORM, SRGB),
__(Z16_UNORM, A8L8, Z16, T, T, T, 1, W, W, W, W, UNORM, 0),
__(S8_UINT_Z24_UNORM,HILO16,Z24, T, T, T, 1, W, W, W, W, UNORM, 0),
__(X8Z24_UNORM, HILO16,Z24, T, T, T, 1, W, W, W, W, UNORM, 0),
_(R16_UNORM, A16, T, 0, 0, 1, X, X, X, X, UNORM, 0),
_(R16_SNORM, A16, T, 0, 0, 1, X, X, X, X, SNORM, 0),
_(R16G16_UNORM, HILO16, T, T, 0, 1, X, Y, X, X, UNORM, 0),
_(R16G16_SNORM, HILO16, T, T, 0, 1, X, Y, X, X, SNORM, 0),
_(R16G16B16A16_FLOAT, RGBA16F, T, T, T, T, X, Y, Z, W, UNORM, 0),
_(R32G32B32A32_FLOAT, RGBA32F, T, T, T, T, X, Y, Z, W, UNORM, 0),
_(R32_FLOAT, R32F, T, 0, 0, 1, X, X, X, X, UNORM, 0)
};

View File

@ -1,214 +0,0 @@
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_staging.h"
#include "state_tracker/drm_driver.h"
#include "nouveau/nouveau_winsys.h"
#include "nouveau/nouveau_screen.h"
#include "nvfx_screen.h"
#include "nvfx_resource.h"
static void
nvfx_miptree_choose_format(struct nvfx_miptree *mt)
{
struct pipe_resource *pt = &mt->base.base;
unsigned uniform_pitch = 0;
static int no_swizzle = -1;
if(no_swizzle < 0)
no_swizzle = debug_get_bool_option("NV40_NO_SWIZZLE", FALSE); /* this will break things on nv30 */
if (!util_is_power_of_two(pt->width0) ||
!util_is_power_of_two(pt->height0) ||
!util_is_power_of_two(pt->depth0) ||
(!nvfx_screen(pt->screen)->is_nv4x && pt->target == PIPE_TEXTURE_RECT)
)
uniform_pitch = 1;
if (
(pt->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET))
|| (pt->usage & PIPE_USAGE_DYNAMIC) || (pt->usage & PIPE_USAGE_STAGING)
|| util_format_is_compressed(pt->format)
|| no_swizzle
)
mt->base.base.flags |= NOUVEAU_RESOURCE_FLAG_LINEAR;
/* non compressed formats with uniform pitch must be linear, and vice versa */
if(!util_format_is_s3tc(pt->format)
&& (uniform_pitch || mt->base.base.flags & NOUVEAU_RESOURCE_FLAG_LINEAR))
{
mt->base.base.flags |= NOUVEAU_RESOURCE_FLAG_LINEAR;
uniform_pitch = 1;
}
if(uniform_pitch)
{
mt->linear_pitch = util_format_get_stride(pt->format, pt->width0);
// TODO: this is only a constraint for rendering and not sampling, apparently
// we may also want this unconditionally
if(pt->bind & (PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_DEPTH_STENCIL |
PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT))
mt->linear_pitch = align(mt->linear_pitch, 64);
}
else
mt->linear_pitch = 0;
}
static unsigned
nvfx_miptree_layout(struct nvfx_miptree *mt)
{
struct pipe_resource* pt = &mt->base.base;
uint offset = 0;
if(!nvfx_screen(pt->screen)->is_nv4x)
{
assert(pt->target == PIPE_TEXTURE_RECT
|| (util_is_power_of_two(pt->width0) && util_is_power_of_two(pt->height0)));
}
for (unsigned l = 0; l <= pt->last_level; l++)
{
unsigned size;
mt->level_offset[l] = offset;
if(mt->linear_pitch)
size = mt->linear_pitch;
else
size = util_format_get_stride(pt->format, u_minify(pt->width0, l));
size = util_format_get_2d_size(pt->format, size, u_minify(pt->height0, l));
if(pt->target == PIPE_TEXTURE_3D)
size *= u_minify(pt->depth0, l);
offset += size;
}
offset = align(offset, 128);
mt->face_size = offset;
if(mt->base.base.target == PIPE_TEXTURE_CUBE)
offset += 5 * mt->face_size;
return offset;
}
static void
nvfx_miptree_surface_final_destroy(struct pipe_surface* ps)
{
pipe_resource_reference(&ps->texture, 0);
FREE(ps);
}
void
nvfx_miptree_destroy(struct pipe_screen *screen, struct pipe_resource *pt)
{
struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
util_surfaces_destroy(&mt->surfaces, pt, nvfx_miptree_surface_final_destroy);
nouveau_screen_bo_release(screen, mt->base.bo);
FREE(mt);
}
static struct nvfx_miptree*
nvfx_miptree_create_skeleton(struct pipe_screen *pscreen, const struct pipe_resource *pt)
{
struct nvfx_miptree *mt;
if(pt->width0 > 4096 || pt->height0 > 4096)
return NULL;
mt = CALLOC_STRUCT(nvfx_miptree);
if (!mt)
return NULL;
mt->base.base = *pt;
pipe_reference_init(&mt->base.base.reference, 1);
mt->base.base.screen = pscreen;
// set this to the actual capabilities, we use it to decide whether to use the 3D engine for copies
// TODO: is this the correct way to use Gallium?
mt->base.base.bind = pt->bind | PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL;
// on our current driver (and the driver too), format support does not depend on geometry, so don't bother computing it
// TODO: may want to revisit this
if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_RENDER_TARGET))
mt->base.base.bind &=~ PIPE_BIND_RENDER_TARGET;
if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_SAMPLER_VIEW))
mt->base.base.bind &=~ PIPE_BIND_SAMPLER_VIEW;
if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_DEPTH_STENCIL))
mt->base.base.bind &=~ PIPE_BIND_DEPTH_STENCIL;
return mt;
}
struct pipe_resource *
nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt)
{
struct nvfx_miptree* mt = nvfx_miptree_create_skeleton(pscreen, pt);
unsigned size;
nvfx_miptree_choose_format(mt);
size = nvfx_miptree_layout(mt);
mt->base.bo = nouveau_screen_bo_new(pscreen, 256, pt->usage, pt->bind, size);
if (!mt->base.bo) {
FREE(mt);
return NULL;
}
return &mt->base.base;
}
// TODO: redo this, just calling miptree_layout
struct pipe_resource *
nvfx_miptree_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *template, struct winsys_handle *whandle)
{
struct nvfx_miptree* mt = nvfx_miptree_create_skeleton(pscreen, template);
unsigned stride;
if(whandle->stride) {
mt->linear_pitch = whandle->stride;
mt->base.base.flags |= NOUVEAU_RESOURCE_FLAG_LINEAR;
} else
nvfx_miptree_choose_format(mt);
nvfx_miptree_layout(mt);
mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
if (mt->base.bo == NULL) {
FREE(mt);
return NULL;
}
return &mt->base.base;
}
struct pipe_surface *
nvfx_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt,
const struct pipe_surface *surf_tmpl)
{
struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
unsigned level = surf_tmpl->u.tex.level;
struct nvfx_surface *ns = NULL;
assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
if(util_surfaces_get(&mt->surfaces, sizeof(struct nvfx_surface), pipe,
pt, level, surf_tmpl->u.tex.first_layer,
surf_tmpl->usage, (struct pipe_surface **)&ns)) {
ns->pitch = nvfx_subresource_pitch(pt, level);
ns->offset = nvfx_subresource_offset(pt, surf_tmpl->u.tex.first_layer, level, surf_tmpl->u.tex.first_layer);
}
return &ns->base;
}
void
nvfx_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
{
util_surfaces_detach(&((struct nvfx_miptree*)ps->texture)->surfaces, ps);
pipe_resource_reference(&ps->texture, 0);
FREE(ps);
}

View File

@ -1,431 +0,0 @@
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_split_prim.h"
#include "translate/translate.h"
#include "nvfx_context.h"
#include "nvfx_resource.h"
struct push_context {
struct nouveau_channel* chan;
struct nouveau_grobj *eng3d;
void *idxbuf;
int32_t idxbias;
float edgeflag;
int edgeflag_attr;
unsigned vertex_length;
unsigned max_vertices_per_packet;
struct translate* translate;
};
static void
emit_edgeflag(void *priv, boolean enabled)
{
struct push_context* ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
struct nouveau_channel *chan = ctx->chan;
BEGIN_RING(chan, eng3d, NV30_3D_EDGEFLAG, 1);
OUT_RING(chan, enabled ? 1 : 0);
}
static void
emit_vertices_lookup8(void *priv, unsigned start, unsigned count)
{
struct push_context *ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
uint8_t* elts = (uint8_t*)ctx->idxbuf + start;
while(count)
{
unsigned push = MIN2(count, ctx->max_vertices_per_packet);
unsigned length = push * ctx->vertex_length;
BEGIN_RING_NI(ctx->chan, eng3d, NV30_3D_VERTEX_DATA, length);
ctx->translate->run_elts8(ctx->translate, elts, push, 0, ctx->chan->cur);
ctx->chan->cur += length;
count -= push;
elts += push;
}
}
static void
emit_vertices_lookup16(void *priv, unsigned start, unsigned count)
{
struct push_context *ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
uint16_t* elts = (uint16_t*)ctx->idxbuf + start;
while(count)
{
unsigned push = MIN2(count, ctx->max_vertices_per_packet);
unsigned length = push * ctx->vertex_length;
BEGIN_RING_NI(ctx->chan, eng3d, NV30_3D_VERTEX_DATA, length);
ctx->translate->run_elts16(ctx->translate, elts, push, 0, ctx->chan->cur);
ctx->chan->cur += length;
count -= push;
elts += push;
}
}
static void
emit_vertices_lookup32(void *priv, unsigned start, unsigned count)
{
struct push_context *ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
uint32_t* elts = (uint32_t*)ctx->idxbuf + start;
while(count)
{
unsigned push = MIN2(count, ctx->max_vertices_per_packet);
unsigned length = push * ctx->vertex_length;
BEGIN_RING_NI(ctx->chan, eng3d, NV30_3D_VERTEX_DATA, length);
ctx->translate->run_elts(ctx->translate, elts, push, 0, ctx->chan->cur);
ctx->chan->cur += length;
count -= push;
elts += push;
}
}
static void
emit_vertices(void *priv, unsigned start, unsigned count)
{
struct push_context *ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
while(count)
{
unsigned push = MIN2(count, ctx->max_vertices_per_packet);
unsigned length = push * ctx->vertex_length;
BEGIN_RING_NI(ctx->chan, eng3d, NV30_3D_VERTEX_DATA, length);
ctx->translate->run(ctx->translate, start, push, 0, ctx->chan->cur);
ctx->chan->cur += length;
count -= push;
start += push;
}
}
static void
emit_ranges(void* priv, unsigned start, unsigned vc, unsigned reg)
{
struct push_context* ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
struct nouveau_channel *chan = ctx->chan;
unsigned nr = (vc & 0xff);
if (nr) {
BEGIN_RING(chan, eng3d, reg, 1);
OUT_RING (chan, ((nr - 1) << 24) | start);
start += nr;
}
nr = vc >> 8;
while (nr) {
unsigned push = nr > 2047 ? 2047 : nr;
nr -= push;
BEGIN_RING_NI(chan, eng3d, reg, push);
while (push--) {
OUT_RING(chan, ((0x100 - 1) << 24) | start);
start += 0x100;
}
}
}
static void
emit_ib_ranges(void* priv, unsigned start, unsigned vc)
{
emit_ranges(priv, start, vc, NV30_3D_VB_INDEX_BATCH);
}
static void
emit_vb_ranges(void* priv, unsigned start, unsigned vc)
{
emit_ranges(priv, start, vc, NV30_3D_VB_VERTEX_BATCH);
}
static INLINE void
emit_elt8(void* priv, unsigned start, unsigned vc)
{
struct push_context* ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
struct nouveau_channel *chan = ctx->chan;
uint8_t *elts = (uint8_t *)ctx->idxbuf + start;
int idxbias = ctx->idxbias;
if (vc & 1) {
BEGIN_RING(chan, eng3d, NV30_3D_VB_ELEMENT_U32, 1);
OUT_RING (chan, elts[0]);
elts++; vc--;
}
while (vc) {
unsigned i;
unsigned push = MIN2(vc, 2047 * 2);
BEGIN_RING_NI(chan, eng3d, NV30_3D_VB_ELEMENT_U16, push >> 1);
for (i = 0; i < push; i+=2)
OUT_RING(chan, ((elts[i+1] + idxbias) << 16) | (elts[i] + idxbias));
vc -= push;
elts += push;
}
}
static INLINE void
emit_elt16(void* priv, unsigned start, unsigned vc)
{
struct push_context* ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
struct nouveau_channel *chan = ctx->chan;
uint16_t *elts = (uint16_t *)ctx->idxbuf + start;
int idxbias = ctx->idxbias;
if (vc & 1) {
BEGIN_RING(chan, eng3d, NV30_3D_VB_ELEMENT_U32, 1);
OUT_RING (chan, elts[0]);
elts++; vc--;
}
while (vc) {
unsigned i;
unsigned push = MIN2(vc, 2047 * 2);
BEGIN_RING_NI(chan, eng3d, NV30_3D_VB_ELEMENT_U16, push >> 1);
for (i = 0; i < push; i+=2)
OUT_RING(chan, ((elts[i+1] + idxbias) << 16) | (elts[i] + idxbias));
vc -= push;
elts += push;
}
}
static INLINE void
emit_elt32(void* priv, unsigned start, unsigned vc)
{
struct push_context* ctx = priv;
struct nouveau_grobj *eng3d = ctx->eng3d;
struct nouveau_channel *chan = ctx->chan;
uint32_t *elts = (uint32_t *)ctx->idxbuf + start;
int idxbias = ctx->idxbias;
while (vc) {
unsigned push = MIN2(vc, 2047);
BEGIN_RING_NI(chan, eng3d, NV30_3D_VB_ELEMENT_U32, push);
if(idxbias)
{
for(unsigned i = 0; i < push; ++i)
OUT_RING(chan, elts[i] + idxbias);
}
else
OUT_RINGp(chan, elts, push);
vc -= push;
elts += push;
}
}
void
nvfx_push_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
struct push_context ctx;
struct util_split_prim s;
unsigned instances_left = info->instance_count;
int vtx_value;
unsigned hw_mode = nvgl_primitive(info->mode);
int i;
struct
{
uint8_t* map;
unsigned step;
} per_instance[16];
unsigned p_overhead = 64 /* magic fix */
+ 4 /* begin/end */
+ 4; /* potential edgeflag enable/disable */
ctx.chan = nvfx->screen->base.channel;
ctx.eng3d = nvfx->screen->eng3d;
ctx.translate = nvfx->vtxelt->translate;
ctx.idxbuf = NULL;
ctx.vertex_length = nvfx->vtxelt->vertex_length;
ctx.max_vertices_per_packet = nvfx->vtxelt->max_vertices_per_packet;
ctx.edgeflag = 0.5f;
// TODO: figure out if we really want to handle this, and do so in that case
ctx.edgeflag_attr = 0xff; // nvfx->vertprog->cfg.edgeflag_in;
if(!nvfx->use_vertex_buffers)
{
for(i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; ++i)
{
struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
uint8_t* data = nvfx_buffer(vb->buffer)->data + vb->buffer_offset;
if(info->indexed)
data += info->index_bias * vb->stride;
ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
}
if(ctx.edgeflag_attr < 16)
vtx_value = -(ctx.vertex_length + 3); /* vertex data and edgeflag header and value */
else
{
p_overhead += 1; /* initial vertex_data header */
vtx_value = -ctx.vertex_length; /* vertex data and edgeflag header and value */
}
if (info->indexed) {
// XXX: this case and is broken and probably need a new VTX_ATTR push path
if (nvfx->idxbuf.index_size == 1)
s.emit = emit_vertices_lookup8;
else if (nvfx->idxbuf.index_size == 2)
s.emit = emit_vertices_lookup16;
else
s.emit = emit_vertices_lookup32;
} else
s.emit = emit_vertices;
}
else
{
if(!info->indexed || nvfx->use_index_buffer)
{
s.emit = info->indexed ? emit_ib_ranges : emit_vb_ranges;
p_overhead += 3;
vtx_value = 0;
}
else if (nvfx->idxbuf.index_size == 4)
{
s.emit = emit_elt32;
p_overhead += 1;
vtx_value = 8;
}
else
{
s.emit = (nvfx->idxbuf.index_size == 2) ? emit_elt16 : emit_elt8;
p_overhead += 3;
vtx_value = 7;
}
}
ctx.idxbias = info->index_bias;
if(nvfx->use_vertex_buffers)
ctx.idxbias -= nvfx->base_vertex;
/* map index buffer, if present */
if (info->indexed && !nvfx->use_index_buffer)
ctx.idxbuf = nvfx_buffer(nvfx->idxbuf.buffer)->data + nvfx->idxbuf.offset;
s.priv = &ctx;
s.edge = emit_edgeflag;
for (i = 0; i < nvfx->vtxelt->num_per_instance; ++i)
{
struct nvfx_per_instance_element *ve = &nvfx->vtxelt->per_instance[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->base.vertex_buffer_index];
float v[4];
per_instance[i].step = info->start_instance % ve->instance_divisor;
per_instance[i].map = nvfx_buffer(vb->buffer)->data + vb->buffer_offset + ve->base.src_offset;
nvfx->vtxelt->per_instance[i].base.fetch_rgba_float(v, per_instance[i].map, 0, 0);
nvfx_emit_vtx_attr(chan, eng3d,
nvfx->vtxelt->per_instance[i].base.idx, v,
nvfx->vtxelt->per_instance[i].base.ncomp);
}
/* per-instance loop */
while (instances_left--) {
int max_verts;
boolean done;
util_split_prim_init(&s, info->mode, info->start, info->count);
nvfx_state_emit(nvfx);
for(;;) {
max_verts = AVAIL_RING(chan);
max_verts -= p_overhead;
/* if vtx_value < 0, each vertex is -vtx_value words long
* otherwise, each vertex is 2^(vtx_value) / 255 words long (this is an approximation)
*/
if(vtx_value < 0)
{
max_verts /= -vtx_value;
max_verts -= (max_verts >> 10); /* vertex data headers */
}
else
{
if(max_verts >= (1 << 23)) /* avoid overflow here */
max_verts = (1 << 23);
max_verts = (max_verts * 255) >> vtx_value;
}
//printf("avail %u max_verts %u\n", AVAIL_RING(chan), max_verts);
if(max_verts >= 16)
{
/* XXX: any command a lot of times seems to (mostly) fix corruption that would otherwise happen */
/* this seems to cause issues on nv3x, and also be unneeded there */
if(nvfx->is_nv4x)
{
int i;
for(i = 0; i < 32; ++i)
{
BEGIN_RING(chan, eng3d,
0x1dac, 1);
OUT_RING(chan, 0);
}
}
BEGIN_RING(chan, eng3d,
NV30_3D_VERTEX_BEGIN_END, 1);
OUT_RING(chan, hw_mode);
done = util_split_prim_next(&s, max_verts);
BEGIN_RING(chan, eng3d,
NV30_3D_VERTEX_BEGIN_END, 1);
OUT_RING(chan, 0);
if(done)
break;
}
FIRE_RING(chan);
nvfx_state_emit(nvfx);
}
/* set data for the next instance, if any changed */
for (i = 0; i < nvfx->vtxelt->num_per_instance; ++i)
{
struct nvfx_per_instance_element *ve = &nvfx->vtxelt->per_instance[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->base.vertex_buffer_index];
if(++per_instance[i].step == ve->instance_divisor)
{
float v[4];
per_instance[i].map += vb->stride;
per_instance[i].step = 0;
nvfx->vtxelt->per_instance[i].base.fetch_rgba_float(v, per_instance[i].map, 0, 0);
nvfx_emit_vtx_attr(chan, eng3d,
nvfx->vtxelt->per_instance[i].base.idx,
v,
nvfx->vtxelt->per_instance[i].base.ncomp);
}
}
}
}

View File

@ -1,147 +0,0 @@
#include "pipe/p_context.h"
#include "nvfx_context.h"
struct nvfx_query {
struct list_head list;
struct nouveau_resource *object;
unsigned type;
boolean ready;
uint64_t result;
};
static INLINE struct nvfx_query *
nvfx_query(struct pipe_query *pipe)
{
return (struct nvfx_query *)pipe;
}
static struct pipe_query *
nvfx_query_create(struct pipe_context *pipe, unsigned query_type)
{
struct nvfx_query *q;
q = CALLOC(1, sizeof(struct nvfx_query));
q->type = query_type;
assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
return (struct pipe_query *)q;
}
static void
nvfx_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
{
struct nvfx_query *q = nvfx_query(pq);
if (q->object)
{
nouveau_resource_free(&q->object);
LIST_DEL(&q->list);
}
FREE(q);
}
static void
nvfx_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nvfx_query *q = nvfx_query(pq);
struct nvfx_screen *screen = nvfx->screen;
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *eng3d = screen->eng3d;
uint64_t tmp;
assert(!nvfx->query);
/* Happens when end_query() is called, then another begin_query()
* without querying the result in-between. For now we'll wait for
* the existing query to notify completion, but it could be better.
*/
if (q->object)
pipe->get_query_result(pipe, pq, 1, (void*)&tmp);
while (nouveau_resource_alloc(nvfx->screen->query_heap, 1, NULL, &q->object))
{
struct nvfx_query* oldestq;
assert(!LIST_IS_EMPTY(&nvfx->screen->query_list));
oldestq = LIST_ENTRY(struct nvfx_query, nvfx->screen->query_list.next, list);
pipe->get_query_result(pipe, (struct pipe_query*)oldestq, 1, (void*)&tmp);
}
LIST_ADDTAIL(&q->list, &nvfx->screen->query_list);
nouveau_notifier_reset(nvfx->screen->query, q->object->start);
BEGIN_RING(chan, eng3d, NV30_3D_QUERY_RESET, 1);
OUT_RING(chan, 1);
BEGIN_RING(chan, eng3d, NV30_3D_QUERY_ENABLE, 1);
OUT_RING(chan, 1);
q->ready = FALSE;
nvfx->query = pq;
}
static void
nvfx_query_end(struct pipe_context *pipe, struct pipe_query *pq)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
struct nvfx_query *q = nvfx_query(pq);
assert(nvfx->query == pq);
BEGIN_RING(chan, eng3d, NV30_3D_QUERY_GET, 1);
OUT_RING (chan, (0x01 << NV30_3D_QUERY_GET_UNK24__SHIFT) |
((q->object->start * 32) << NV30_3D_QUERY_GET_OFFSET__SHIFT));
BEGIN_RING(chan, eng3d, NV30_3D_QUERY_ENABLE, 1);
OUT_RING(chan, 0);
FIRE_RING(chan);
nvfx->query = 0;
}
static boolean
nvfx_query_result(struct pipe_context *pipe, struct pipe_query *pq,
boolean wait, union pipe_query_result *vresult)
{
uint64_t *result = (uint64_t *)vresult;
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nvfx_query *q = nvfx_query(pq);
if (!q->ready) {
unsigned status;
status = nouveau_notifier_status(nvfx->screen->query,
q->object->start);
if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) {
if (wait == FALSE)
return FALSE;
nouveau_notifier_wait_status(nvfx->screen->query,
q->object->start,
NV_NOTIFY_STATE_STATUS_COMPLETED, 0);
}
q->result = nouveau_notifier_return_val(nvfx->screen->query,
q->object->start);
q->ready = TRUE;
nouveau_resource_free(&q->object);
LIST_DEL(&q->list);
}
*result = q->result;
return TRUE;
}
void
nvfx_init_query_functions(struct nvfx_context *nvfx)
{
nvfx->pipe.create_query = nvfx_query_create;
nvfx->pipe.destroy_query = nvfx_query_destroy;
nvfx->pipe.begin_query = nvfx_query_begin;
nvfx->pipe.end_query = nvfx_query_end;
nvfx->pipe.get_query_result = nvfx_query_result;
}

View File

@ -1,66 +0,0 @@
#include "pipe/p_context.h"
#include "util/u_staging.h"
#include "nvfx_resource.h"
#include "nouveau/nouveau_screen.h"
static struct pipe_resource *
nvfx_resource_create(struct pipe_screen *screen,
const struct pipe_resource *template)
{
if (template->target == PIPE_BUFFER)
return nvfx_buffer_create(screen, template);
else
return nvfx_miptree_create(screen, template);
}
static void
nvfx_resource_destroy(struct pipe_screen *screen, struct pipe_resource *pr)
{
if (pr->target == PIPE_BUFFER)
return nvfx_buffer_destroy(screen, pr);
else
return nvfx_miptree_destroy(screen, pr);
}
static struct pipe_resource *
nvfx_resource_from_handle(struct pipe_screen * screen,
const struct pipe_resource *template,
struct winsys_handle *whandle)
{
if (template->target == PIPE_BUFFER)
return NULL;
else
return nvfx_miptree_from_handle(screen, template, whandle);
}
static boolean
nvfx_resource_get_handle(struct pipe_screen *pscreen,
struct pipe_resource *pr,
struct winsys_handle *whandle)
{
struct nvfx_resource* res = (struct nvfx_resource*)pr;
if (!res || !res->bo)
return FALSE;
return nouveau_screen_bo_get_handle(pscreen, res->bo, nvfx_subresource_pitch(pr, 0), whandle);
}
void
nvfx_init_resource_functions(struct pipe_context *pipe)
{
pipe->create_surface = nvfx_miptree_surface_new;
pipe->surface_destroy = nvfx_miptree_surface_del;
}
void
nvfx_screen_init_resource_functions(struct pipe_screen *pscreen)
{
pscreen->resource_create = nvfx_resource_create;
pscreen->resource_from_handle = nvfx_resource_from_handle;
pscreen->resource_get_handle = nvfx_resource_get_handle;
pscreen->resource_destroy = nvfx_resource_destroy;
pscreen->user_buffer_create = nvfx_user_buffer_create;
}

View File

@ -1,194 +0,0 @@
#ifndef NVFX_RESOURCE_H
#define NVFX_RESOURCE_H
#include "util/u_transfer.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_double_list.h"
#include "util/u_surfaces.h"
#include "util/u_dirty_surfaces.h"
#include <nouveau/nouveau_bo.h>
struct pipe_resource;
struct nv04_region;
struct nvfx_resource {
struct pipe_resource base;
struct nouveau_bo *bo;
};
static INLINE
struct nvfx_resource *nvfx_resource(struct pipe_resource *resource)
{
return (struct nvfx_resource *)resource;
}
#define NVFX_RESOURCE_FLAG_USER (NOUVEAU_RESOURCE_FLAG_DRV_PRIV << 0)
/* is resource mapped into the GPU's address space (i.e. VRAM or GART) ? */
static INLINE boolean
nvfx_resource_mapped_by_gpu(struct pipe_resource *resource)
{
return nvfx_resource(resource)->bo->handle;
}
/* is resource in VRAM? */
static inline int
nvfx_resource_on_gpu(struct pipe_resource* pr)
{
#if 0
// a compiler error here means you need to apply libdrm-nouveau-add-domain.patch to libdrm
// TODO: return FALSE if not VRAM and on a PCI-E system
return ((struct nvfx_resource*)pr)->bo->domain & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART);
#else
return TRUE;
#endif
}
#define NVFX_MAX_TEXTURE_LEVELS 16
struct nvfx_miptree {
struct nvfx_resource base;
unsigned linear_pitch; /* for linear textures, 0 for swizzled and compressed textures with level-dependent minimal pitch */
unsigned face_size; /* 128-byte aligned face/total size */
unsigned level_offset[NVFX_MAX_TEXTURE_LEVELS];
struct util_surfaces surfaces;
};
struct nvfx_surface {
struct pipe_surface base;
unsigned pitch;
unsigned offset;
};
static INLINE struct nouveau_bo *
nvfx_surface_buffer(struct pipe_surface *surf)
{
struct nvfx_resource *mt = nvfx_resource(surf->texture);
return mt->bo;
}
void
nvfx_init_resource_functions(struct pipe_context *pipe);
void
nvfx_screen_init_resource_functions(struct pipe_screen *pscreen);
/* Internal:
*/
struct pipe_resource *
nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt);
void
nvfx_miptree_destroy(struct pipe_screen *pscreen,
struct pipe_resource *presource);
struct pipe_resource *
nvfx_miptree_from_handle(struct pipe_screen *pscreen,
const struct pipe_resource *template,
struct winsys_handle *whandle);
void
nvfx_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps);
struct pipe_surface *
nvfx_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt,
const struct pipe_surface *surf_tmpl);
/* only for miptrees, don't use for buffers */
/* NOTE: for swizzled 3D textures, this just returns the offset of the mipmap level */
static inline unsigned
nvfx_subresource_offset(struct pipe_resource* pt, unsigned face, unsigned level, unsigned zslice)
{
if(pt->target == PIPE_BUFFER)
return 0;
else
{
struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
unsigned offset = mt->level_offset[level];
if (pt->target == PIPE_TEXTURE_CUBE)
offset += mt->face_size * face;
else if (pt->target == PIPE_TEXTURE_3D && mt->linear_pitch)
offset += zslice * util_format_get_2d_size(pt->format, (mt->linear_pitch ? mt->linear_pitch : util_format_get_stride(pt->format, u_minify(pt->width0, level))), u_minify(pt->height0, level));
return offset;
}
}
static inline unsigned
nvfx_subresource_pitch(struct pipe_resource* pt, unsigned level)
{
if(pt->target == PIPE_BUFFER)
return ((struct nvfx_resource*)pt)->bo->size;
else
{
struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
if(mt->linear_pitch)
return mt->linear_pitch;
else
return util_format_get_stride(pt->format, u_minify(pt->width0, level));
}
}
struct nvfx_buffer
{
struct nvfx_resource base;
uint8_t* data;
unsigned size;
/* the range of data not yet uploaded to the GPU bo */
unsigned dirty_begin;
unsigned dirty_end;
/* whether all transfers were unsynchronized */
boolean dirty_unsynchronized;
/* whether it would have been profitable to upload
* the latest updated data to the GPU immediately */
boolean last_update_static;
/* how many bytes we need to draw before we deem
* the buffer to be static
*/
long long bytes_to_draw_until_static;
};
static inline struct nvfx_buffer* nvfx_buffer(struct pipe_resource* pr)
{
return (struct nvfx_buffer*)pr;
}
/* this is an heuristic to determine whether we are better off uploading the
* buffer to the GPU, or just continuing pushing it on the FIFO
*/
static inline boolean nvfx_buffer_seems_static(struct nvfx_buffer* buffer)
{
return buffer->last_update_static
|| buffer->bytes_to_draw_until_static < 0;
}
struct pipe_resource *
nvfx_buffer_create(struct pipe_screen *pscreen,
const struct pipe_resource *template);
void
nvfx_buffer_destroy(struct pipe_screen *pscreen,
struct pipe_resource *presource);
struct pipe_resource *
nvfx_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes,
unsigned usage);
void
nvfx_buffer_upload(struct nvfx_buffer* buffer);
#endif

View File

@ -1,665 +0,0 @@
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
#include "util/u_format.h"
#include "util/u_format_s3tc.h"
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
#include "nouveau/nouveau_screen.h"
#include "nouveau/nv_object.xml.h"
#include "nvfx_context.h"
#include "nvfx_screen.h"
#include "nvfx_resource.h"
#include "nvfx_tex.h"
#define NV30_3D_CHIPSET_3X_MASK 0x00000003
#define NV34_3D_CHIPSET_3X_MASK 0x00000010
#define NV35_3D_CHIPSET_3X_MASK 0x000001e0
#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf
#define NV4X_GRCLASS4497_CHIPSETS 0x00005450
#define NV6X_GRCLASS4497_CHIPSETS 0x00000088
static int
nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
{
struct nvfx_screen *screen = nvfx_screen(pscreen);
switch (param) {
case PIPE_CAP_NPOT_TEXTURES:
return screen->advertise_npot;
case PIPE_CAP_TWO_SIDED_STENCIL:
return 1;
case PIPE_CAP_SM3:
/* TODO: >= nv4x support Shader Model 3.0 */
return 0;
case PIPE_CAP_GLSL_FEATURE_LEVEL:
return 120;
case PIPE_CAP_ANISOTROPIC_FILTER:
return 1;
case PIPE_CAP_POINT_SPRITE:
return 1;
case PIPE_CAP_MAX_RENDER_TARGETS:
return screen->use_nv4x ? 4 : 1;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_TIMER_QUERY:
return 0;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_TEXTURE_SWIZZLE:
return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
return 13;
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
return 10;
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
return 13;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return !!screen->use_nv4x;
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
return screen->advertise_blend_equation_separate;
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
return 16;
case PIPE_CAP_INDEP_BLEND_ENABLE:
/* TODO: on nv40 we have separate color masks */
/* TODO: nv40 mrt blending is probably broken */
return 0;
case PIPE_CAP_INDEP_BLEND_FUNC:
return 0;
case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
return 0;
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
case PIPE_CAP_VERTEX_COLOR_CLAMPED:
return 1;
case PIPE_CAP_DEPTH_CLIP_DISABLE:
return 0; // TODO: implement depth clamp
case PIPE_CAP_PRIMITIVE_RESTART:
return 0; // TODO: implement primitive restart
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
case PIPE_CAP_TGSI_INSTANCEID:
case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
case PIPE_CAP_SEAMLESS_CUBE_MAP:
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
case PIPE_CAP_SHADER_STENCIL_EXPORT:
case PIPE_CAP_MIN_TEXEL_OFFSET:
case PIPE_CAP_MAX_TEXEL_OFFSET:
case PIPE_CAP_CONDITIONAL_RENDER:
case PIPE_CAP_TEXTURE_BARRIER:
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
return 0;
default:
NOUVEAU_ERR("Warning: unknown PIPE_CAP %d\n", param);
return 0;
}
}
static int
nvfx_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, enum pipe_shader_cap param)
{
struct nvfx_screen *screen = nvfx_screen(pscreen);
switch(shader) {
case PIPE_SHADER_FRAGMENT:
switch(param) {
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
return 4096;
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
/* FIXME: is it the dynamic (nv30:0/nv40:24) or the static
value (nv30:0/nv40:4) ? */
return screen->use_nv4x ? 4 : 0;
case PIPE_SHADER_CAP_MAX_INPUTS:
return screen->use_nv4x ? 12 : 10;
case PIPE_SHADER_CAP_MAX_CONSTS:
return screen->use_nv4x ? 224 : 32;
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
return 1;
case PIPE_SHADER_CAP_MAX_TEMPS:
return 32;
case PIPE_SHADER_CAP_MAX_ADDRS:
return screen->use_nv4x ? 1 : 0;
case PIPE_SHADER_CAP_MAX_PREDS:
return 0; /* we could expose these, but nothing uses them */
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
return 0;
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
return 0;
case PIPE_SHADER_CAP_SUBROUTINES:
return screen->use_nv4x ? 1 : 0;
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
return 16;
default:
break;
}
break;
case PIPE_SHADER_VERTEX:
switch(param) {
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
return screen->use_nv4x ? 512 : 256;
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
return screen->use_nv4x ? 512 : 0;
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
/* FIXME: is it the dynamic (nv30:24/nv40:24) or the static
value (nv30:1/nv40:4) ? */
return screen->use_nv4x ? 4 : 1;
case PIPE_SHADER_CAP_MAX_INPUTS:
return 16;
case PIPE_SHADER_CAP_MAX_CONSTS:
/* - 6 is for clip planes; Gallium should be fixed to put
* them in the vertex shader itself, so we don't need to reserve these */
return (screen->use_nv4x ? 468 : 256) - 6;
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
return 1;
case PIPE_SHADER_CAP_MAX_TEMPS:
return screen->use_nv4x ? 32 : 13;
case PIPE_SHADER_CAP_MAX_ADDRS:
return 2;
case PIPE_SHADER_CAP_MAX_PREDS:
return 0; /* we could expose these, but nothing uses them */
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
return 1;
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
return 0;
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
return 1;
case PIPE_SHADER_CAP_SUBROUTINES:
return 1;
case PIPE_SHADER_CAP_INTEGERS:
return 0;
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
return 0; /* We have 4 on nv40 - but unsupported currently */
default:
break;
}
break;
default:
break;
}
return 0;
}
static float
nvfx_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
{
struct nvfx_screen *screen = nvfx_screen(pscreen);
switch (param) {
case PIPE_CAPF_MAX_LINE_WIDTH:
case PIPE_CAPF_MAX_LINE_WIDTH_AA:
return 10.0;
case PIPE_CAPF_MAX_POINT_WIDTH:
case PIPE_CAPF_MAX_POINT_WIDTH_AA:
return 64.0;
case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
return screen->use_nv4x ? 16.0 : 8.0;
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
return 15.0;
default:
NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
return 0.0;
}
}
static int
nvfx_screen_get_video_param(struct pipe_screen *screen,
enum pipe_video_profile profile,
enum pipe_video_cap param)
{
switch (param) {
case PIPE_VIDEO_CAP_SUPPORTED:
return vl_profile_supported(screen, profile);
case PIPE_VIDEO_CAP_NPOT_TEXTURES:
return 0;
case PIPE_VIDEO_CAP_MAX_WIDTH:
case PIPE_VIDEO_CAP_MAX_HEIGHT:
return vl_video_buffer_max_size(screen);
case PIPE_VIDEO_CAP_PREFERED_FORMAT:
return PIPE_FORMAT_NV12;
case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
return false;
case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
return false;
case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
return true;
default:
return 0;
}
}
static boolean
nvfx_screen_is_format_supported(struct pipe_screen *pscreen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned bind)
{
struct nvfx_screen *screen = nvfx_screen(pscreen);
if (!util_format_is_supported(format, bind))
return FALSE;
if (sample_count > 1)
return FALSE;
if (bind & PIPE_BIND_RENDER_TARGET) {
switch (format) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
case PIPE_FORMAT_B8G8R8X8_UNORM:
case PIPE_FORMAT_R8G8B8A8_UNORM:
case PIPE_FORMAT_R8G8B8X8_UNORM:
case PIPE_FORMAT_B5G6R5_UNORM:
break;
case PIPE_FORMAT_R16G16B16A16_FLOAT:
if(!screen->advertise_fp16)
return FALSE;
break;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
if(!screen->advertise_fp32)
return FALSE;
break;
default:
return FALSE;
}
}
if (bind & PIPE_BIND_DEPTH_STENCIL) {
switch (format) {
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_Z16_UNORM:
break;
default:
return FALSE;
}
}
if (bind & PIPE_BIND_SAMPLER_VIEW) {
struct nvfx_texture_format* tf = &nvfx_texture_formats[format];
if(util_format_is_s3tc(format) && !util_format_s3tc_enabled)
return FALSE;
if(format == PIPE_FORMAT_R16G16B16A16_FLOAT && !screen->advertise_fp16)
return FALSE;
if(format == PIPE_FORMAT_R32G32B32A32_FLOAT && !screen->advertise_fp32)
return FALSE;
if(screen->use_nv4x)
{
if(tf->fmt[4] < 0)
return FALSE;
}
else
{
if(tf->fmt[0] < 0)
return FALSE;
}
}
// note that we do actually support everything through translate
if (bind & PIPE_BIND_VERTEX_BUFFER) {
unsigned type = nvfx_vertex_formats[format];
if(!type)
return FALSE;
}
if (bind & PIPE_BIND_INDEX_BUFFER) {
// 8-bit indices supported, but not in hardware index buffer
if(format != PIPE_FORMAT_R16_USCALED && format != PIPE_FORMAT_R32_USCALED)
return FALSE;
}
if(bind & PIPE_BIND_STREAM_OUTPUT)
return FALSE;
return TRUE;
}
static void
nvfx_screen_destroy(struct pipe_screen *pscreen)
{
struct nvfx_screen *screen = nvfx_screen(pscreen);
nouveau_resource_destroy(&screen->vp_exec_heap);
nouveau_resource_destroy(&screen->vp_data_heap);
nouveau_resource_destroy(&screen->query_heap);
nouveau_notifier_free(&screen->query);
nouveau_notifier_free(&screen->sync);
nouveau_grobj_free(&screen->eng3d);
nvfx_screen_surface_takedown(pscreen);
nouveau_bo_ref(NULL, &screen->fence);
nouveau_screen_fini(&screen->base);
FREE(pscreen);
}
static void nv30_screen_init(struct nvfx_screen *screen)
{
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *eng3d = screen->eng3d;
int i;
/* TODO: perhaps we should do some of this on nv40 too? */
for (i=1; i<8; i++) {
BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_CLIP_HORIZ(i), 1);
OUT_RING(chan, 0);
BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_CLIP_VERT(i), 1);
OUT_RING(chan, 0);
}
BEGIN_RING(chan, eng3d, 0x220, 1);
OUT_RING(chan, 1);
BEGIN_RING(chan, eng3d, 0x03b0, 1);
OUT_RING(chan, 0x00100000);
BEGIN_RING(chan, eng3d, 0x1454, 1);
OUT_RING(chan, 0);
BEGIN_RING(chan, eng3d, 0x1d80, 1);
OUT_RING(chan, 3);
BEGIN_RING(chan, eng3d, 0x1450, 1);
OUT_RING(chan, 0x00030004);
/* NEW */
BEGIN_RING(chan, eng3d, 0x1e98, 1);
OUT_RING(chan, 0);
BEGIN_RING(chan, eng3d, 0x17e0, 3);
OUT_RING(chan, fui(0.0));
OUT_RING(chan, fui(0.0));
OUT_RING(chan, fui(1.0));
BEGIN_RING(chan, eng3d, 0x1f80, 16);
for (i=0; i<16; i++) {
OUT_RING(chan, (i==8) ? 0x0000ffff : 0);
}
BEGIN_RING(chan, eng3d, 0x120, 3);
OUT_RING(chan, 0);
OUT_RING(chan, 1);
OUT_RING(chan, 2);
BEGIN_RING(chan, eng3d, 0x1d88, 1);
OUT_RING(chan, 0x00001200);
BEGIN_RING(chan, eng3d, NV30_3D_RC_ENABLE, 1);
OUT_RING(chan, 0);
BEGIN_RING(chan, eng3d, NV30_3D_DEPTH_RANGE_NEAR, 2);
OUT_RING(chan, fui(0.0));
OUT_RING(chan, fui(1.0));
BEGIN_RING(chan, eng3d, NV30_3D_MULTISAMPLE_CONTROL, 1);
OUT_RING(chan, 0xffff0000);
/* enables use of vp rather than fixed-function somehow */
BEGIN_RING(chan, eng3d, 0x1e94, 1);
OUT_RING(chan, 0x13);
}
static void nv40_screen_init(struct nvfx_screen *screen)
{
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *eng3d = screen->eng3d;
BEGIN_RING(chan, eng3d, NV40_3D_DMA_COLOR2, 2);
OUT_RING(chan, screen->base.channel->vram->handle);
OUT_RING(chan, screen->base.channel->vram->handle);
BEGIN_RING(chan, eng3d, 0x1450, 1);
OUT_RING(chan, 0x00000004);
BEGIN_RING(chan, eng3d, 0x1ea4, 3);
OUT_RING(chan, 0x00000010);
OUT_RING(chan, 0x01000100);
OUT_RING(chan, 0xff800006);
/* vtxprog output routing */
BEGIN_RING(chan, eng3d, 0x1fc4, 1);
OUT_RING(chan, 0x06144321);
BEGIN_RING(chan, eng3d, 0x1fc8, 2);
OUT_RING(chan, 0xedcba987);
OUT_RING(chan, 0x0000006f);
BEGIN_RING(chan, eng3d, 0x1fd0, 1);
OUT_RING(chan, 0x00171615);
BEGIN_RING(chan, eng3d, 0x1fd4, 1);
OUT_RING(chan, 0x001b1a19);
BEGIN_RING(chan, eng3d, 0x1ef8, 1);
OUT_RING(chan, 0x0020ffff);
BEGIN_RING(chan, eng3d, 0x1d64, 1);
OUT_RING(chan, 0x01d300d4);
BEGIN_RING(chan, eng3d, 0x1e94, 1);
OUT_RING(chan, 0x00000001);
BEGIN_RING(chan, eng3d, NV40_3D_MIPMAP_ROUNDING, 1);
OUT_RING(chan, NV40_3D_MIPMAP_ROUNDING_MODE_DOWN);
}
static unsigned
nvfx_screen_get_vertex_buffer_flags(struct nvfx_screen* screen)
{
int vram_hack_default = 0;
int vram_hack;
// TODO: this is a bit of a guess; also add other cards that may need this hack.
// It may also depend on the specific card or the AGP/PCIe chipset.
if(screen->base.device->chipset == 0x47 /* G70 */
|| screen->base.device->chipset == 0x49 /* G71 */
|| screen->base.device->chipset == 0x46 /* G72 */
)
vram_hack_default = 1;
vram_hack = debug_get_bool_option("NOUVEAU_VTXIDX_IN_VRAM", vram_hack_default);
return vram_hack ? NOUVEAU_BO_VRAM : NOUVEAU_BO_GART;
}
static void nvfx_channel_flush_notify(struct nouveau_channel* chan)
{
struct nvfx_screen* screen = chan->user_private;
struct nvfx_context* nvfx = screen->cur_ctx;
if(nvfx)
nvfx->relocs_needed = NVFX_RELOCATE_ALL;
}
struct pipe_screen *
nvfx_screen_create(struct nouveau_device *dev)
{
static const unsigned query_sizes[] = {(4096 - 4 * 32) / 32, 3 * 1024 / 32, 2 * 1024 / 32, 1024 / 32};
struct nvfx_screen *screen = CALLOC_STRUCT(nvfx_screen);
struct nouveau_channel *chan;
struct pipe_screen *pscreen;
unsigned eng3d_class = 0;
int ret, i;
if (!screen)
return NULL;
pscreen = &screen->base.base;
ret = nouveau_screen_init(&screen->base, dev);
if (ret) {
nvfx_screen_destroy(pscreen);
return NULL;
}
chan = screen->base.channel;
screen->cur_ctx = NULL;
chan->user_private = screen;
chan->flush_notify = nvfx_channel_flush_notify;
pscreen->destroy = nvfx_screen_destroy;
pscreen->get_param = nvfx_screen_get_param;
pscreen->get_shader_param = nvfx_screen_get_shader_param;
pscreen->get_paramf = nvfx_screen_get_paramf;
pscreen->get_video_param = nvfx_screen_get_video_param;
pscreen->is_format_supported = nvfx_screen_is_format_supported;
pscreen->is_video_format_supported = vl_video_buffer_is_format_supported;
pscreen->context_create = nvfx_create;
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 4096, &screen->fence);
if (ret) {
nvfx_screen_destroy(pscreen);
return NULL;
}
switch (dev->chipset & 0xf0) {
case 0x30:
if (NV30_3D_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
eng3d_class = NV30_3D;
else if (NV34_3D_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
eng3d_class = NV34_3D;
else if (NV35_3D_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
eng3d_class = NV35_3D;
break;
case 0x40:
if (NV4X_GRCLASS4097_CHIPSETS & (1 << (dev->chipset & 0x0f)))
eng3d_class = NV40_3D;
else if (NV4X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f)))
eng3d_class = NV44_3D;
screen->is_nv4x = ~0;
break;
case 0x60:
if (NV6X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f)))
eng3d_class = NV44_3D;
screen->is_nv4x = ~0;
break;
}
if (!eng3d_class) {
NOUVEAU_ERR("Unknown nv3x/nv4x chipset: nv%02x\n", dev->chipset);
return NULL;
}
screen->advertise_npot = !!screen->is_nv4x;
screen->advertise_blend_equation_separate = !!screen->is_nv4x;
screen->use_nv4x = screen->is_nv4x;
if(screen->is_nv4x) {
if(debug_get_bool_option("NVFX_SIMULATE_NV30", FALSE))
screen->use_nv4x = 0;
if(!debug_get_bool_option("NVFX_NPOT", TRUE))
screen->advertise_npot = 0;
if(!debug_get_bool_option("NVFX_BLEND_EQ_SEP", TRUE))
screen->advertise_blend_equation_separate = 0;
}
screen->force_swtnl = debug_get_bool_option("NVFX_SWTNL", FALSE);
screen->trace_draw = debug_get_bool_option("NVFX_TRACE_DRAW", FALSE);
screen->buffer_allocation_cost = debug_get_num_option("NVFX_BUFFER_ALLOCATION_COST", 16384);
screen->inline_cost_per_hardware_cost = atof(debug_get_option("NVFX_INLINE_COST_PER_HARDWARE_COST", "1.0"));
screen->static_reuse_threshold = atof(debug_get_option("NVFX_STATIC_REUSE_THRESHOLD", "2.0"));
/* We don't advertise these by default because filtering and blending doesn't work as
* it should, due to several restrictions.
* The only exception is fp16 on nv40.
*/
screen->advertise_fp16 = debug_get_bool_option("NVFX_FP16", !!screen->use_nv4x);
screen->advertise_fp32 = debug_get_bool_option("NVFX_FP32", 0);
screen->vertex_buffer_reloc_flags = nvfx_screen_get_vertex_buffer_flags(screen);
/* surely both nv3x and nv44 support index buffers too: find out how and test that */
if(eng3d_class == NV40_3D)
screen->index_buffer_reloc_flags = screen->vertex_buffer_reloc_flags;
if(!screen->force_swtnl && screen->vertex_buffer_reloc_flags == screen->index_buffer_reloc_flags)
screen->base.vertex_buffer_flags = screen->base.index_buffer_flags = screen->vertex_buffer_reloc_flags;
nvfx_screen_init_resource_functions(pscreen);
ret = nouveau_grobj_alloc(chan, 0xbeef3097, eng3d_class, &screen->eng3d);
if (ret) {
NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
return FALSE;
}
/* 2D engine setup */
nvfx_screen_surface_init(pscreen);
/* Notifier for sync purposes */
ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
if (ret) {
NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
nvfx_screen_destroy(pscreen);
return NULL;
}
/* Query objects */
for(i = 0; i < sizeof(query_sizes) / sizeof(query_sizes[0]); ++i)
{
ret = nouveau_notifier_alloc(chan, 0xbeef0302, query_sizes[i], &screen->query);
if(!ret)
break;
}
if (ret) {
NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
nvfx_screen_destroy(pscreen);
return NULL;
}
ret = nouveau_resource_init(&screen->query_heap, 0, query_sizes[i]);
if (ret) {
NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
nvfx_screen_destroy(pscreen);
return NULL;
}
LIST_INITHEAD(&screen->query_list);
/* Vtxprog resources */
if (nouveau_resource_init(&screen->vp_exec_heap, 0, screen->use_nv4x ? 512 : 256) ||
nouveau_resource_init(&screen->vp_data_heap, 0, screen->use_nv4x ? 468 : 256)) {
nvfx_screen_destroy(pscreen);
return NULL;
}
BIND_RING(chan, screen->eng3d, 7);
/* Static eng3d initialisation */
/* note that we just started using the channel, so we must have space in the pushbuffer */
BEGIN_RING(chan, screen->eng3d, NV30_3D_DMA_NOTIFY, 1);
OUT_RING(chan, screen->sync->handle);
BEGIN_RING(chan, screen->eng3d, NV30_3D_DMA_TEXTURE0, 2);
OUT_RING(chan, chan->vram->handle);
OUT_RING(chan, chan->gart->handle);
BEGIN_RING(chan, screen->eng3d, NV30_3D_DMA_COLOR1, 1);
OUT_RING(chan, chan->vram->handle);
BEGIN_RING(chan, screen->eng3d, NV30_3D_DMA_COLOR0, 2);
OUT_RING(chan, chan->vram->handle);
OUT_RING(chan, chan->vram->handle);
BEGIN_RING(chan, screen->eng3d, NV30_3D_DMA_VTXBUF0, 2);
OUT_RING(chan, chan->vram->handle);
OUT_RING(chan, chan->gart->handle);
BEGIN_RING(chan, screen->eng3d, NV30_3D_DMA_FENCE, 2);
OUT_RING(chan, 0);
OUT_RING(chan, screen->query->handle);
BEGIN_RING(chan, screen->eng3d, NV30_3D_DMA_UNK1AC, 2);
OUT_RING(chan, chan->vram->handle);
OUT_RING(chan, chan->vram->handle);
if(!screen->is_nv4x)
nv30_screen_init(screen);
else
nv40_screen_init(screen);
return pscreen;
}

View File

@ -1,65 +0,0 @@
#ifndef __NVFX_SCREEN_H__
#define __NVFX_SCREEN_H__
#include "pipe/p_compiler.h"
#include "util/u_double_list.h"
#include "nouveau/nouveau_screen.h"
struct pipe_screen;
struct nvfx_screen {
struct nouveau_screen base;
struct nouveau_bo *fence;
struct nvfx_context *cur_ctx;
unsigned is_nv4x; /* either 0 or ~0 */
unsigned use_nv4x; /* either 0 or ~0 */
boolean force_swtnl;
boolean trace_draw;
unsigned vertex_buffer_reloc_flags;
unsigned index_buffer_reloc_flags;
unsigned advertise_fp16;
unsigned advertise_fp32;
unsigned advertise_npot;
unsigned advertise_blend_equation_separate;
/* HW graphics objects */
struct nouveau_grobj *eng3d;
struct nouveau_notifier *sync;
/* Query object resources */
struct nouveau_notifier *query;
struct nouveau_resource *query_heap;
struct list_head query_list;
/* Vtxprog resources */
struct nouveau_resource *vp_exec_heap;
struct nouveau_resource *vp_data_heap;
struct nv04_2d_context* eng2d;
/* Once the amount of bytes drawn from the buffer reaches the updated size times this value,
* we will assume that the buffer will be drawn an huge number of times before the
* next modification
*/
float static_reuse_threshold;
/* Cost of allocating a buffer in terms of the cost of copying a byte to an hardware buffer */
unsigned buffer_allocation_cost;
/* inline_cost/hardware_cost conversion ration */
float inline_cost_per_hardware_cost;
};
static INLINE struct nvfx_screen *
nvfx_screen(struct pipe_screen *screen)
{
return (struct nvfx_screen *)screen;
}
int nvfx_screen_surface_init(struct pipe_screen *pscreen);
void nvfx_screen_surface_takedown(struct pipe_screen *pscreen);
#endif

View File

@ -1,526 +0,0 @@
#ifndef __NVFX_SHADER_H__
#define __NVFX_SHADER_H__
#include <stdint.h>
#include "pipe/p_compiler.h"
#define NVFX_SWZ_IDENTITY ((3 << 6) | (2 << 4) | (1 << 2) | (0 << 0))
/* this will resolve to either the NV30 or the NV40 version
* depending on the current hardware */
/* unusual, but very fast and compact method */
#define NVFX_VP(c) ((NV30_VP_##c) + (nvfx->is_nv4x & ((NV40_VP_##c) - (NV30_VP_##c))))
#define NVFX_VP_INST_SLOT_VEC 0
#define NVFX_VP_INST_SLOT_SCA 1
#define NVFX_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */
#define NVFX_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */
#define NVFX_VP_INST_IN_NORMAL 2
#define NVFX_VP_INST_IN_COL0 3 /* Should probably confirm them all though */
#define NVFX_VP_INST_IN_COL1 4
#define NVFX_VP_INST_IN_FOGC 5
#define NVFX_VP_INST_IN_TC0 8
#define NVFX_VP_INST_IN_TC(n) (8+n)
#define NVFX_VP_INST_SCA_OP_NOP 0x00
#define NVFX_VP_INST_SCA_OP_MOV 0x01
#define NVFX_VP_INST_SCA_OP_RCP 0x02
#define NVFX_VP_INST_SCA_OP_RCC 0x03
#define NVFX_VP_INST_SCA_OP_RSQ 0x04
#define NVFX_VP_INST_SCA_OP_EXP 0x05
#define NVFX_VP_INST_SCA_OP_LOG 0x06
#define NVFX_VP_INST_SCA_OP_LIT 0x07
#define NVFX_VP_INST_SCA_OP_BRA 0x09
#define NVFX_VP_INST_SCA_OP_CAL 0x0B
#define NVFX_VP_INST_SCA_OP_RET 0x0C
#define NVFX_VP_INST_SCA_OP_LG2 0x0D
#define NVFX_VP_INST_SCA_OP_EX2 0x0E
#define NVFX_VP_INST_SCA_OP_SIN 0x0F
#define NVFX_VP_INST_SCA_OP_COS 0x10
#define NV40_VP_INST_SCA_OP_PUSHA 0x13
#define NV40_VP_INST_SCA_OP_POPA 0x14
#define NVFX_VP_INST_VEC_OP_NOP 0x00
#define NVFX_VP_INST_VEC_OP_MOV 0x01
#define NVFX_VP_INST_VEC_OP_MUL 0x02
#define NVFX_VP_INST_VEC_OP_ADD 0x03
#define NVFX_VP_INST_VEC_OP_MAD 0x04
#define NVFX_VP_INST_VEC_OP_DP3 0x05
#define NVFX_VP_INST_VEC_OP_DPH 0x06
#define NVFX_VP_INST_VEC_OP_DP4 0x07
#define NVFX_VP_INST_VEC_OP_DST 0x08
#define NVFX_VP_INST_VEC_OP_MIN 0x09
#define NVFX_VP_INST_VEC_OP_MAX 0x0A
#define NVFX_VP_INST_VEC_OP_SLT 0x0B
#define NVFX_VP_INST_VEC_OP_SGE 0x0C
#define NVFX_VP_INST_VEC_OP_ARL 0x0D
#define NVFX_VP_INST_VEC_OP_FRC 0x0E
#define NVFX_VP_INST_VEC_OP_FLR 0x0F
#define NVFX_VP_INST_VEC_OP_SEQ 0x10
#define NVFX_VP_INST_VEC_OP_SFL 0x11
#define NVFX_VP_INST_VEC_OP_SGT 0x12
#define NVFX_VP_INST_VEC_OP_SLE 0x13
#define NVFX_VP_INST_VEC_OP_SNE 0x14
#define NVFX_VP_INST_VEC_OP_STR 0x15
#define NVFX_VP_INST_VEC_OP_SSG 0x16
#define NVFX_VP_INST_VEC_OP_ARR 0x17
#define NVFX_VP_INST_VEC_OP_ARA 0x18
#define NV40_VP_INST_VEC_OP_TXL 0x19
/* DWORD 3 */
#define NVFX_VP_INST_LAST (1 << 0)
/*
* Each fragment program opcode appears to be comprised of 4 32-bit values.
*
* 0: OPDEST
* 0: program end
* 1-6: destination register
* 7: destination register is fp16?? (use for outputs)
* 8: set condition code
* 9: writemask x
* 10: writemask y
* 11: writemask z
* 12: writemask w
* 13-16: source attribute register number (e.g. COL0)
* 17-20: texture unit number
* 21: expand value on texture operation (x -> 2x - 1)
* 22-23: precision 0 = fp32, 1 = fp16, 2 = s1.10 fixed, 3 = s0.8 fixed (nv40-only))
* 24-29: opcode
* 30: no destination
* 31: saturate
* 1 - SRC0
* 0-17: see common source fields
* 18: execute if condition code less
* 19: execute if condition code equal
* 20: execute if condition code greater
* 21-22: condition code swizzle x source component
* 23-24: condition code swizzle y source component
* 25-26: condition code swizzle z source component
* 27-28: condition code swizzle w source component
* 29: source 0 absolute
* 30: always 0 in renouveau tests
* 31: always 0 in renouveau tests
* 2 - SRC1
* 0-17: see common source fields
* 18: source 1 absolute
* 19-20: input precision 0 = fp32, 1 = fp16, 2 = s1.10 fixed, 3 = ???
* 21-27: always 0 in renouveau tests
* 28-30: scale (0 = 1x, 1 = 2x, 2 = 4x, 3 = 8x, 4 = ???, 5, = 1/2, 6 = 1/4, 7 = 1/8)
* 31: opcode is branch
* 3 - SRC2
* 0-17: see common source fields
* 18: source 2 absolute
* 19-29: address register displacement
* 30: use index register
* 31: disable perspective-correct interpolation?
*
* Common fields of 0, 1, 2 - SRC
* 0-1: source register type (0 = temp, 1 = input, 2 = immediate, 3 = ???)
* 2-7: source temp register index
* 8: source register is fp16??
* 9-10: source swizzle x source component
* 11-12: source swizzle y source component
* 13-14: source swizzle z source component
* 15-16: source swizzle w source component
* 17: negate
* 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
*
* NV40 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.
*
*/
//== Opcode / Destination selection ==
#define NVFX_FP_OP_PROGRAM_END (1 << 0)
#define NVFX_FP_OP_OUT_REG_SHIFT 1
#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */
#define NV40_FP_OP_OUT_REG_MASK (63 << 1)
/* Needs to be set when writing outputs to get expected result.. */
#define NVFX_FP_OP_OUT_REG_HALF (1 << 7)
#define NVFX_FP_OP_COND_WRITE_ENABLE (1 << 8)
#define NVFX_FP_OP_OUTMASK_SHIFT 9
#define NVFX_FP_OP_OUTMASK_MASK (0xF << 9)
# define NVFX_FP_OP_OUT_X (1<<9)
# define NVFX_FP_OP_OUT_Y (1<<10)
# define NVFX_FP_OP_OUT_Z (1<<11)
# define NVFX_FP_OP_OUT_W (1<<12)
/* Uncertain about these, especially the input_src values.. it's possible that
* they can be dynamically changed.
*/
#define NVFX_FP_OP_INPUT_SRC_SHIFT 13
#define NVFX_FP_OP_INPUT_SRC_MASK (15 << 13)
# define NVFX_FP_OP_INPUT_SRC_POSITION 0x0
# define NVFX_FP_OP_INPUT_SRC_COL0 0x1
# define NVFX_FP_OP_INPUT_SRC_COL1 0x2
# define NVFX_FP_OP_INPUT_SRC_FOGC 0x3
# define NVFX_FP_OP_INPUT_SRC_TC0 0x4
# define NVFX_FP_OP_INPUT_SRC_TC(n) (0x4 + n)
# define NV40_FP_OP_INPUT_SRC_FACING 0xE
#define NVFX_FP_OP_TEX_UNIT_SHIFT 17
#define NVFX_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */
#define NVFX_FP_OP_PRECISION_SHIFT 22
#define NVFX_FP_OP_PRECISION_MASK (3 << 22)
# define NVFX_FP_PRECISION_FP32 0
# define NVFX_FP_PRECISION_FP16 1
# define NVFX_FP_PRECISION_FX12 2
#define NVFX_FP_OP_OPCODE_SHIFT 24
#define NVFX_FP_OP_OPCODE_MASK (0x3F << 24)
/* NV30/NV40 fragment program opcodes */
#define NVFX_FP_OP_OPCODE_NOP 0x00
#define NVFX_FP_OP_OPCODE_MOV 0x01
#define NVFX_FP_OP_OPCODE_MUL 0x02
#define NVFX_FP_OP_OPCODE_ADD 0x03
#define NVFX_FP_OP_OPCODE_MAD 0x04
#define NVFX_FP_OP_OPCODE_DP3 0x05
#define NVFX_FP_OP_OPCODE_DP4 0x06
#define NVFX_FP_OP_OPCODE_DST 0x07
#define NVFX_FP_OP_OPCODE_MIN 0x08
#define NVFX_FP_OP_OPCODE_MAX 0x09
#define NVFX_FP_OP_OPCODE_SLT 0x0A
#define NVFX_FP_OP_OPCODE_SGE 0x0B
#define NVFX_FP_OP_OPCODE_SLE 0x0C
#define NVFX_FP_OP_OPCODE_SGT 0x0D
#define NVFX_FP_OP_OPCODE_SNE 0x0E
#define NVFX_FP_OP_OPCODE_SEQ 0x0F
#define NVFX_FP_OP_OPCODE_FRC 0x10
#define NVFX_FP_OP_OPCODE_FLR 0x11
#define NVFX_FP_OP_OPCODE_KIL 0x12
#define NVFX_FP_OP_OPCODE_PK4B 0x13
#define NVFX_FP_OP_OPCODE_UP4B 0x14
#define NVFX_FP_OP_OPCODE_DDX 0x15 /* can only write XY */
#define NVFX_FP_OP_OPCODE_DDY 0x16 /* can only write XY */
#define NVFX_FP_OP_OPCODE_TEX 0x17
#define NVFX_FP_OP_OPCODE_TXP 0x18
#define NVFX_FP_OP_OPCODE_TXD 0x19
#define NVFX_FP_OP_OPCODE_RCP 0x1A
#define NVFX_FP_OP_OPCODE_EX2 0x1C
#define NVFX_FP_OP_OPCODE_LG2 0x1D
#define NVFX_FP_OP_OPCODE_STR 0x20
#define NVFX_FP_OP_OPCODE_SFL 0x21
#define NVFX_FP_OP_OPCODE_COS 0x22
#define NVFX_FP_OP_OPCODE_SIN 0x23
#define NVFX_FP_OP_OPCODE_PK2H 0x24
#define NVFX_FP_OP_OPCODE_UP2H 0x25
#define NVFX_FP_OP_OPCODE_PK4UB 0x27
#define NVFX_FP_OP_OPCODE_UP4UB 0x28
#define NVFX_FP_OP_OPCODE_PK2US 0x29
#define NVFX_FP_OP_OPCODE_UP2US 0x2A
#define NVFX_FP_OP_OPCODE_DP2A 0x2E
#define NVFX_FP_OP_OPCODE_TXB 0x31
#define NVFX_FP_OP_OPCODE_DIV 0x3A
/* NV30 only fragment program opcodes */
#define NVFX_FP_OP_OPCODE_RSQ_NV30 0x1B
#define NVFX_FP_OP_OPCODE_LIT_NV30 0x1E
#define NVFX_FP_OP_OPCODE_LRP_NV30 0x1F
#define NVFX_FP_OP_OPCODE_POW_NV30 0x26
#define NVFX_FP_OP_OPCODE_RFL_NV30 0x36
/* NV40 only fragment program opcodes */
#define NVFX_FP_OP_OPCODE_TXL_NV40 0x2F
#define NVFX_FP_OP_OPCODE_LITEX2_NV40 0x3C
/* 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_NONE (1 << 30)
#define NVFX_FP_OP_OUT_SAT (1 << 31)
/* high order bits of SRC0 */
#define NVFX_FP_OP_SRC0_ABS (1 << 29)
#define NVFX_FP_OP_COND_SWZ_W_SHIFT 27
#define NVFX_FP_OP_COND_SWZ_W_MASK (3 << 27)
#define NVFX_FP_OP_COND_SWZ_Z_SHIFT 25
#define NVFX_FP_OP_COND_SWZ_Z_MASK (3 << 25)
#define NVFX_FP_OP_COND_SWZ_Y_SHIFT 23
#define NVFX_FP_OP_COND_SWZ_Y_MASK (3 << 23)
#define NVFX_FP_OP_COND_SWZ_X_SHIFT 21
#define NVFX_FP_OP_COND_SWZ_X_MASK (3 << 21)
#define NVFX_FP_OP_COND_SWZ_ALL_SHIFT 21
#define NVFX_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21)
#define NVFX_FP_OP_COND_SHIFT 18
#define NVFX_FP_OP_COND_MASK (0x07 << 18)
# define NVFX_FP_OP_COND_FL 0
# define NVFX_FP_OP_COND_LT 1
# define NVFX_FP_OP_COND_EQ 2
# define NVFX_FP_OP_COND_LE 3
# define NVFX_FP_OP_COND_GT 4
# define NVFX_FP_OP_COND_NE 5
# define NVFX_FP_OP_COND_GE 6
# define NVFX_FP_OP_COND_TR 7
/* high order bits of SRC1 */
#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31)
#define NVFX_FP_OP_DST_SCALE_SHIFT 28
#define NVFX_FP_OP_DST_SCALE_MASK (3 << 28)
#define NVFX_FP_OP_DST_SCALE_1X 0
#define NVFX_FP_OP_DST_SCALE_2X 1
#define NVFX_FP_OP_DST_SCALE_4X 2
#define NVFX_FP_OP_DST_SCALE_8X 3
#define NVFX_FP_OP_DST_SCALE_INV_2X 5
#define NVFX_FP_OP_DST_SCALE_INV_4X 6
#define NVFX_FP_OP_DST_SCALE_INV_8X 7
#define NVFX_FP_OP_SRC1_ABS (1 << 18)
/* 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: absolute offset in dwords */
#define NV40_FP_OP_ELSE_OFFSET_SHIFT 0
#define NV40_FP_OP_ELSE_OFFSET_MASK (0x7FFFFFFF << 0)
/* SRC1 CAL */
#define NV40_FP_OP_SUB_OFFSET_SHIFT 0
#define NV40_FP_OP_SUB_OFFSET_MASK (0x7FFFFFFF << 0)
/* 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: absolute offset in dwords */
#define NV40_FP_OP_END_OFFSET_SHIFT 0
#define NV40_FP_OP_END_OFFSET_MASK (0x7FFFFFFF << 0)
/* high order bits of SRC2 */
#define NVFX_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 NVFX_FP_REG_TYPE_SHIFT 0
#define NVFX_FP_REG_TYPE_MASK (3 << 0)
# define NVFX_FP_REG_TYPE_TEMP 0
# define NVFX_FP_REG_TYPE_INPUT 1
# define NVFX_FP_REG_TYPE_CONST 2
#define NVFX_FP_REG_SRC_SHIFT 2
#define NV30_FP_REG_SRC_MASK (31 << 2)
#define NV40_FP_REG_SRC_MASK (63 << 2)
#define NVFX_FP_REG_SRC_HALF (1 << 8)
#define NVFX_FP_REG_SWZ_ALL_SHIFT 9
#define NVFX_FP_REG_SWZ_ALL_MASK (255 << 9)
#define NVFX_FP_REG_SWZ_X_SHIFT 9
#define NVFX_FP_REG_SWZ_X_MASK (3 << 9)
#define NVFX_FP_REG_SWZ_Y_SHIFT 11
#define NVFX_FP_REG_SWZ_Y_MASK (3 << 11)
#define NVFX_FP_REG_SWZ_Z_SHIFT 13
#define NVFX_FP_REG_SWZ_Z_MASK (3 << 13)
#define NVFX_FP_REG_SWZ_W_SHIFT 15
#define NVFX_FP_REG_SWZ_W_MASK (3 << 15)
# define NVFX_FP_SWIZZLE_X 0
# define NVFX_FP_SWIZZLE_Y 1
# define NVFX_FP_SWIZZLE_Z 2
# define NVFX_FP_SWIZZLE_W 3
#define NVFX_FP_REG_NEGATE (1 << 17)
#define NVFXSR_NONE 0
#define NVFXSR_OUTPUT 1
#define NVFXSR_INPUT 2
#define NVFXSR_TEMP 3
#define NVFXSR_CONST 5
#define NVFXSR_IMM 6
#define NVFXSR_RELOCATED 7
#define NVFX_COND_FL 0
#define NVFX_COND_LT 1
#define NVFX_COND_EQ 2
#define NVFX_COND_LE 3
#define NVFX_COND_GT 4
#define NVFX_COND_NE 5
#define NVFX_COND_GE 6
#define NVFX_COND_TR 7
/* Yes, this are ordered differently... */
#define NVFX_VP_MASK_X 8
#define NVFX_VP_MASK_Y 4
#define NVFX_VP_MASK_Z 2
#define NVFX_VP_MASK_W 1
#define NVFX_VP_MASK_ALL 0xf
#define NVFX_FP_MASK_X 1
#define NVFX_FP_MASK_Y 2
#define NVFX_FP_MASK_Z 4
#define NVFX_FP_MASK_W 8
#define NVFX_FP_MASK_ALL 0xf
#define NVFX_SWZ_X 0
#define NVFX_SWZ_Y 1
#define NVFX_SWZ_Z 2
#define NVFX_SWZ_W 3
#define swz(s,x,y,z,w) nvfx_src_swz((s), NVFX_SWZ_##x, NVFX_SWZ_##y, NVFX_SWZ_##z, NVFX_SWZ_##w)
#define neg(s) nvfx_src_neg((s))
#define abs(s) nvfx_src_abs((s))
struct nvfx_reg {
int8_t type;
uint32_t index;
};
struct nvfx_src {
struct nvfx_reg reg;
uint8_t indirect : 1;
uint8_t indirect_reg : 1;
uint8_t indirect_swz : 2;
uint8_t negate : 1;
uint8_t abs : 1;
uint8_t swz[4];
};
struct nvfx_insn
{
uint8_t op;
char scale;
int8_t unit;
uint8_t mask;
uint8_t cc_swz[4];
uint8_t sat : 1;
uint8_t cc_update : 1;
uint8_t cc_update_reg : 1;
uint8_t cc_test : 3;
uint8_t cc_test_reg : 1;
struct nvfx_reg dst;
struct nvfx_src src[3];
};
static INLINE struct nvfx_insn
nvfx_insn(boolean sat, unsigned op, int unit, struct nvfx_reg dst, unsigned mask, struct nvfx_src s0, struct nvfx_src s1, struct nvfx_src s2)
{
struct nvfx_insn insn = {
.op = op,
.scale = 0,
.unit = unit,
.sat = sat,
.mask = mask,
.cc_update = 0,
.cc_update_reg = 0,
.cc_test = NVFX_COND_TR,
.cc_test_reg = 0,
.cc_swz = { 0, 1, 2, 3 },
.dst = dst,
.src = {s0, s1, s2}
};
return insn;
}
static INLINE struct nvfx_reg
nvfx_reg(int type, int index)
{
struct nvfx_reg temp = {
.type = type,
.index = index,
};
return temp;
}
static INLINE struct nvfx_src
nvfx_src(struct nvfx_reg reg)
{
struct nvfx_src temp = {
.reg = reg,
.abs = 0,
.negate = 0,
.swz = { 0, 1, 2, 3 },
.indirect = 0,
};
return temp;
}
static INLINE struct nvfx_src
nvfx_src_swz(struct nvfx_src src, int x, int y, int z, int w)
{
struct nvfx_src dst = src;
dst.swz[NVFX_SWZ_X] = src.swz[x];
dst.swz[NVFX_SWZ_Y] = src.swz[y];
dst.swz[NVFX_SWZ_Z] = src.swz[z];
dst.swz[NVFX_SWZ_W] = src.swz[w];
return dst;
}
static INLINE struct nvfx_src
nvfx_src_neg(struct nvfx_src src)
{
src.negate = !src.negate;
return src;
}
static INLINE struct nvfx_src
nvfx_src_abs(struct nvfx_src src)
{
src.abs = 1;
return src;
}
struct nvfx_relocation {
unsigned location;
unsigned target;
};
#endif

View File

@ -1,389 +0,0 @@
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_framebuffer.h"
#include "draw/draw_context.h"
#include "tgsi/tgsi_parse.h"
#include "nvfx_context.h"
#include "nvfx_state.h"
#include "nvfx_tex.h"
static void *
nvfx_blend_state_create(struct pipe_context *pipe,
const struct pipe_blend_state *cso)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nvfx_blend_state *bso = CALLOC(1, sizeof(*bso));
struct nouveau_statebuf_builder sb = sb_init(bso->sb);
if (cso->rt[0].blend_enable) {
sb_method(sb, NV30_3D_BLEND_FUNC_ENABLE, 3);
sb_data(sb, 1);
sb_data(sb, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) |
nvgl_blend_func(cso->rt[0].rgb_src_factor));
sb_data(sb, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 |
nvgl_blend_func(cso->rt[0].rgb_dst_factor));
if(nvfx->screen->base.device->chipset < 0x40) {
sb_method(sb, NV30_3D_BLEND_EQUATION, 1);
sb_data(sb, nvgl_blend_eqn(cso->rt[0].rgb_func));
} else {
sb_method(sb, NV40_3D_BLEND_EQUATION, 1);
sb_data(sb, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 |
nvgl_blend_eqn(cso->rt[0].rgb_func));
}
} else {
sb_method(sb, NV30_3D_BLEND_FUNC_ENABLE, 1);
sb_data(sb, 0);
}
sb_method(sb, NV30_3D_COLOR_MASK, 1);
sb_data(sb, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) |
((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0)));
/* TODO: add NV40 MRT color mask */
if (cso->logicop_enable) {
sb_method(sb, NV30_3D_COLOR_LOGIC_OP_ENABLE, 2);
sb_data(sb, 1);
sb_data(sb, nvgl_logicop_func(cso->logicop_func));
} else {
sb_method(sb, NV30_3D_COLOR_LOGIC_OP_ENABLE, 1);
sb_data(sb, 0);
}
sb_method(sb, NV30_3D_DITHER_ENABLE, 1);
sb_data(sb, cso->dither ? 1 : 0);
bso->sb_len = sb_len(sb, bso->sb);
bso->pipe = *cso;
return (void *)bso;
}
static void
nvfx_blend_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
nvfx->blend = hwcso;
nvfx->dirty |= NVFX_NEW_BLEND;
}
static void
nvfx_blend_state_delete(struct pipe_context *pipe, void *hwcso)
{
struct nvfx_blend_state *bso = hwcso;
FREE(bso);
}
static void *
nvfx_rasterizer_state_create(struct pipe_context *pipe,
const struct pipe_rasterizer_state *cso)
{
struct nvfx_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
struct nouveau_statebuf_builder sb = sb_init(rsso->sb);
/*XXX: ignored:
* point_smooth -nohw
* multisample
* sprite_coord_origin
*/
sb_method(sb, NV30_3D_SHADE_MODEL, 1);
sb_data(sb, cso->flatshade ? NV30_3D_SHADE_MODEL_FLAT :
NV30_3D_SHADE_MODEL_SMOOTH);
sb_method(sb, NV30_3D_VERTEX_TWO_SIDE_ENABLE, 1);
sb_data(sb, cso->light_twoside);
sb_method(sb, NV30_3D_LINE_WIDTH, 2);
sb_data(sb, (unsigned char)(cso->line_width * 8.0) & 0xff);
sb_data(sb, cso->line_smooth ? 1 : 0);
sb_method(sb, NV30_3D_LINE_STIPPLE_ENABLE, 2);
sb_data(sb, cso->line_stipple_enable ? 1 : 0);
sb_data(sb, (cso->line_stipple_pattern << 16) |
cso->line_stipple_factor);
sb_method(sb, NV30_3D_POINT_SIZE, 1);
sb_data(sb, fui(cso->point_size));
sb_method(sb, NV30_3D_POLYGON_MODE_FRONT, 6);
sb_data(sb, nvgl_polygon_mode(cso->fill_front));
sb_data(sb, nvgl_polygon_mode(cso->fill_back));
switch (cso->cull_face) {
case PIPE_FACE_FRONT:
sb_data(sb, NV30_3D_CULL_FACE_FRONT);
break;
case PIPE_FACE_BACK:
sb_data(sb, NV30_3D_CULL_FACE_BACK);
break;
case PIPE_FACE_FRONT_AND_BACK:
sb_data(sb, NV30_3D_CULL_FACE_FRONT_AND_BACK);
break;
default:
sb_data(sb, NV30_3D_CULL_FACE_BACK);
break;
}
if (cso->front_ccw) {
sb_data(sb, NV30_3D_FRONT_FACE_CCW);
} else {
sb_data(sb, NV30_3D_FRONT_FACE_CW);
}
sb_data(sb, cso->poly_smooth ? 1 : 0);
sb_data(sb, (cso->cull_face != PIPE_FACE_NONE) ? 1 : 0);
sb_method(sb, NV30_3D_POLYGON_STIPPLE_ENABLE, 1);
sb_data(sb, cso->poly_stipple_enable ? 1 : 0);
sb_method(sb, NV30_3D_POLYGON_OFFSET_POINT_ENABLE, 3);
sb_data(sb, cso->offset_point);
sb_data(sb, cso->offset_line);
sb_data(sb, cso->offset_tri);
if (cso->offset_point || cso->offset_line || cso->offset_tri) {
sb_method(sb, NV30_3D_POLYGON_OFFSET_FACTOR, 2);
sb_data(sb, fui(cso->offset_scale));
sb_data(sb, fui(cso->offset_units * 2));
}
sb_method(sb, NV30_3D_FLATSHADE_FIRST, 1);
sb_data(sb, cso->flatshade_first);
rsso->pipe = *cso;
rsso->sb_len = sb_len(sb, rsso->sb);
return (void *)rsso;
}
static void
nvfx_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
if(nvfx->rasterizer && hwcso)
{
if(!nvfx->rasterizer || ((struct nvfx_rasterizer_state*)hwcso)->pipe.scissor
!= nvfx->rasterizer->pipe.scissor)
{
nvfx->dirty |= NVFX_NEW_SCISSOR;
nvfx->draw_dirty |= NVFX_NEW_SCISSOR;
}
if(((struct nvfx_rasterizer_state*)hwcso)->pipe.point_quad_rasterization != nvfx->rasterizer->pipe.point_quad_rasterization
|| ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_enable != nvfx->rasterizer->pipe.sprite_coord_enable
|| ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_mode != nvfx->rasterizer->pipe.sprite_coord_mode)
{
nvfx->dirty |= NVFX_NEW_SPRITE;
}
}
nvfx->rasterizer = hwcso;
nvfx->dirty |= NVFX_NEW_RAST;
nvfx->draw_dirty |= NVFX_NEW_RAST;
}
static void
nvfx_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
{
struct nvfx_rasterizer_state *rsso = hwcso;
FREE(rsso);
}
static void *
nvfx_depth_stencil_alpha_state_create(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *cso)
{
struct nvfx_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
struct nouveau_statebuf_builder sb = sb_init(zsaso->sb);
sb_method(sb, NV30_3D_DEPTH_FUNC, 1);
sb_data (sb, nvgl_comparison_op(cso->depth.func));
sb_method(sb, NV30_3D_ALPHA_FUNC_ENABLE, 3);
sb_data (sb, cso->alpha.enabled ? 1 : 0);
sb_data (sb, nvgl_comparison_op(cso->alpha.func));
sb_data (sb, float_to_ubyte(cso->alpha.ref_value));
if (cso->stencil[0].enabled) {
sb_method(sb, NV30_3D_STENCIL_ENABLE(0), 3);
sb_data (sb, cso->stencil[0].enabled ? 1 : 0);
sb_data (sb, cso->stencil[0].writemask);
sb_data (sb, nvgl_comparison_op(cso->stencil[0].func));
sb_method(sb, NV30_3D_STENCIL_FUNC_MASK(0), 4);
sb_data (sb, cso->stencil[0].valuemask);
sb_data (sb, nvgl_stencil_op(cso->stencil[0].fail_op));
sb_data (sb, nvgl_stencil_op(cso->stencil[0].zfail_op));
sb_data (sb, nvgl_stencil_op(cso->stencil[0].zpass_op));
} else {
sb_method(sb, NV30_3D_STENCIL_ENABLE(0), 1);
sb_data (sb, 0);
}
if (cso->stencil[1].enabled) {
sb_method(sb, NV30_3D_STENCIL_ENABLE(1), 3);
sb_data (sb, cso->stencil[1].enabled ? 1 : 0);
sb_data (sb, cso->stencil[1].writemask);
sb_data (sb, nvgl_comparison_op(cso->stencil[1].func));
sb_method(sb, NV30_3D_STENCIL_FUNC_MASK(1), 4);
sb_data (sb, cso->stencil[1].valuemask);
sb_data (sb, nvgl_stencil_op(cso->stencil[1].fail_op));
sb_data (sb, nvgl_stencil_op(cso->stencil[1].zfail_op));
sb_data (sb, nvgl_stencil_op(cso->stencil[1].zpass_op));
} else {
sb_method(sb, NV30_3D_STENCIL_ENABLE(1), 1);
sb_data (sb, 0);
}
zsaso->pipe = *cso;
zsaso->sb_len = sb_len(sb, zsaso->sb);
return (void *)zsaso;
}
static void
nvfx_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
nvfx->zsa = hwcso;
nvfx->dirty |= NVFX_NEW_ZSA;
}
static void
nvfx_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
{
struct nvfx_zsa_state *zsaso = hwcso;
FREE(zsaso);
}
static void
nvfx_set_blend_color(struct pipe_context *pipe,
const struct pipe_blend_color *bcol)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
nvfx->blend_colour = *bcol;
nvfx->dirty |= NVFX_NEW_BCOL;
}
static void
nvfx_set_stencil_ref(struct pipe_context *pipe,
const struct pipe_stencil_ref *sr)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
nvfx->stencil_ref = *sr;
nvfx->dirty |= NVFX_NEW_SR;
}
static void
nvfx_set_clip_state(struct pipe_context *pipe,
const struct pipe_clip_state *clip)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
nvfx->clip = *clip;
nvfx->dirty |= NVFX_NEW_UCP;
nvfx->draw_dirty |= NVFX_NEW_UCP;
}
static void
nvfx_set_sample_mask(struct pipe_context *pipe,
unsigned sample_mask)
{
}
static void
nvfx_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
struct pipe_resource *buf )
{
struct nvfx_context *nvfx = nvfx_context(pipe);
pipe_resource_reference(&nvfx->constbuf[shader], buf);
nvfx->constbuf_nr[shader] = buf ? (buf->width0 / (4 * sizeof(float))) : 0;
if (shader == PIPE_SHADER_VERTEX) {
nvfx->dirty |= NVFX_NEW_VERTCONST;
} else
if (shader == PIPE_SHADER_FRAGMENT) {
nvfx->dirty |= NVFX_NEW_FRAGCONST;
}
}
static void
nvfx_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
if(fb)
util_copy_framebuffer_state(&nvfx->framebuffer, fb);
else
util_unreference_framebuffer_state(&nvfx->framebuffer);
nvfx->dirty |= NVFX_NEW_FB;
}
static void
nvfx_set_polygon_stipple(struct pipe_context *pipe,
const struct pipe_poly_stipple *stipple)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
memcpy(nvfx->stipple, stipple->stipple, 4 * 32);
nvfx->dirty |= NVFX_NEW_STIPPLE;
}
static void
nvfx_set_scissor_state(struct pipe_context *pipe,
const struct pipe_scissor_state *s)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
nvfx->scissor = *s;
nvfx->dirty |= NVFX_NEW_SCISSOR;
}
static void
nvfx_set_viewport_state(struct pipe_context *pipe,
const struct pipe_viewport_state *vpt)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
nvfx->viewport = *vpt;
nvfx->dirty |= NVFX_NEW_VIEWPORT;
nvfx->draw_dirty |= NVFX_NEW_VIEWPORT;
}
void
nvfx_init_state_functions(struct nvfx_context *nvfx)
{
nvfx->pipe.create_blend_state = nvfx_blend_state_create;
nvfx->pipe.bind_blend_state = nvfx_blend_state_bind;
nvfx->pipe.delete_blend_state = nvfx_blend_state_delete;
nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create;
nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind;
nvfx->pipe.delete_rasterizer_state = nvfx_rasterizer_state_delete;
nvfx->pipe.create_depth_stencil_alpha_state =
nvfx_depth_stencil_alpha_state_create;
nvfx->pipe.bind_depth_stencil_alpha_state =
nvfx_depth_stencil_alpha_state_bind;
nvfx->pipe.delete_depth_stencil_alpha_state =
nvfx_depth_stencil_alpha_state_delete;
nvfx->pipe.set_blend_color = nvfx_set_blend_color;
nvfx->pipe.set_stencil_ref = nvfx_set_stencil_ref;
nvfx->pipe.set_clip_state = nvfx_set_clip_state;
nvfx->pipe.set_sample_mask = nvfx_set_sample_mask;
nvfx->pipe.set_constant_buffer = nvfx_set_constant_buffer;
nvfx->pipe.set_framebuffer_state = nvfx_set_framebuffer_state;
nvfx->pipe.set_polygon_stipple = nvfx_set_polygon_stipple;
nvfx->pipe.set_scissor_state = nvfx_set_scissor_state;
nvfx->pipe.set_viewport_state = nvfx_set_viewport_state;
}

View File

@ -1,115 +0,0 @@
#ifndef __NVFX_STATE_H__
#define __NVFX_STATE_H__
#include "pipe/p_state.h"
#include "pipe/p_video_state.h"
#include "tgsi/tgsi_scan.h"
#include "nouveau/nouveau_statebuf.h"
#include "util/u_dynarray.h"
#include "util/u_linkage.h"
struct nvfx_vertex_program_exec {
uint32_t data[4];
};
struct nvfx_vertex_program_data {
int index; /* immediates == -1 */
float value[4];
};
struct nvfx_vertex_program {
unsigned long long id;
struct nvfx_vertex_program_exec *insns;
unsigned nr_insns;
struct nvfx_vertex_program_data *consts;
unsigned nr_consts;
char generic_to_fp_input[256];
int sprite_fp_input;
struct nouveau_resource *exec;
unsigned exec_start;
struct nouveau_resource *data;
unsigned data_start;
unsigned data_start_min;
uint32_t ir;
uint32_t or;
int clip_nr;
struct util_dynarray branch_relocs;
struct util_dynarray const_relocs;
};
#define NVFX_VP_FAILED ((struct nvfx_vertex_program*)-1)
struct nvfx_pipe_vertex_program {
struct pipe_shader_state pipe;
struct tgsi_shader_info info;
unsigned draw_elements;
boolean draw_no_elements;
struct draw_vertex_shader *draw_vs;
struct nvfx_vertex_program* draw_vp;
struct nvfx_vertex_program* vp;
};
struct nvfx_fragment_program_data {
unsigned offset;
unsigned index;
};
struct nvfx_fragment_program_bo {
struct nvfx_fragment_program_bo* next;
struct nouveau_bo* bo;
unsigned char* slots;
char insn[] __attribute__((aligned(16)));
};
struct nvfx_fragment_program {
unsigned samplers;
unsigned point_sprite_control;
unsigned or;
unsigned coord_conventions;
uint32_t *insn;
int insn_len;
struct nvfx_fragment_program_data *consts;
unsigned nr_consts;
/* the slot at num_slots is for the sprite coordinate, if any */
unsigned num_slots; /* how many input semantics? */
unsigned char slot_to_generic[10]; /* semantics */
unsigned char slot_to_fp_input[11]; /* current assignment of slots for each used semantic */
struct util_dynarray slot_relocations[11];
/* This is reset to progs on any relocation update, and decreases every time we
* move to a new prog due to a constant update
* When this is the same as progs, applying relocations is no longer necessary.
*/
unsigned progs_left_with_obsolete_slot_assignments;
unsigned long long last_vp_id;
unsigned last_sprite_coord_enable;
uint32_t fp_control;
unsigned bo_prog_idx;
unsigned prog_size;
unsigned progs_per_bo;
unsigned progs;
struct nvfx_fragment_program_bo* fpbo;
};
struct nvfx_pipe_fragment_program {
struct pipe_shader_state pipe;
struct tgsi_shader_info info;
struct nvfx_fragment_program* fps[2];
};
#endif

View File

@ -1,439 +0,0 @@
#include "nvfx_context.h"
#include "nvfx_state.h"
#include "nvfx_resource.h"
#include "draw/draw_context.h"
void
nvfx_state_viewport_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
struct pipe_viewport_state *vpt = &nvfx->viewport;
if(nvfx->render_mode == HW) {
BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_TRANSLATE_X, 8);
OUT_RINGf(chan, vpt->translate[0]);
OUT_RINGf(chan, vpt->translate[1]);
OUT_RINGf(chan, vpt->translate[2]);
OUT_RINGf(chan, vpt->translate[3]);
OUT_RINGf(chan, vpt->scale[0]);
OUT_RINGf(chan, vpt->scale[1]);
OUT_RINGf(chan, vpt->scale[2]);
OUT_RINGf(chan, vpt->scale[3]);
BEGIN_RING(chan, eng3d, 0x1d78, 1);
OUT_RING(chan, 1);
} else {
BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_TRANSLATE_X, 8);
OUT_RINGf(chan, 0.0f);
OUT_RINGf(chan, 0.0f);
OUT_RINGf(chan, 0.0f);
OUT_RINGf(chan, 0.0f);
OUT_RINGf(chan, 1.0f);
OUT_RINGf(chan, 1.0f);
OUT_RINGf(chan, 1.0f);
OUT_RINGf(chan, 1.0f);
BEGIN_RING(chan, eng3d, 0x1d78, 1);
OUT_RING(chan, nvfx->is_nv4x ? 0x110 : 1);
}
}
void
nvfx_state_scissor_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
struct pipe_rasterizer_state *rast = &nvfx->rasterizer->pipe;
struct pipe_scissor_state *s = &nvfx->scissor;
if ((rast->scissor == 0 && nvfx->state.scissor_enabled == 0))
return;
nvfx->state.scissor_enabled = rast->scissor;
BEGIN_RING(chan, eng3d, NV30_3D_SCISSOR_HORIZ, 2);
if (nvfx->state.scissor_enabled) {
OUT_RING(chan, ((s->maxx - s->minx) << 16) | s->minx);
OUT_RING(chan, ((s->maxy - s->miny) << 16) | s->miny);
} else {
OUT_RING(chan, 4096 << 16);
OUT_RING(chan, 4096 << 16);
}
}
void
nvfx_state_sr_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
struct pipe_stencil_ref *sr = &nvfx->stencil_ref;
BEGIN_RING(chan, eng3d, NV30_3D_STENCIL_FUNC_REF(0), 1);
OUT_RING(chan, sr->ref_value[0]);
BEGIN_RING(chan, eng3d, NV30_3D_STENCIL_FUNC_REF(1), 1);
OUT_RING(chan, sr->ref_value[1]);
}
void
nvfx_state_blend_colour_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
struct pipe_blend_color *bcol = &nvfx->blend_colour;
BEGIN_RING(chan, eng3d, NV30_3D_BLEND_COLOR, 1);
OUT_RING(chan, ((float_to_ubyte(bcol->color[3]) << 24) |
(float_to_ubyte(bcol->color[0]) << 16) |
(float_to_ubyte(bcol->color[1]) << 8) |
(float_to_ubyte(bcol->color[2]) << 0)));
}
void
nvfx_state_stipple_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
BEGIN_RING(chan, eng3d, NV30_3D_POLYGON_STIPPLE_PATTERN(0), 32);
OUT_RINGp(chan, nvfx->stipple, 32);
}
static void
nvfx_coord_conventions_validate(struct nvfx_context* nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
unsigned value = nvfx->hw_fragprog->coord_conventions;
if(value & NV30_3D_COORD_CONVENTIONS_ORIGIN_INVERTED)
value |= nvfx->framebuffer.height << NV30_3D_COORD_CONVENTIONS_HEIGHT__SHIFT;
BEGIN_RING(chan, eng3d, NV30_3D_COORD_CONVENTIONS, 1);
OUT_RING(chan, value);
}
static void
nvfx_ucp_validate(struct nvfx_context* nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
unsigned enables[] =
{
NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0,
NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE1,
NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE2,
NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE3,
NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE4,
NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE5
};
unsigned i, enable = 0, nr = 0;
for (i = 0; i < 6; i++) {
if (nvfx->rasterizer->pipe.clip_plane_enable & (1 << i)) {
enable |= enables[i];
nr = i+1;
}
}
if(!nvfx->use_vp_clipping)
{
BEGIN_RING(chan, eng3d, NV30_3D_VP_CLIP_PLANES_ENABLE, 1);
OUT_RING(chan, 0);
BEGIN_RING(chan, eng3d, NV30_3D_VP_CLIP_PLANE(0, 0),
nr * 4);
OUT_RINGp(chan, &nvfx->clip.ucp[0][0], nr * 4);
}
BEGIN_RING(chan, eng3d, NV30_3D_VP_CLIP_PLANES_ENABLE, 1);
OUT_RING(chan, enable);
}
static void
nvfx_vertprog_ucp_validate(struct nvfx_context* nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
unsigned i;
struct nvfx_vertex_program* vp = nvfx->hw_vertprog;
unsigned enable = nvfx->rasterizer->pipe.clip_plane_enable;
unsigned nr = util_bitcount(enable);
if(nr != vp->clip_nr)
{
unsigned idx;
/* remove last instruction bit */
if(vp->clip_nr >= 0)
{
idx = vp->nr_insns - 7 + vp->clip_nr;
BEGIN_RING(chan, eng3d, NV30_3D_VP_UPLOAD_FROM_ID, 1);
OUT_RING(chan, vp->exec->start + idx);
BEGIN_RING(chan, eng3d, NV30_3D_VP_UPLOAD_INST(0), 4);
OUT_RINGp (chan, vp->insns[idx].data, 4);
}
/* set last instruction bit */
idx = vp->nr_insns - 7 + nr;
BEGIN_RING(chan, eng3d, NV30_3D_VP_UPLOAD_FROM_ID, 1);
OUT_RING(chan, vp->exec->start + idx);
BEGIN_RING(chan, eng3d, NV30_3D_VP_UPLOAD_INST(0), 4);
OUT_RINGp(chan, vp->insns[idx].data, 3);
OUT_RING(chan, vp->insns[idx].data[3] | 1);
vp->clip_nr = nr;
}
// TODO: only do this for the ones changed
for(i = 0; enable; ++i)
{
unsigned index = ffs(enable) - 1;
enable &= ~(1 << index);
BEGIN_RING(chan, eng3d, NV30_3D_VP_UPLOAD_CONST_ID, 5);
OUT_RING(chan, vp->data->start + i);
OUT_RINGp (chan, nvfx->clip.ucp[index], 4);
}
}
static boolean
nvfx_state_validate_common(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
unsigned dirty;
unsigned still_dirty = 0;
boolean flush_tex_cache = FALSE;
if(nvfx != nvfx->screen->cur_ctx)
{
nvfx->dirty = ~0;
nvfx->hw_vtxelt_nr = 16;
nvfx->hw_pointsprite_control = -1;
nvfx->hw_vp_output = -1;
nvfx->screen->cur_ctx = nvfx;
nvfx->relocs_needed = NVFX_RELOCATE_ALL;
}
dirty = nvfx->dirty;
if(nvfx->render_mode == HW)
{
if(dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_VERTCONST))
{
if(!nvfx_vertprog_validate(nvfx))
return FALSE;
}
if(dirty & NVFX_NEW_ARRAYS)
{
if(!nvfx_vbo_validate(nvfx))
return FALSE;
}
if(dirty & NVFX_NEW_INDEX)
{
if(nvfx->use_index_buffer)
nvfx_idxbuf_validate(nvfx);
else
still_dirty = NVFX_NEW_INDEX;
}
}
else
{
if(dirty & NVFX_NEW_VERTPROG) {
assert(nvfx_vertprog_validate(nvfx));
nvfx_vbo_swtnl_validate(nvfx);
}
}
if(dirty & NVFX_NEW_SAMPLER) {
/* XXX: we take the big hammer here, I have no idea why this is needed
to make this work properly */
nvfx->dirty &= ~NVFX_NEW_SAMPLER;
nvfx_fragtex_validate(nvfx);
// TODO: only set this if really necessary
flush_tex_cache = TRUE;
}
if(dirty & NVFX_NEW_RAST)
sb_emit(chan, nvfx->rasterizer->sb, nvfx->rasterizer->sb_len);
if(dirty & NVFX_NEW_SCISSOR)
nvfx_state_scissor_validate(nvfx);
if(dirty & NVFX_NEW_STIPPLE)
nvfx_state_stipple_validate(nvfx);
if(nvfx->dirty & (NVFX_NEW_UCP | NVFX_NEW_RAST))
nvfx_ucp_validate(nvfx);
if(nvfx->use_vp_clipping && (nvfx->dirty &
(NVFX_NEW_UCP | NVFX_NEW_VERTPROG |
NVFX_NEW_RAST)))
nvfx_vertprog_ucp_validate(nvfx);
if(dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST |
NVFX_NEW_VERTPROG | NVFX_NEW_SPRITE))
{
nvfx_fragprog_validate(nvfx);
if(dirty & NVFX_NEW_FRAGPROG)
flush_tex_cache = TRUE; // TODO: do we need this?
}
if(nvfx->is_nv4x)
{
unsigned vp_output = nvfx->hw_vertprog->or | nvfx->hw_fragprog->or;
vp_output |= ((1 << (nvfx->rasterizer->pipe.clip_plane_enable & 63)) - 1) << 6;
if(vp_output != nvfx->hw_vp_output)
{
BEGIN_RING(chan, eng3d, NV40_3D_VP_RESULT_EN, 1);
OUT_RING(chan, vp_output);
nvfx->hw_vp_output = vp_output;
}
}
if(dirty & NVFX_NEW_FB)
nvfx_framebuffer_validate(nvfx);
if(dirty & NVFX_NEW_BLEND)
sb_emit(chan, nvfx->blend->sb, nvfx->blend->sb_len);
if(dirty & NVFX_NEW_BCOL)
nvfx_state_blend_colour_validate(nvfx);
if(dirty & NVFX_NEW_ZSA)
sb_emit(chan, nvfx->zsa->sb, nvfx->zsa->sb_len);
if(dirty & NVFX_NEW_SR)
nvfx_state_sr_validate(nvfx);
/* XXX: nv3x needs viewport revalidation after RAST or ZSA change */
if(dirty & (NVFX_NEW_VIEWPORT | NVFX_NEW_RAST | NVFX_NEW_ZSA))
{
nvfx_state_viewport_validate(nvfx);
}
if(dirty & (NVFX_NEW_ZSA | NVFX_NEW_FB))
{
BEGIN_RING(chan, eng3d, NV30_3D_DEPTH_WRITE_ENABLE, 2);
OUT_RING(chan, nvfx->framebuffer.zsbuf &&
nvfx->zsa->pipe.depth.writemask);
OUT_RING(chan, nvfx->framebuffer.zsbuf &&
nvfx->zsa->pipe.depth.enabled);
}
if(dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FB))
nvfx_coord_conventions_validate(nvfx);
if(flush_tex_cache && nvfx->is_nv4x)
{
BEGIN_RING(chan, eng3d, NV40_3D_TEX_CACHE_CTL, 1);
OUT_RING(chan, 2);
BEGIN_RING(chan, eng3d, NV40_3D_TEX_CACHE_CTL, 1);
OUT_RING(chan, 1);
}
nvfx->dirty = dirty & still_dirty;
return TRUE;
}
inline void
nvfx_state_relocate(struct nvfx_context *nvfx, unsigned relocs)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
/* we need to ensure there is enough space to output relocations in one go */
const unsigned max_relocs = 0
+ 16 /* vertex buffers, incl. dma flag */
+ 2 /* index buffer plus format+dma flag */
+ 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */
+ 2 * 16 /* fragment textures plus format+dma flag */
+ 2 * 4 /* vertex textures plus format+dma flag */
+ 1 /* fragprog incl dma flag */
;
MARK_RING(chan, max_relocs * 2, max_relocs * 2);
if(relocs & NVFX_RELOCATE_FRAMEBUFFER)
nvfx_framebuffer_relocate(nvfx);
if(relocs & NVFX_RELOCATE_FRAGTEX)
nvfx_fragtex_relocate(nvfx);
if(relocs & NVFX_RELOCATE_FRAGPROG)
nvfx_fragprog_relocate(nvfx);
if(relocs & NVFX_RELOCATE_VTXBUF)
nvfx_vbo_relocate(nvfx);
if(relocs & NVFX_RELOCATE_IDXBUF)
nvfx_idxbuf_relocate(nvfx);
}
boolean
nvfx_state_validate(struct nvfx_context *nvfx)
{
if (nvfx->render_mode != HW) {
/* Don't even bother trying to go back to hw if none
* of the states that caused swtnl previously have changed.
*/
if ((nvfx->fallback_swtnl & nvfx->dirty)
!= nvfx->fallback_swtnl)
return FALSE;
/* Attempt to go to hwtnl again */
nvfx->dirty |= (NVFX_NEW_VIEWPORT |
NVFX_NEW_VERTPROG |
NVFX_NEW_ARRAYS);
nvfx->render_mode = HW;
}
if(!nvfx_state_validate_common(nvfx))
return FALSE;
return TRUE;
}
boolean
nvfx_state_validate_swtnl(struct nvfx_context *nvfx)
{
struct draw_context *draw = nvfx->draw;
/* Setup for swtnl */
if (nvfx->render_mode == HW) {
static boolean warned = FALSE;
if(!warned) {
NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx->fallback_swtnl);
warned = TRUE;
}
nvfx->pipe.flush(&nvfx->pipe, NULL);
nvfx->dirty |= (NVFX_NEW_VIEWPORT |
NVFX_NEW_VERTPROG |
NVFX_NEW_ARRAYS);
nvfx->render_mode = SWTNL;
}
if (nvfx->draw_dirty & NVFX_NEW_VERTPROG) {
if(!nvfx->vertprog->draw_vs)
nvfx->vertprog->draw_vs = draw_create_vertex_shader(draw, &nvfx->vertprog->pipe);
draw_bind_vertex_shader(draw, nvfx->vertprog->draw_vs);
}
if (nvfx->draw_dirty & NVFX_NEW_RAST)
draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe,
nvfx->rasterizer);
if (nvfx->draw_dirty & NVFX_NEW_UCP)
draw_set_clip_state(draw, &nvfx->clip);
if (nvfx->draw_dirty & NVFX_NEW_VIEWPORT)
draw_set_viewport_state(draw, &nvfx->viewport);
if (nvfx->draw_dirty & NVFX_NEW_ARRAYS) {
draw_set_vertex_buffers(draw, nvfx->vtxbuf_nr, nvfx->vtxbuf);
draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe);
}
if (nvfx->draw_dirty & NVFX_NEW_INDEX)
draw_set_index_buffer(draw, &nvfx->idxbuf);
nvfx_state_validate_common(nvfx);
nvfx->draw_dirty = 0;
return TRUE;
}

View File

@ -1,290 +0,0 @@
#include "nvfx_context.h"
#include "nvfx_resource.h"
#include "util/u_format.h"
static inline boolean
nvfx_surface_linear_target(struct pipe_surface* surf)
{
return !!((struct nvfx_miptree*)surf->texture)->linear_pitch;
}
static void
nvfx_surface_get_render_target(struct pipe_surface* surf,
struct nvfx_render_target* target)
{
struct nvfx_surface* ns = (struct nvfx_surface*)surf;
target->bo = ((struct nvfx_miptree*)surf->texture)->base.bo;
target->offset = ns->offset;
target->pitch = align(ns->pitch, 64);
assert(target->pitch);
}
void
nvfx_framebuffer_validate(struct nvfx_context *nvfx)
{
struct pipe_framebuffer_state *fb = &nvfx->framebuffer;
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
uint32_t rt_enable, rt_format;
int i;
unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
unsigned w = fb->width;
unsigned h = fb->height;
int all_swizzled =1 , cb_format = 0;
/* do some sanity checks on the render target state and check if the targets
* are swizzled
*/
nvfx->is_nv4x ? assert(fb->nr_cbufs <= 4) : assert(fb->nr_cbufs <= 1);
if(fb->nr_cbufs && fb->zsbuf)
assert(util_format_get_blocksize(fb->cbufs[0]->format) ==
util_format_get_blocksize(fb->zsbuf->format));
for(i = 0; i < fb->nr_cbufs; i++) {
if(cb_format)
assert(cb_format == fb->cbufs[i]->format);
else
cb_format = fb->cbufs[i]->format;
if(nvfx_surface_linear_target(fb->cbufs[i]))
all_swizzled = 0;
}
if(fb->zsbuf && nvfx_surface_linear_target(fb->zsbuf))
all_swizzled = 0;
rt_enable = (NV30_3D_RT_ENABLE_COLOR0 << fb->nr_cbufs) - 1;
if(rt_enable & (NV30_3D_RT_ENABLE_COLOR1 |
NV40_3D_RT_ENABLE_COLOR2 | NV40_3D_RT_ENABLE_COLOR3))
rt_enable |= NV30_3D_RT_ENABLE_MRT;
for(i = 0; i < fb->nr_cbufs; i++)
nvfx_surface_get_render_target(fb->cbufs[i], &nvfx->hw_rt[i]);
for(; i < 4; ++i)
nvfx->hw_rt[i].bo = NULL;
nvfx->hw_zeta.bo = NULL;
if(fb->zsbuf) {
nvfx_surface_get_render_target(fb->zsbuf, &nvfx->hw_zeta);
assert(util_format_get_stride(fb->zsbuf->format, fb->width) <=
nvfx->hw_zeta.pitch);
}
if(all_swizzled) {
/* hardware rounds down render target offset to 64 bytes,
* but surfaces with a size of 2x2 pixel (16bpp) or 1x1 pixel (32bpp)
* have an unaligned start address, for those two important square
* formats we can hack around this limitation by adjusting the viewport
*/
if(nvfx->hw_rt[0].offset & 63) {
int delta = nvfx->hw_rt[0].offset & 63;
h = 2;
w = 16;
nvfx->viewport.translate[0] += delta /
(util_format_get_blocksize(fb->cbufs[0]->format) * 2);
nvfx->dirty |= NVFX_NEW_VIEWPORT;
}
rt_format = NV30_3D_RT_FORMAT_TYPE_SWIZZLED |
(util_logbase2(w) << NV30_3D_RT_FORMAT_LOG2_WIDTH__SHIFT) |
(util_logbase2(h) << NV30_3D_RT_FORMAT_LOG2_HEIGHT__SHIFT);
} else {
rt_format = NV30_3D_RT_FORMAT_TYPE_LINEAR;
}
if(fb->nr_cbufs > 0) {
switch (fb->cbufs[0]->format) {
case PIPE_FORMAT_B8G8R8X8_UNORM:
rt_format |= NV30_3D_RT_FORMAT_COLOR_X8R8G8B8;
break;
case PIPE_FORMAT_B8G8R8A8_UNORM:
case 0:
rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
break;
case PIPE_FORMAT_R8G8B8X8_UNORM:
rt_format |= NV30_3D_RT_FORMAT_COLOR_X8B8G8R8;
break;
case PIPE_FORMAT_R8G8B8A8_UNORM:
rt_format |= NV30_3D_RT_FORMAT_COLOR_A8B8G8R8;
break;
case PIPE_FORMAT_B5G6R5_UNORM:
rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
break;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
rt_format |= NV30_3D_RT_FORMAT_COLOR_A32B32G32R32_FLOAT;
break;
case PIPE_FORMAT_R16G16B16A16_FLOAT:
rt_format |= NV30_3D_RT_FORMAT_COLOR_A16B16G16R16_FLOAT;
break;
default:
assert(0);
}
} else if(fb->zsbuf && util_format_get_blocksize(fb->zsbuf->format) == 2)
rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
else
rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
if(fb->zsbuf) {
switch (fb->zsbuf->format) {
case PIPE_FORMAT_Z16_UNORM:
rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
case 0:
rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
break;
default:
assert(0);
}
} else if(fb->nr_cbufs && util_format_get_blocksize(fb->cbufs[0]->format) == 2)
rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
else
rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
MARK_RING(chan, 42, 10);
if ((rt_enable & NV30_3D_RT_ENABLE_COLOR0) || fb->zsbuf) {
struct nvfx_render_target *rt0 = &nvfx->hw_rt[0];
uint32_t pitch;
if(!(rt_enable & NV30_3D_RT_ENABLE_COLOR0))
rt0 = &nvfx->hw_zeta;
pitch = rt0->pitch;
if(!nvfx->is_nv4x)
{
if (nvfx->hw_zeta.bo)
pitch |= (nvfx->hw_zeta.pitch << 16);
else
pitch |= (pitch << 16);
}
//printf("rendering to bo %p [%i] at offset %i with pitch %i\n", rt0->bo, rt0->bo->handle, rt0->offset, pitch);
BEGIN_RING(chan, eng3d, NV30_3D_DMA_COLOR0, 1);
OUT_RELOC(chan, rt0->bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
BEGIN_RING(chan, eng3d, NV30_3D_COLOR0_PITCH, 2);
OUT_RING(chan, pitch);
OUT_RELOC(chan, rt0->bo,
rt0->offset, rt_flags | NOUVEAU_BO_LOW,
0, 0);
}
if (rt_enable & NV30_3D_RT_ENABLE_COLOR1) {
BEGIN_RING(chan, eng3d, NV30_3D_DMA_COLOR1, 1);
OUT_RELOC(chan, nvfx->hw_rt[1].bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
BEGIN_RING(chan, eng3d, NV30_3D_COLOR1_OFFSET, 2);
OUT_RELOC(chan, nvfx->hw_rt[1].bo,
nvfx->hw_rt[1].offset, rt_flags | NOUVEAU_BO_LOW,
0, 0);
OUT_RING(chan, nvfx->hw_rt[1].pitch);
}
if(nvfx->is_nv4x)
{
if (rt_enable & NV40_3D_RT_ENABLE_COLOR2) {
BEGIN_RING(chan, eng3d, NV40_3D_DMA_COLOR2, 1);
OUT_RELOC(chan, nvfx->hw_rt[2].bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
BEGIN_RING(chan, eng3d, NV40_3D_COLOR2_OFFSET, 1);
OUT_RELOC(chan, nvfx->hw_rt[2].bo,
nvfx->hw_rt[2].offset, rt_flags | NOUVEAU_BO_LOW,
0, 0);
BEGIN_RING(chan, eng3d, NV40_3D_COLOR2_PITCH, 1);
OUT_RING(chan, nvfx->hw_rt[2].pitch);
}
if (rt_enable & NV40_3D_RT_ENABLE_COLOR3) {
BEGIN_RING(chan, eng3d, NV40_3D_DMA_COLOR3, 1);
OUT_RELOC(chan, nvfx->hw_rt[3].bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
BEGIN_RING(chan, eng3d, NV40_3D_COLOR3_OFFSET, 1);
OUT_RELOC(chan, nvfx->hw_rt[3].bo,
nvfx->hw_rt[3].offset, rt_flags | NOUVEAU_BO_LOW,
0, 0);
BEGIN_RING(chan, eng3d, NV40_3D_COLOR3_PITCH, 1);
OUT_RING(chan, nvfx->hw_rt[3].pitch);
}
}
if (fb->zsbuf) {
BEGIN_RING(chan, eng3d, NV30_3D_DMA_ZETA, 1);
OUT_RELOC(chan, nvfx->hw_zeta.bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
BEGIN_RING(chan, eng3d, NV30_3D_ZETA_OFFSET, 1);
/* TODO: reverse engineer LMA */
OUT_RELOC(chan, nvfx->hw_zeta.bo,
nvfx->hw_zeta.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0);
if(nvfx->is_nv4x) {
BEGIN_RING(chan, eng3d, NV40_3D_ZETA_PITCH, 1);
OUT_RING(chan, nvfx->hw_zeta.pitch);
}
}
else if(nvfx->is_nv4x) {
BEGIN_RING(chan, eng3d, NV40_3D_ZETA_PITCH, 1);
OUT_RING(chan, 64);
}
BEGIN_RING(chan, eng3d, NV30_3D_RT_ENABLE, 1);
OUT_RING(chan, rt_enable);
BEGIN_RING(chan, eng3d, NV30_3D_RT_HORIZ, 3);
OUT_RING(chan, (w << 16) | 0);
OUT_RING(chan, (h << 16) | 0);
OUT_RING(chan, rt_format);
BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_HORIZ, 2);
OUT_RING(chan, (w << 16) | 0);
OUT_RING(chan, (h << 16) | 0);
BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_CLIP_HORIZ(0), 2);
OUT_RING(chan, ((w - 1) << 16) | 0);
OUT_RING(chan, ((h - 1) << 16) | 0);
if(!nvfx->is_nv4x) {
/* Wonder why this is needed, context should all be set to zero on init */
/* TODO: we can most likely remove this, after putting it in context init */
BEGIN_RING(chan, eng3d, NV30_3D_VIEWPORT_TX_ORIGIN, 1);
OUT_RING(chan, 0);
}
nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAMEBUFFER;
}
void
nvfx_framebuffer_relocate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
rt_flags |= NOUVEAU_BO_DUMMY;
MARK_RING(chan, 20, 20);
#define DO_(var, pfx, name) \
if(var.bo) { \
OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_DMA_##name, 1), rt_flags, 0, 0); \
OUT_RELOC(chan, var.bo, 0, \
rt_flags | NOUVEAU_BO_OR, \
chan->vram->handle, chan->gart->handle); \
OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_##name##_OFFSET, 1), rt_flags, 0, 0); \
OUT_RELOC(chan, var.bo, \
var.offset, rt_flags | NOUVEAU_BO_LOW, \
0, 0); \
}
#define DO(pfx, num) DO_(nvfx->hw_rt[num], pfx, COLOR##num)
DO(NV30, 0);
DO(NV30, 1);
DO(NV40, 2);
DO(NV40, 3);
DO_(nvfx->hw_zeta, NV30, ZETA);
nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAMEBUFFER;
}

View File

@ -1,413 +0,0 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 TUNGSTEN 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.
*
**************************************************************************/
#include "pipe/p_context.h"
#include "pipe/p_format.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pack_color.h"
#include "util/u_blitter.h"
#include "util/u_surface.h"
#include "nouveau/nouveau_winsys.h"
#include "nouveau/nouveau_screen.h"
#include "nvfx_context.h"
#include "nvfx_screen.h"
#include "nvfx_resource.h"
#include "nv04_2d.h"
#include <nouveau/nouveau_bo.h>
static INLINE void
nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format)
{
unsigned bits = util_format_get_blocksizebits(format);
unsigned shift = 0;
rgn->one_bits = 0;
switch(bits)
{
case 8:
rgn->bpps = 0;
break;
case 16:
rgn->bpps = 1;
if(format == PIPE_FORMAT_B5G5R5X1_UNORM)
rgn->one_bits = 1;
break;
case 32:
rgn->bpps = 2;
if(format == PIPE_FORMAT_R8G8B8X8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM)
rgn->one_bits = 8;
break;
case 64:
rgn->bpps = 2;
shift = 1;
break;
case 128:
rgn->bpps = 2;
shift = 2;
break;
}
if(shift) {
rgn->x = util_format_get_nblocksx(format, rgn->x) << shift;
rgn->y = util_format_get_nblocksy(format, rgn->y);
rgn->w <<= shift;
}
}
static INLINE void
nvfx_region_init_for_surface(struct nv04_region* rgn, struct nvfx_surface* surf, unsigned x, unsigned y, boolean for_write)
{
rgn->x = x;
rgn->y = y;
rgn->z = 0;
rgn->bo = ((struct nvfx_resource*)surf->base.texture)->bo;
rgn->offset = surf->offset;
if(surf->base.texture->flags & NOUVEAU_RESOURCE_FLAG_LINEAR)
rgn->pitch = surf->pitch;
else {
rgn->pitch = 0;
rgn->z = surf->base.u.tex.first_layer;
rgn->w = surf->base.width;
rgn->h = surf->base.height;
rgn->d = u_minify(surf->base.texture->depth0, surf->base.u.tex.level);
}
nvfx_region_set_format(rgn, surf->base.format);
if(!rgn->pitch)
nv04_region_try_to_linearize(rgn);
}
static INLINE void
nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource* pt, unsigned level, unsigned x, unsigned y, unsigned z, boolean for_write)
{
if(pt->target != PIPE_BUFFER)
{
struct nvfx_surface* ns = (struct nvfx_surface*)util_surfaces_peek(&((struct nvfx_miptree*)pt)->surfaces, pt, level, z);
if(ns)
{
nvfx_region_init_for_surface(rgn, ns, x, y, for_write);
return;
}
}
rgn->bo = ((struct nvfx_resource*)pt)->bo;
rgn->offset = nvfx_subresource_offset(pt, z, level, z);
rgn->x = x;
rgn->y = y;
if(pt->flags & NOUVEAU_RESOURCE_FLAG_LINEAR)
{
rgn->pitch = nvfx_subresource_pitch(pt, level);
rgn->z = 0;
}
else
{
rgn->pitch = 0;
rgn->z = z;
rgn->w = u_minify(pt->width0, level);
rgn->h = u_minify(pt->height0, level);
rgn->d = u_minify(pt->depth0, level);
}
nvfx_region_set_format(rgn, pt->format);
if(!rgn->pitch)
nv04_region_try_to_linearize(rgn);
}
// don't save index buffer because blitter doesn't setit
static struct blitter_context*
nvfx_get_blitter(struct pipe_context* pipe, int copy)
{
struct nvfx_context* nvfx = nvfx_context(pipe);
struct blitter_context** pblitter;
struct blitter_context* blitter;
assert(nvfx->blitters_in_use < Elements(nvfx->blitter));
if(nvfx->query && !nvfx->blitters_in_use)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
BEGIN_RING(chan, eng3d, NV30_3D_QUERY_ENABLE, 1);
OUT_RING(chan, 0);
}
pblitter = &nvfx->blitter[nvfx->blitters_in_use++];
if(!*pblitter)
*pblitter = util_blitter_create(pipe);
blitter = *pblitter;
util_blitter_save_blend(blitter, nvfx->blend);
util_blitter_save_depth_stencil_alpha(blitter, nvfx->zsa);
util_blitter_save_stencil_ref(blitter, &nvfx->stencil_ref);
util_blitter_save_rasterizer(blitter, nvfx->rasterizer);
util_blitter_save_fragment_shader(blitter, nvfx->fragprog);
util_blitter_save_vertex_shader(blitter, nvfx->vertprog);
util_blitter_save_viewport(blitter, &nvfx->viewport);
util_blitter_save_framebuffer(blitter, &nvfx->framebuffer);
util_blitter_save_vertex_elements(blitter, nvfx->vtxelt);
util_blitter_save_vertex_buffers(blitter, nvfx->vtxbuf_nr, nvfx->vtxbuf);
if(copy)
{
util_blitter_save_fragment_sampler_states(blitter, nvfx->nr_samplers, (void**)nvfx->tex_sampler);
util_blitter_save_fragment_sampler_views(blitter, nvfx->nr_textures, nvfx->fragment_sampler_views);
}
return blitter;
}
static inline void
nvfx_put_blitter(struct pipe_context* pipe, struct blitter_context* blitter)
{
struct nvfx_context* nvfx = nvfx_context(pipe);
--nvfx->blitters_in_use;
assert(nvfx->blitters_in_use >= 0);
if(nvfx->query && !nvfx->blitters_in_use)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
BEGIN_RING(chan, eng3d, NV30_3D_QUERY_ENABLE, 1);
OUT_RING(chan, 1);
}
}
static unsigned
nvfx_region_clone(struct nv04_2d_context* ctx, struct nv04_region* rgn, unsigned w, unsigned h, boolean for_read)
{
unsigned begin = nv04_region_begin(rgn, w, h);
unsigned end = nv04_region_end(rgn, w, h);
unsigned size = end - begin;
struct nouveau_bo* bo = 0;
nouveau_bo_new(rgn->bo->device, NOUVEAU_BO_MAP | NOUVEAU_BO_GART, 256, size, &bo);
if(for_read || (size > ((w * h) << rgn->bpps)))
nv04_memcpy(ctx, bo, 0, rgn->bo, rgn->offset + begin, size);
rgn->bo = bo;
rgn->offset = -begin;
return begin;
}
static void
nvfx_resource_copy_region(struct pipe_context *pipe,
struct pipe_resource *dstr, unsigned dst_level,
unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *srcr, unsigned src_level,
const struct pipe_box *src_box)
{
static int copy_threshold = -1;
struct nv04_2d_context *ctx = nvfx_screen(pipe->screen)->eng2d;
struct nv04_region dst, src;
int dst_to_gpu;
int src_on_gpu;
boolean small;
int ret;
unsigned w = src_box->width;
unsigned h = src_box->height;
if(!w || !h)
return;
/* Fallback for buffers. */
if (dstr->target == PIPE_BUFFER && srcr->target == PIPE_BUFFER) {
util_resource_copy_region(pipe, dstr, dst_level, dstx, dsty, dstz,
srcr, src_level, src_box);
return;
}
if(copy_threshold < 0)
copy_threshold = debug_get_num_option("NOUVEAU_COPY_THRESHOLD", 4);
dst_to_gpu = dstr->usage != PIPE_USAGE_DYNAMIC && dstr->usage != PIPE_USAGE_STAGING;
src_on_gpu = nvfx_resource_on_gpu(srcr);
nvfx_region_init_for_subresource(&dst, dstr, dst_level, dstx, dsty, dstz, TRUE);
nvfx_region_init_for_subresource(&src, srcr, src_level, src_box->x, src_box->y, src_box->z, FALSE);
w = util_format_get_stride(dstr->format, w) >> dst.bpps;
h = util_format_get_nblocksy(dstr->format, h);
small = (w * h <= copy_threshold);
if((!dst_to_gpu || !src_on_gpu) && small)
ret = -1; /* use the CPU */
else
ret = nv04_region_copy_2d(ctx, &dst, &src, w, h, dst_to_gpu, src_on_gpu);
if(!ret)
{}
else if(ret > 0
&& dstr->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)
&& srcr->bind & PIPE_BIND_SAMPLER_VIEW)
{
/* this currently works because we hack the bind flags on resource creation to be
* the maximum set that the resource type actually supports
*
* TODO: perhaps support reinterpreting the formats
*/
struct blitter_context* blitter = nvfx_get_blitter(pipe, 1);
util_blitter_copy_texture(blitter, dstr, dst_level, dstx, dsty, dstz, srcr, src_level, src_box, TRUE);
nvfx_put_blitter(pipe, blitter);
}
else
{
struct nv04_region dstt = dst;
struct nv04_region srct = src;
unsigned dstbegin = 0;
if(!small)
{
if(src_on_gpu)
nvfx_region_clone(ctx, &srct, w, h, TRUE);
if(dst_to_gpu)
dstbegin = nvfx_region_clone(ctx, &dstt, w, h, FALSE);
}
nv04_region_copy_cpu(&dstt, &srct, w, h);
if(srct.bo != src.bo)
nouveau_screen_bo_release(pipe->screen, srct.bo);
if(dstt.bo != dst.bo)
{
nv04_memcpy(ctx, dst.bo, dst.offset + dstbegin, dstt.bo, 0, dstt.bo->size);
nouveau_screen_bo_release(pipe->screen, dstt.bo);
}
}
}
static int
nvfx_surface_fill(struct pipe_context* pipe, struct pipe_surface *dsts,
unsigned dx, unsigned dy, unsigned w, unsigned h, unsigned value)
{
struct nv04_2d_context *ctx = nvfx_screen(pipe->screen)->eng2d;
struct nv04_region dst;
int ret;
/* Always try to use the GPU right now, if possible
* If the user wanted the surface data on the CPU, he would have cleared with memset (hopefully) */
// we don't care about interior pixel order since we set all them to the same value
nvfx_region_init_for_surface(&dst, (struct nvfx_surface*)dsts, dx, dy, TRUE);
w = util_format_get_stride(dsts->format, w) >> dst.bpps;
h = util_format_get_nblocksy(dsts->format, h);
ret = nv04_region_fill_2d(ctx, &dst, w, h, value);
if(ret > 0 && dsts->texture->bind & PIPE_BIND_RENDER_TARGET)
return 1;
else if(ret)
{
struct nv04_region dstt = dst;
unsigned dstbegin = 0;
if(nvfx_resource_on_gpu(dsts->texture))
dstbegin = nvfx_region_clone(ctx, &dstt, w, h, FALSE);
nv04_region_fill_cpu(&dstt, w, h, value);
if(dstt.bo != dst.bo)
{
nv04_memcpy(ctx, dst.bo, dst.offset + dstbegin, dstt.bo, 0, dstt.bo->size);
nouveau_screen_bo_release(pipe->screen, dstt.bo);
}
}
return 0;
}
void
nvfx_screen_surface_takedown(struct pipe_screen *pscreen)
{
nv04_2d_context_takedown(nvfx_screen(pscreen)->eng2d);
nvfx_screen(pscreen)->eng2d = 0;
}
int
nvfx_screen_surface_init(struct pipe_screen *pscreen)
{
struct nv04_2d_context* ctx = nv04_2d_context_init(nouveau_screen(pscreen)->channel);
if(!ctx)
return -1;
nvfx_screen(pscreen)->eng2d = ctx;
return 0;
}
static void
nvfx_clear_render_target(struct pipe_context *pipe,
struct pipe_surface *dst,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
union util_color uc;
util_pack_color(color->f, dst->format, &uc);
if(util_format_get_blocksizebits(dst->format) > 32
|| nvfx_surface_fill(pipe, dst, dstx, dsty, width, height, uc.ui))
{
// TODO: probably should use hardware clear here instead if possible
struct blitter_context* blitter = nvfx_get_blitter(pipe, 0);
util_blitter_clear_render_target(blitter, dst, color, dstx, dsty, width, height);
nvfx_put_blitter(pipe, blitter);
}
}
static void
nvfx_clear_depth_stencil(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
if(util_format_get_blocksizebits(dst->format) > 32
|| nvfx_surface_fill(pipe, dst, dstx, dsty, width, height, util_pack_z_stencil(dst->format, depth, stencil)))
{
// TODO: probably should use hardware clear here instead if possible
struct blitter_context* blitter = nvfx_get_blitter(pipe, 0);
util_blitter_clear_depth_stencil(blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height);
nvfx_put_blitter(pipe, blitter);
}
}
void
nvfx_init_surface_functions(struct nvfx_context *nvfx)
{
nvfx->pipe.resource_copy_region = nvfx_resource_copy_region;
nvfx->pipe.clear_render_target = nvfx_clear_render_target;
nvfx->pipe.clear_depth_stencil = nvfx_clear_depth_stencil;
}

View File

@ -1,175 +0,0 @@
#ifndef NVFX_TEX_H_
#define NVFX_TEX_H_
#include "util/u_math.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
static inline unsigned
nvfx_tex_wrap_mode(unsigned wrap) {
unsigned ret;
switch (wrap) {
case PIPE_TEX_WRAP_REPEAT:
ret = NV30_3D_TEX_WRAP_S_REPEAT;
break;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
ret = NV30_3D_TEX_WRAP_S_MIRRORED_REPEAT;
break;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
ret = NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE;
break;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
ret = NV30_3D_TEX_WRAP_S_CLAMP_TO_BORDER;
break;
case PIPE_TEX_WRAP_CLAMP:
ret = NV30_3D_TEX_WRAP_S_CLAMP;
break;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
ret = NV40_3D_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE;
break;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
ret = NV40_3D_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER;
break;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
ret = NV40_3D_TEX_WRAP_S_MIRROR_CLAMP;
break;
default:
assert(0);
ret = NV30_3D_TEX_WRAP_S_REPEAT;
break;
}
return ret >> NV30_3D_TEX_WRAP_S__SHIFT;
}
static inline unsigned
nvfx_tex_wrap_compare_mode(unsigned func)
{
switch (func) {
case PIPE_FUNC_NEVER:
return NV30_3D_TEX_WRAP_RCOMP_NEVER;
case PIPE_FUNC_GREATER:
return NV30_3D_TEX_WRAP_RCOMP_GREATER;
case PIPE_FUNC_EQUAL:
return NV30_3D_TEX_WRAP_RCOMP_EQUAL;
case PIPE_FUNC_GEQUAL:
return NV30_3D_TEX_WRAP_RCOMP_GEQUAL;
case PIPE_FUNC_LESS:
return NV30_3D_TEX_WRAP_RCOMP_LESS;
case PIPE_FUNC_NOTEQUAL:
return NV30_3D_TEX_WRAP_RCOMP_NOTEQUAL;
case PIPE_FUNC_LEQUAL:
return NV30_3D_TEX_WRAP_RCOMP_LEQUAL;
case PIPE_FUNC_ALWAYS:
return NV30_3D_TEX_WRAP_RCOMP_ALWAYS;
default:
assert(0);
return 0;
}
}
static inline unsigned nvfx_tex_filter(const struct pipe_sampler_state* cso)
{
unsigned filter = 0;
switch (cso->mag_img_filter) {
case PIPE_TEX_FILTER_LINEAR:
filter |= NV30_3D_TEX_FILTER_MAG_LINEAR;
break;
case PIPE_TEX_FILTER_NEAREST:
default:
filter |= NV30_3D_TEX_FILTER_MAG_NEAREST;
break;
}
switch (cso->min_img_filter) {
case PIPE_TEX_FILTER_LINEAR:
switch (cso->min_mip_filter) {
case PIPE_TEX_MIPFILTER_NEAREST:
filter |= NV30_3D_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST;
break;
case PIPE_TEX_MIPFILTER_LINEAR:
filter |= NV30_3D_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR;
break;
case PIPE_TEX_MIPFILTER_NONE:
default:
filter |= NV30_3D_TEX_FILTER_MIN_LINEAR;
break;
}
break;
case PIPE_TEX_FILTER_NEAREST:
default:
switch (cso->min_mip_filter) {
case PIPE_TEX_MIPFILTER_NEAREST:
filter |= NV30_3D_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST;
break;
case PIPE_TEX_MIPFILTER_LINEAR:
filter |= NV30_3D_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR;
break;
case PIPE_TEX_MIPFILTER_NONE:
default:
filter |= NV30_3D_TEX_FILTER_MIN_NEAREST;
break;
}
break;
}
return filter;
}
static inline unsigned nvfx_tex_border_color(const float* border_color)
{
return ((float_to_ubyte(border_color[3]) << 24) |
(float_to_ubyte(border_color[0]) << 16) |
(float_to_ubyte(border_color[1]) << 8) |
(float_to_ubyte(border_color[2]) << 0));
}
struct nvfx_sampler_state {
uint32_t fmt;
uint32_t wrap;
uint32_t en;
uint32_t filt;
uint32_t bcol;
uint32_t min_lod;
uint32_t max_lod;
boolean compare;
};
struct nvfx_sampler_view {
struct pipe_sampler_view base;
int offset;
uint32_t swizzle;
uint32_t npot_size;
uint32_t filt;
uint32_t wrap_mask;
uint32_t wrap;
uint32_t lod_offset;
uint32_t max_lod_limit;
union
{
struct
{
uint32_t fmt[4]; /* nv30 has 4 entries, nv40 one */
int rect;
} nv30;
struct
{
uint32_t fmt[2]; /* nv30 has 4 entries, nv40 one */
uint32_t npot_size2; /* nv40 only */
} nv40;
uint32_t init_fmt;
} u;
};
struct nvfx_texture_format {
int fmt[6];
unsigned sign;
unsigned wrap;
unsigned char src[6];
unsigned char comp[6];
};
extern struct nvfx_texture_format nvfx_texture_formats[PIPE_FORMAT_COUNT];
#endif /* NVFX_TEX_H_ */

View File

@ -1,221 +0,0 @@
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_staging.h"
#include "nvfx_context.h"
#include "nvfx_screen.h"
#include "nvfx_state.h"
#include "nvfx_resource.h"
#include "nvfx_transfer.h"
struct nvfx_staging_transfer
{
struct util_staging_transfer base;
unsigned offset;
unsigned map_count;
};
struct pipe_transfer *
nvfx_transfer_new(struct pipe_context *pipe,
struct pipe_resource *pt,
unsigned level,
unsigned usage,
const struct pipe_box *box)
{
if((usage & (PIPE_TRANSFER_UNSYNCHRONIZED | PIPE_TRANSFER_DONTBLOCK)) == PIPE_TRANSFER_DONTBLOCK)
{
struct nouveau_bo* bo = ((struct nvfx_resource*)pt)->bo;
if(bo && nouveau_bo_busy(bo, NOUVEAU_BO_WR))
return NULL;
}
if(pt->target == PIPE_BUFFER)
{
// it would be nice if we could avoid all this ridiculous overhead...
struct pipe_transfer* tx;
struct nvfx_buffer* buffer = nvfx_buffer(pt);
tx = CALLOC_STRUCT(pipe_transfer);
if (!tx)
return NULL;
pipe_resource_reference(&tx->resource, pt);
tx->level = level;
tx->usage = usage;
tx->box = *box;
tx->layer_stride = tx->stride = util_format_get_stride(pt->format, box->width);
tx->data = buffer->data + util_format_get_stride(pt->format, box->x);
return tx;
}
else
{
struct nvfx_staging_transfer* tx;
boolean direct = !nvfx_resource_on_gpu(pt) && pt->flags & NOUVEAU_RESOURCE_FLAG_LINEAR;
tx = CALLOC_STRUCT(nvfx_staging_transfer);
if(!tx)
return NULL;
util_staging_transfer_init(pipe, pt, level, usage, box, direct, &tx->base);
if(direct)
{
tx->base.base.stride = nvfx_subresource_pitch(pt, level);
tx->base.base.layer_stride = tx->base.base.stride * u_minify(pt->height0, level);
tx->offset = nvfx_subresource_offset(pt, box->z, level, box->z)
+ util_format_get_2d_size(pt->format, tx->base.base.stride, box->y)
+ util_format_get_stride(pt->format, box->x);
}
else
{
tx->base.base.stride = nvfx_subresource_pitch(tx->base.staging_resource, 0);
tx->base.base.layer_stride = tx->base.base.stride * tx->base.staging_resource->height0;
tx->offset = 0;
}
assert(tx->base.base.stride);
return &tx->base.base;
}
}
static void nvfx_buffer_dirty_interval(struct nvfx_buffer* buffer, unsigned begin, unsigned size, boolean unsynchronized)
{
struct nvfx_screen* screen = nvfx_screen(buffer->base.base.screen);
buffer->last_update_static = buffer->bytes_to_draw_until_static < 0;
if(buffer->dirty_begin == buffer->dirty_end)
{
buffer->dirty_begin = begin;
buffer->dirty_end = begin + size;
buffer->dirty_unsynchronized = unsynchronized;
}
else
{
buffer->dirty_begin = MIN2(buffer->dirty_begin, begin);
buffer->dirty_end = MAX2(buffer->dirty_end, begin + size);
buffer->dirty_unsynchronized &= unsynchronized;
}
if(unsynchronized)
{
// TODO: revisit this, it doesn't seem quite right
//printf("UNSYNC UPDATE %p %u %u\n", buffer, begin, size);
buffer->bytes_to_draw_until_static += size * screen->static_reuse_threshold;
}
else
buffer->bytes_to_draw_until_static = buffer->size * screen->static_reuse_threshold;
}
static void nvfx_transfer_flush_region( struct pipe_context *pipe,
struct pipe_transfer *ptx,
const struct pipe_box *box)
{
if(ptx->resource->target == PIPE_BUFFER && (ptx->usage & PIPE_TRANSFER_FLUSH_EXPLICIT))
{
struct nvfx_buffer* buffer = nvfx_buffer(ptx->resource);
nvfx_buffer_dirty_interval(buffer,
(uint8_t*)ptx->data - buffer->data + util_format_get_stride(buffer->base.base.format, box->x),
util_format_get_stride(buffer->base.base.format, box->width),
!!(ptx->usage & PIPE_TRANSFER_UNSYNCHRONIZED));
}
}
static void
nvfx_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx)
{
if(ptx->resource->target == PIPE_BUFFER)
{
struct nvfx_buffer* buffer = nvfx_buffer(ptx->resource);
if((ptx->usage & (PIPE_TRANSFER_WRITE | PIPE_TRANSFER_FLUSH_EXPLICIT)) == PIPE_TRANSFER_WRITE)
nvfx_buffer_dirty_interval(buffer,
(uint8_t*)ptx->data - buffer->data,
ptx->stride,
!!(ptx->usage & PIPE_TRANSFER_UNSYNCHRONIZED));
pipe_resource_reference(&ptx->resource, 0);
FREE(ptx);
}
else
{
struct nouveau_channel* chan = nvfx_context(pipe)->screen->base.channel;
util_staging_transfer_destroy(pipe, ptx);
FIRE_RING(chan);
}
}
void *
nvfx_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
{
if(ptx->resource->target == PIPE_BUFFER)
return ptx->data;
else
{
struct nvfx_staging_transfer *tx = (struct nvfx_staging_transfer *)ptx;
if(!ptx->data)
{
struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->base.staging_resource;
uint8_t *map = nouveau_screen_bo_map(pipe->screen, mt->base.bo, nouveau_screen_transfer_flags(ptx->usage));
ptx->data = map + tx->offset;
}
++tx->map_count;
return ptx->data;
}
}
void
nvfx_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
{
if(ptx->resource->target != PIPE_BUFFER)
{
struct nvfx_staging_transfer *tx = (struct nvfx_staging_transfer *)ptx;
struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->base.staging_resource;
if(!--tx->map_count)
{
nouveau_screen_bo_unmap(pipe->screen, mt->base.bo);
ptx->data = 0;
}
}
}
static void nvfx_transfer_inline_write( struct pipe_context *pipe,
struct pipe_resource *pr,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned slice_stride)
{
if(pr->target != PIPE_BUFFER)
{
u_default_transfer_inline_write(pipe, pr, level, usage, box, data, stride, slice_stride);
}
else
{
struct nvfx_buffer* buffer = nvfx_buffer(pr);
unsigned begin = util_format_get_stride(pr->format, box->x);
unsigned size = util_format_get_stride(pr->format, box->width);
memcpy(buffer->data + begin, data, size);
nvfx_buffer_dirty_interval(buffer, begin, size,
!!(pr->flags & PIPE_TRANSFER_UNSYNCHRONIZED));
}
}
void
nvfx_init_transfer_functions(struct pipe_context *pipe)
{
pipe->get_transfer = nvfx_transfer_new;
pipe->transfer_map = nvfx_transfer_map;
pipe->transfer_flush_region = nvfx_transfer_flush_region;
pipe->transfer_unmap = nvfx_transfer_unmap;
pipe->transfer_destroy = nvfx_transfer_destroy;
pipe->transfer_inline_write = nvfx_transfer_inline_write;
}

View File

@ -1,24 +0,0 @@
#ifndef NVFX_TRANSFER_H
#define NVFX_TRANSFER_H
#include "util/u_transfer.h"
#include "pipe/p_state.h"
struct pipe_transfer *
nvfx_transfer_new(struct pipe_context *pcontext,
struct pipe_resource *pt,
unsigned level,
unsigned usage,
const struct pipe_box *box);
void *
nvfx_transfer_map(struct pipe_context *pcontext,
struct pipe_transfer *ptx);
void
nvfx_transfer_unmap(struct pipe_context *pcontext,
struct pipe_transfer *ptx);
#endif

View File

@ -1,637 +0,0 @@
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_transfer.h"
#include "translate/translate.h"
#include "nvfx_context.h"
#include "nvfx_state.h"
#include "nvfx_resource.h"
#include "nouveau/nouveau_channel.h"
#include "nouveau/nv04_pushbuf.h"
static inline unsigned
util_guess_unique_indices_count(unsigned mode, unsigned indices)
{
/* Euler's formula gives V =
* = E - F + 2 =
* = F * (polygon_edges / 2 - 1) + 2 =
* = F * (polygon_edges - 2) / 2 + 2 =
* = indices * (polygon_edges - 2) / (2 * indices_per_face) + 2
* = indices * (1 / 2 - 1 / polygon_edges) + 2
*/
switch(mode)
{
case PIPE_PRIM_LINES:
return indices >> 1;
case PIPE_PRIM_TRIANGLES:
{
// avoid an expensive division by 3 using the multiplicative inverse mod 2^32
unsigned q;
unsigned inv3 = 2863311531;
indices >>= 1;
q = indices * inv3;
if(unlikely(q >= indices))
{
q += inv3;
if(q >= indices)
q += inv3;
}
return indices + 2;
//return indices / 6 + 2;
}
// guess that indexed quads are created by successive connections, since a closed mesh seems unlikely
case PIPE_PRIM_QUADS:
return (indices >> 1) + 2;
// return (indices >> 2) + 2; // if it is a closed mesh
default:
return indices;
}
}
static unsigned nvfx_decide_upload_mode(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct nvfx_context* nvfx = nvfx_context(pipe);
unsigned hardware_cost = 0;
unsigned inline_cost = 0;
unsigned unique_vertices;
unsigned upload_mode;
float best_index_cost_for_hardware_vertices_as_inline_cost;
boolean prefer_hardware_indices;
unsigned index_inline_cost;
unsigned index_hardware_cost;
if (info->indexed)
unique_vertices = util_guess_unique_indices_count(info->mode, info->count);
else
unique_vertices = info->count;
/* Here we try to figure out if we are better off writing vertex data directly on the FIFO,
* or create hardware buffer objects and pointing the hardware to them.
*
* This is done by computing the total memcpy cost of each option, ignoring uploads
* if we think that the buffer is static and thus the upload cost will be amortized over
* future draw calls.
*
* For instance, if everything looks static, we will always create buffer objects, while if
* everything is a user buffer and we are not doing indexed drawing, we never do.
*
* Other interesting cases are where a small user vertex buffer, but a huge user index buffer,
* where we will upload the vertex buffer, so that we can use hardware index lookup, and
* the opposite case, where we instead do index lookup in software to avoid uploading
* a huge amount of vertex data that is not going to be used.
*
* Otherwise, we generally move to the GPU the after it has been pushed
* NVFX_STATIC_BUFFER_MIN_REUSE_TIMES times to the GPU without having
* been updated with a transfer (or just the buffer having been destroyed).
*
* There is no special handling for user buffers, since applications can use
* OpenGL VBOs in a one-shot fashion. OpenGL 3/4 core profile forces this
* by the way.
*
* Note that currently we don't support only putting some data on the FIFO, and
* some on vertex buffers (constant and instanced data is independent from this).
*
* nVidia doesn't seem to do this either, even though it should be at least
* doable with VTX_ATTR and possibly with VERTEX_DATA too if not indexed.
*/
for (unsigned i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; i++)
{
struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
struct nvfx_buffer* buffer = nvfx_buffer(vb->buffer);
buffer->bytes_to_draw_until_static -= vbi->per_vertex_size * unique_vertices;
if (!nvfx_buffer_seems_static(buffer))
{
hardware_cost += buffer->dirty_end - buffer->dirty_begin;
if (!buffer->base.bo)
hardware_cost += nvfx->screen->buffer_allocation_cost;
}
inline_cost += vbi->per_vertex_size * info->count;
}
best_index_cost_for_hardware_vertices_as_inline_cost = 0.0f;
prefer_hardware_indices = FALSE;
index_inline_cost = 0;
index_hardware_cost = 0;
if (info->indexed)
{
index_inline_cost = nvfx->idxbuf.index_size * info->count;
if (nvfx->screen->index_buffer_reloc_flags
&& (nvfx->idxbuf.index_size == 2 || nvfx->idxbuf.index_size == 4)
&& !(nvfx->idxbuf.offset & (nvfx->idxbuf.index_size - 1)))
{
struct nvfx_buffer* buffer = nvfx_buffer(nvfx->idxbuf.buffer);
buffer->bytes_to_draw_until_static -= index_inline_cost;
prefer_hardware_indices = TRUE;
if (!nvfx_buffer_seems_static(buffer))
{
index_hardware_cost = buffer->dirty_end - buffer->dirty_begin;
if (!buffer->base.bo)
index_hardware_cost += nvfx->screen->buffer_allocation_cost;
}
if ((float) index_inline_cost < (float) index_hardware_cost * nvfx->screen->inline_cost_per_hardware_cost)
{
best_index_cost_for_hardware_vertices_as_inline_cost = (float) index_inline_cost;
}
else
{
best_index_cost_for_hardware_vertices_as_inline_cost = (float) index_hardware_cost * nvfx->screen->inline_cost_per_hardware_cost;
prefer_hardware_indices = TRUE;
}
}
}
/* let's finally figure out which of the 3 paths we want to take */
if ((float) (inline_cost + index_inline_cost) > ((float) hardware_cost * nvfx->screen->inline_cost_per_hardware_cost + best_index_cost_for_hardware_vertices_as_inline_cost))
upload_mode = 1 + prefer_hardware_indices;
else
upload_mode = 0;
#ifdef DEBUG
if (unlikely(nvfx->screen->trace_draw))
{
fprintf(stderr, "DRAW");
if (info->indexed)
{
fprintf(stderr, "_IDX%u", nvfx->idxbuf.index_size);
if (info->index_bias)
fprintf(stderr, " biased %u", info->index_bias);
fprintf(stderr, " idxrange %u -> %u", info->min_index, info->max_index);
}
if (info->instance_count > 1)
fprintf(stderr, " %u instances from %u", info->instance_count, info->indexed);
fprintf(stderr, " start %u count %u prim %u", info->start, info->count, info->mode);
if (!upload_mode)
fprintf(stderr, " -> inline vertex data");
else if (upload_mode == 2 || !info->indexed)
fprintf(stderr, " -> buffer range");
else
fprintf(stderr, " -> inline indices");
fprintf(stderr, " [ivtx %u hvtx %u iidx %u hidx %u bidx %f] <", inline_cost, hardware_cost, index_inline_cost, index_hardware_cost, best_index_cost_for_hardware_vertices_as_inline_cost);
for (unsigned i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; ++i)
{
struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
struct nvfx_buffer* buffer = nvfx_buffer(vb->buffer);
if (i)
fprintf(stderr, ", ");
fprintf(stderr, "%p%s left %Li", buffer, buffer->last_update_static ? " static" : "", buffer->bytes_to_draw_until_static);
}
fprintf(stderr, ">\n");
}
#endif
return upload_mode;
}
void nvfx_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
unsigned upload_mode = 0;
if (!nvfx->vtxelt->needs_translate)
upload_mode = nvfx_decide_upload_mode(pipe, info);
nvfx->use_index_buffer = upload_mode > 1;
if ((upload_mode > 0) != nvfx->use_vertex_buffers)
{
nvfx->use_vertex_buffers = (upload_mode > 0);
nvfx->dirty |= NVFX_NEW_ARRAYS;
nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
}
if (upload_mode > 0)
{
for (unsigned i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; i++)
{
struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
nvfx_buffer_upload(nvfx_buffer(vb->buffer));
}
if (upload_mode > 1)
{
nvfx_buffer_upload(nvfx_buffer(nvfx->idxbuf.buffer));
if (unlikely(info->index_bias != nvfx->base_vertex))
{
nvfx->base_vertex = info->index_bias;
nvfx->dirty |= NVFX_NEW_ARRAYS;
}
}
else
{
if (unlikely(info->start < nvfx->base_vertex && nvfx->base_vertex))
{
nvfx->base_vertex = 0;
nvfx->dirty |= NVFX_NEW_ARRAYS;
}
}
}
if (nvfx->screen->force_swtnl || !nvfx_state_validate(nvfx))
nvfx_draw_vbo_swtnl(pipe, info);
else
nvfx_push_vbo(pipe, info);
}
boolean
nvfx_vbo_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
int i;
int elements = MAX2(nvfx->vtxelt->num_elements, nvfx->hw_vtxelt_nr);
unsigned vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD;
if (!elements)
return TRUE;
MARK_RING(chan, (5 + 2) * 16 + 2 + 11, 16 + 2);
for(unsigned i = 0; i < nvfx->vtxelt->num_constant; ++i)
{
struct nvfx_low_frequency_element *ve = &nvfx->vtxelt->constant[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
struct nvfx_buffer* buffer = nvfx_buffer(vb->buffer);
float v[4];
ve->fetch_rgba_float(v, buffer->data + vb->buffer_offset + ve->src_offset, 0, 0);
nvfx_emit_vtx_attr(chan, eng3d, ve->idx, v, ve->ncomp);
}
BEGIN_RING(chan, eng3d, NV30_3D_VTXFMT(0), elements);
if(nvfx->use_vertex_buffers)
{
unsigned idx = 0;
for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
if(idx != ve->idx)
{
assert(idx < ve->idx);
OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], ve->idx - idx);
idx = ve->idx;
}
OUT_RING(chan, nvfx->vtxelt->vtxfmt[idx] | (vb->stride << NV30_3D_VTXFMT_STRIDE__SHIFT));
++idx;
}
if(idx != nvfx->vtxelt->num_elements)
OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], nvfx->vtxelt->num_elements - idx);
}
else
OUT_RINGp(chan, nvfx->vtxelt->vtxfmt, nvfx->vtxelt->num_elements);
for(i = nvfx->vtxelt->num_elements; i < elements; ++i)
OUT_RING(chan, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
if(nvfx->is_nv4x) {
unsigned i;
/* seems to be some kind of cache flushing */
for(i = 0; i < 3; ++i) {
BEGIN_RING(chan, eng3d, 0x1718, 1);
OUT_RING(chan, 0);
}
}
BEGIN_RING(chan, eng3d, NV30_3D_VTXBUF(0), elements);
if(nvfx->use_vertex_buffers)
{
unsigned idx = 0;
for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo;
for(; idx < ve->idx; ++idx)
OUT_RING(chan, 0);
OUT_RELOC(chan, bo,
vb->buffer_offset + ve->src_offset + nvfx->base_vertex * vb->stride,
vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
0, NV30_3D_VTXBUF_DMA1);
++idx;
}
for(; idx < elements; ++idx)
OUT_RING(chan, 0);
}
else
{
for (i = 0; i < elements; i++)
OUT_RING(chan, 0);
}
BEGIN_RING(chan, eng3d, 0x1710, 1);
OUT_RING(chan, 0);
nvfx->hw_vtxelt_nr = nvfx->vtxelt->num_elements;
nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
return TRUE;
}
void
nvfx_vbo_swtnl_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
unsigned num_outputs = nvfx->vertprog->draw_elements;
int elements = MAX2(num_outputs, nvfx->hw_vtxelt_nr);
if (!elements)
return;
BEGIN_RING(chan, eng3d, NV30_3D_VTXFMT(0), elements);
for(unsigned i = 0; i < num_outputs; ++i)
OUT_RING(chan, (4 << NV30_3D_VTXFMT_SIZE__SHIFT) | NV30_3D_VTXFMT_TYPE_V32_FLOAT);
for(unsigned i = num_outputs; i < elements; ++i)
OUT_RING(chan, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
if(nvfx->is_nv4x) {
unsigned i;
/* seems to be some kind of cache flushing */
for(i = 0; i < 3; ++i) {
BEGIN_RING(chan, eng3d, 0x1718, 1);
OUT_RING(chan, 0);
}
}
BEGIN_RING(chan, eng3d, NV30_3D_VTXBUF(0), elements);
for (unsigned i = 0; i < elements; i++)
OUT_RING(chan, 0);
BEGIN_RING(chan, eng3d, 0x1710, 1);
OUT_RING(chan, 0);
nvfx->hw_vtxelt_nr = num_outputs;
nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
}
void
nvfx_vbo_relocate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan;
unsigned vb_flags;
int i;
if(!nvfx->use_vertex_buffers)
return;
chan = nvfx->screen->base.channel;
vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY;
MARK_RING(chan, 2 * 16 + 3, 2 * 16 + 3);
for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo;
OUT_RELOC(chan, bo, RING_3D(NV30_3D_VTXBUF(ve->idx), 1),
vb_flags, 0, 0);
OUT_RELOC(chan, bo, vb->buffer_offset + ve->src_offset + nvfx->base_vertex * vb->stride,
vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
0, NV30_3D_VTXBUF_DMA1);
}
nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
}
static void
nvfx_idxbuf_emit(struct nvfx_context* nvfx, unsigned ib_flags)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
unsigned ib_format = (nvfx->idxbuf.index_size == 2) ? NV30_3D_IDXBUF_FORMAT_TYPE_U16 : NV30_3D_IDXBUF_FORMAT_TYPE_U32;
struct nouveau_bo* bo = nvfx_resource(nvfx->idxbuf.buffer)->bo;
ib_flags |= nvfx->screen->index_buffer_reloc_flags | NOUVEAU_BO_RD;
assert(nvfx->screen->index_buffer_reloc_flags);
MARK_RING(chan, 3, 3);
if(ib_flags & NOUVEAU_BO_DUMMY)
OUT_RELOC(chan, bo, RING_3D(NV30_3D_IDXBUF_OFFSET, 2), ib_flags, 0, 0);
else
OUT_RING(chan, RING_3D(NV30_3D_IDXBUF_OFFSET, 2));
OUT_RELOC(chan, bo, nvfx->idxbuf.offset + 1, ib_flags | NOUVEAU_BO_LOW, 0, 0);
OUT_RELOC(chan, bo, ib_format, ib_flags | NOUVEAU_BO_OR,
0, NV30_3D_IDXBUF_FORMAT_DMA1);
nvfx->relocs_needed &=~ NVFX_RELOCATE_IDXBUF;
}
void
nvfx_idxbuf_validate(struct nvfx_context* nvfx)
{
nvfx_idxbuf_emit(nvfx, 0);
}
void
nvfx_idxbuf_relocate(struct nvfx_context* nvfx)
{
nvfx_idxbuf_emit(nvfx, NOUVEAU_BO_DUMMY);
}
unsigned nvfx_vertex_formats[PIPE_FORMAT_COUNT] =
{
[PIPE_FORMAT_R32_FLOAT] = NV30_3D_VTXFMT_TYPE_V32_FLOAT,
[PIPE_FORMAT_R32G32_FLOAT] = NV30_3D_VTXFMT_TYPE_V32_FLOAT,
[PIPE_FORMAT_R32G32B32_FLOAT] = NV30_3D_VTXFMT_TYPE_V32_FLOAT,
[PIPE_FORMAT_R32G32B32A32_FLOAT] = NV30_3D_VTXFMT_TYPE_V32_FLOAT,
[PIPE_FORMAT_R16_FLOAT] = NV30_3D_VTXFMT_TYPE_V16_FLOAT,
[PIPE_FORMAT_R16G16_FLOAT] = NV30_3D_VTXFMT_TYPE_V16_FLOAT,
[PIPE_FORMAT_R16G16B16_FLOAT] = NV30_3D_VTXFMT_TYPE_V16_FLOAT,
[PIPE_FORMAT_R16G16B16A16_FLOAT] = NV30_3D_VTXFMT_TYPE_V16_FLOAT,
[PIPE_FORMAT_R8_UNORM] = NV30_3D_VTXFMT_TYPE_U8_UNORM,
[PIPE_FORMAT_R8G8_UNORM] = NV30_3D_VTXFMT_TYPE_U8_UNORM,
[PIPE_FORMAT_R8G8B8_UNORM] = NV30_3D_VTXFMT_TYPE_U8_UNORM,
[PIPE_FORMAT_R8G8B8A8_UNORM] = NV30_3D_VTXFMT_TYPE_U8_UNORM,
[PIPE_FORMAT_R8G8B8A8_USCALED] = NV30_3D_VTXFMT_TYPE_U8_USCALED,
[PIPE_FORMAT_R16_SNORM] = NV30_3D_VTXFMT_TYPE_V16_SNORM,
[PIPE_FORMAT_R16G16_SNORM] = NV30_3D_VTXFMT_TYPE_V16_SNORM,
[PIPE_FORMAT_R16G16B16_SNORM] = NV30_3D_VTXFMT_TYPE_V16_SNORM,
[PIPE_FORMAT_R16G16B16A16_SNORM] = NV30_3D_VTXFMT_TYPE_V16_SNORM,
[PIPE_FORMAT_R16_SSCALED] = NV30_3D_VTXFMT_TYPE_V16_SSCALED,
[PIPE_FORMAT_R16G16_SSCALED] = NV30_3D_VTXFMT_TYPE_V16_SSCALED,
[PIPE_FORMAT_R16G16B16_SSCALED] = NV30_3D_VTXFMT_TYPE_V16_SSCALED,
[PIPE_FORMAT_R16G16B16A16_SSCALED] = NV30_3D_VTXFMT_TYPE_V16_SSCALED,
};
static void *
nvfx_vtxelts_state_create(struct pipe_context *pipe,
unsigned num_elements,
const struct pipe_vertex_element *elements)
{
struct nvfx_vtxelt_state *cso = CALLOC_STRUCT(nvfx_vtxelt_state);
struct translate_key transkey;
unsigned per_vertex_size[16];
unsigned vb_compacted_index[16];
if(num_elements > 16)
{
_debug_printf("Error: application attempted to use %u vertex elements, but only 16 are supported: ignoring the rest\n", num_elements);
num_elements = 16;
}
memset(per_vertex_size, 0, sizeof(per_vertex_size));
memcpy(cso->pipe, elements, num_elements * sizeof(elements[0]));
cso->num_elements = num_elements;
cso->needs_translate = FALSE;
transkey.nr_elements = 0;
transkey.output_stride = 0;
for(unsigned i = 0; i < num_elements; ++i)
{
const struct pipe_vertex_element* ve = &elements[i];
if(!ve->instance_divisor)
per_vertex_size[ve->vertex_buffer_index] += util_format_get_stride(ve->src_format, 1);
}
for(unsigned i = 0; i < 16; ++i)
{
if(per_vertex_size[i])
{
unsigned idx = cso->num_per_vertex_buffer_infos++;
cso->per_vertex_buffer_info[idx].vertex_buffer_index = i;
cso->per_vertex_buffer_info[idx].per_vertex_size = per_vertex_size[i];
vb_compacted_index[i] = idx;
}
}
for(unsigned i = 0; i < num_elements; ++i)
{
const struct pipe_vertex_element* ve = &elements[i];
unsigned type = nvfx_vertex_formats[ve->src_format];
unsigned ncomp = util_format_get_nr_components(ve->src_format);
//if(ve->frequency != PIPE_ELEMENT_FREQUENCY_PER_VERTEX)
if(ve->instance_divisor)
{
struct nvfx_low_frequency_element* lfve;
cso->vtxfmt[i] = NV30_3D_VTXFMT_TYPE_V32_FLOAT;
//if(ve->frequency == PIPE_ELEMENT_FREQUENCY_CONSTANT)
if(0)
lfve = &cso->constant[cso->num_constant++];
else
{
lfve = &cso->per_instance[cso->num_per_instance++].base;
((struct nvfx_per_instance_element*)lfve)->instance_divisor = ve->instance_divisor;
}
lfve->idx = i;
lfve->vertex_buffer_index = ve->vertex_buffer_index;
lfve->src_offset = ve->src_offset;
lfve->fetch_rgba_float = util_format_description(ve->src_format)->fetch_rgba_float;
lfve->ncomp = ncomp;
}
else
{
unsigned idx;
idx = cso->num_per_vertex++;
cso->per_vertex[idx].idx = i;
cso->per_vertex[idx].vertex_buffer_index = ve->vertex_buffer_index;
cso->per_vertex[idx].src_offset = ve->src_offset;
idx = transkey.nr_elements++;
transkey.element[idx].input_format = ve->src_format;
transkey.element[idx].input_buffer = vb_compacted_index[ve->vertex_buffer_index];
transkey.element[idx].input_offset = ve->src_offset;
transkey.element[idx].instance_divisor = 0;
transkey.element[idx].type = TRANSLATE_ELEMENT_NORMAL;
if(type)
{
transkey.element[idx].output_format = ve->src_format;
cso->vtxfmt[i] = (ncomp << NV30_3D_VTXFMT_SIZE__SHIFT) | type;
}
else
{
unsigned float32[4] = {PIPE_FORMAT_R32_FLOAT, PIPE_FORMAT_R32G32_FLOAT, PIPE_FORMAT_R32G32B32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT};
transkey.element[idx].output_format = float32[ncomp - 1];
cso->needs_translate = TRUE;
cso->vtxfmt[i] = (ncomp << NV30_3D_VTXFMT_SIZE__SHIFT) | NV30_3D_VTXFMT_TYPE_V32_FLOAT;
}
transkey.element[idx].output_offset = transkey.output_stride;
transkey.output_stride += (util_format_get_stride(transkey.element[idx].output_format, 1) + 3) & ~3;
}
}
cso->translate = translate_create(&transkey);
cso->vertex_length = transkey.output_stride >> 2;
cso->max_vertices_per_packet = 2047 / MAX2(cso->vertex_length, 1);
return (void *)cso;
}
static void
nvfx_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso)
{
FREE(hwcso);
}
static void
nvfx_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
nvfx->vtxelt = hwcso;
nvfx->use_vertex_buffers = -1;
nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
}
static void
nvfx_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
const struct pipe_vertex_buffer *vb)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
util_copy_vertex_buffers(nvfx->vtxbuf,
&nvfx->vtxbuf_nr,
vb, count);
nvfx->use_vertex_buffers = -1;
nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
}
static void
nvfx_set_index_buffer(struct pipe_context *pipe,
const struct pipe_index_buffer *ib)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
if(ib)
{
pipe_resource_reference(&nvfx->idxbuf.buffer, ib->buffer);
nvfx->idxbuf.index_size = ib->index_size;
nvfx->idxbuf.offset = ib->offset;
}
else
{
pipe_resource_reference(&nvfx->idxbuf.buffer, 0);
nvfx->idxbuf.index_size = 0;
nvfx->idxbuf.offset = 0;
}
nvfx->dirty |= NVFX_NEW_INDEX;
nvfx->draw_dirty |= NVFX_NEW_INDEX;
}
void
nvfx_init_vbo_functions(struct nvfx_context *nvfx)
{
nvfx->pipe.set_vertex_buffers = nvfx_set_vertex_buffers;
nvfx->pipe.set_index_buffer = nvfx_set_index_buffer;
nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create;
nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete;
nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind;
nvfx->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
}

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,6 @@ PIPE_DRIVERS = \
$(TOP)/src/gallium/winsys/nouveau/drm/libnouveaudrm.a \
$(TOP)/src/gallium/drivers/trace/libtrace.a \
$(TOP)/src/gallium/drivers/rbug/librbug.a \
$(TOP)/src/gallium/drivers/nvfx/libnvfx.a \
$(TOP)/src/gallium/drivers/nv50/libnv50.a \
$(TOP)/src/gallium/drivers/nvc0/libnvc0.a \
$(TOP)/src/gallium/drivers/nouveau/libnouveau.a

View File

@ -7,7 +7,6 @@ DRIVER_INCLUDES = $(shell $(PKG_CONFIG) libdrm --cflags-only-I)
PIPE_DRIVERS = \
$(TOP)/src/gallium/winsys/nouveau/drm/libnouveaudrm.a \
$(TOP)/src/gallium/drivers/nvfx/libnvfx.a \
$(TOP)/src/gallium/drivers/nv50/libnv50.a \
$(TOP)/src/gallium/drivers/nvc0/libnvc0.a \
$(TOP)/src/gallium/drivers/nouveau/libnouveau.a \

View File

@ -13,7 +13,6 @@ DRIVER_DEFINES = \
DRIVER_PIPES = \
$(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \
$(TOP)/src/gallium/winsys/nouveau/drm/libnouveaudrm.a \
$(TOP)/src/gallium/drivers/nvfx/libnvfx.a \
$(TOP)/src/gallium/drivers/nv50/libnv50.a \
$(TOP)/src/gallium/drivers/nvc0/libnvc0.a \
$(TOP)/src/gallium/drivers/nouveau/libnouveau.a \

View File

@ -5,7 +5,6 @@ LIBBASENAME = XvMCnouveau
PIPE_DRIVERS = \
$(TOP)/src/gallium/winsys/nouveau/drm/libnouveaudrm.a \
$(TOP)/src/gallium/drivers/nvfx/libnvfx.a \
$(TOP)/src/gallium/drivers/nv50/libnv50.a \
$(TOP)/src/gallium/drivers/nvc0/libnvc0.a \
$(TOP)/src/gallium/drivers/nouveau/libnouveau.a \

View File

@ -25,11 +25,13 @@ nouveau_drm_screen_create(int fd)
return NULL;
switch (dev->chipset & 0xf0) {
#if 0
case 0x30:
case 0x40:
case 0x60:
init = nvfx_screen_create;
init = nv30_screen_create;
break;
#endif
case 0x50:
case 0x80:
case 0x90: