nv30: import new driver for GeForce FX/6/7 chipsets, and Quadro variants

The primary motivation for this rewrite was to have a maintainable driver
going forward, as nvfx was quite horrible in a lot of ways.

The driver is heavily based on the design of the nv50/nvc0 3d drivers we
already have, and uses the same common buffer/fence code.  It also passes
a HEAP more piglit tests than nvfx did, supports a couple more features,
and a few more to come still probably.

The CPU footprint of this driver is far far less than nvfx, and translates
into far greater framerates in a lot of applications (unless you're using
a CPU that's way way newer than the GPUs of these generations....)

Basically, we once again have a maintained driver for these chipsets \o/

Feel free to report bugs now!
This commit is contained in:
Ben Skeggs
2012-01-11 12:42:07 +01:00
parent 6d1cdec3ba
commit a2fc42b899
45 changed files with 13725 additions and 8 deletions
+1 -1
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 nv50 nvc0"
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nv30 nv50 nvc0"
gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" "" "xvmc-nouveau" "vdpau-nouveau"
;;
xswrast)
+1 -1
View File
@@ -135,7 +135,7 @@ nouveau_buffer_upload(struct nouveau_context *nv, struct nv04_resource *buf,
struct nouveau_bo *bounce = NULL;
uint32_t offset;
if (size <= 192) {
if (size <= 192 && (nv->push_data || nv->push_cb)) {
if (buf->base.bind & PIPE_BIND_CONSTANT_BUFFER)
nv->push_cb(nv, buf->bo, buf->domain, buf->offset, buf->base.width0,
start, size / 4, (const uint32_t *)(buf->data + start));
@@ -3,12 +3,11 @@
#include "pipe/p_context.h"
struct nouveau_pushbuf;
struct nouveau_context {
struct pipe_context pipe;
struct nouveau_screen *screen;
struct nouveau_client *client;
struct nouveau_pushbuf *pushbuf;
boolean vbo_dirty;
@@ -74,6 +74,9 @@ nouveau_screen_transfer_flags(unsigned pipe)
return flags;
}
extern struct pipe_screen *
nv30_screen_create(struct nouveau_device *);
extern struct pipe_screen *
nv50_screen_create(struct nouveau_device *);
+37
View File
@@ -0,0 +1,37 @@
# 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 and CPP_SOURCES
include $(LOCAL_PATH)/Makefile.sources
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(C_SOURCES) $(CPP_SOURCES)
LOCAL_C_INCLUDES := $(DRM_TOP)
LOCAL_MODULE := libmesa_pipe_nv30
include $(GALLIUM_COMMON_MK)
include $(BUILD_STATIC_LIBRARY)
+15
View File
@@ -0,0 +1,15 @@
TOP = ../../../..
include $(TOP)/configs/current
LIBNAME = nv30
include Makefile.sources
LIBRARY_INCLUDES = \
$(LIBDRM_CFLAGS)
include ../../Makefile.template
# DO NOT DELETE
# FIXME: Remove when this driver is converted to automake.
all: default
+20
View File
@@ -0,0 +1,20 @@
C_SOURCES := nv30_screen.c \
nv30_context.c \
nv30_format.c \
nv30_resource.c \
nv30_transfer.c \
nv30_miptree.c \
nv30_state.c \
nv30_state_validate.c \
nv30_texture.c \
nv30_fragtex.c \
nv40_verttex.c \
nv30_fragprog.c \
nv30_vertprog.c \
nv30_clear.c \
nv30_vbo.c \
nv30_push.c \
nv30_draw.c \
nv30_query.c \
nvfx_vertprog.c \
nvfx_fragprog.c
+11
View File
@@ -0,0 +1,11 @@
Import('*')
env = env.Clone()
nv30 = env.ConvenienceLibrary(
target = 'nv30',
source = env.ParseSourceList('Makefile.sources',
['C_SOURCES', 'CPP_SOURCES'])
)
Export('nv30')
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+226
View File
@@ -0,0 +1,226 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "pipe/p_defines.h"
#include "util/u_pack_color.h"
#include "nouveau/nouveau_gldefs.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_format.h"
static INLINE uint32_t
pack_rgba(enum pipe_format format, const float *rgba)
{
union util_color uc;
util_pack_color(rgba, format, &uc);
return uc.ui;
}
static INLINE uint32_t
pack_zeta(enum pipe_format format, double depth, unsigned stencil)
{
uint32_t zuint = (uint32_t)(depth * 4294967295.0);
if (format != PIPE_FORMAT_Z16_UNORM)
return (zuint & 0xffffff00) | (stencil & 0xff);
return zuint >> 16;
}
static void
nv30_clear(struct pipe_context *pipe, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct pipe_framebuffer_state *fb = &nv30->framebuffer;
uint32_t colr = 0, zeta = 0, mode = 0;
if (!nv30_state_validate(nv30, TRUE))
return;
if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
colr = pack_rgba(fb->cbufs[0]->format, color->f);
mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R |
NV30_3D_CLEAR_BUFFERS_COLOR_G |
NV30_3D_CLEAR_BUFFERS_COLOR_B |
NV30_3D_CLEAR_BUFFERS_COLOR_A;
}
if (fb->zsbuf) {
zeta = pack_zeta(fb->zsbuf->format, depth, stencil);
if (buffers & PIPE_CLEAR_DEPTH)
mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
if (buffers & PIPE_CLEAR_STENCIL)
mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
}
/*XXX: wtf? fixes clears sometimes not clearing on nv3x... */
if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) {
BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
PUSH_DATA (push, zeta);
PUSH_DATA (push, colr);
PUSH_DATA (push, mode);
}
BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
PUSH_DATA (push, zeta);
PUSH_DATA (push, colr);
PUSH_DATA (push, mode);
nv30_state_release(nv30);
}
static void
nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps,
const union pipe_color_union *color,
unsigned x, unsigned y, unsigned w, unsigned h)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_surface *sf = nv30_surface(ps);
struct nv30_miptree *mt = nv30_miptree(ps->texture);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_object *eng3d = nv30->screen->eng3d;
struct nouveau_pushbuf_refn refn;
uint32_t rt_format;
rt_format = nv30_format(pipe->screen, ps->format)->hw;
if (util_format_get_blocksize(ps->format) == 4)
rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
else
rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
if (nv30_miptree(ps->texture)->swizzled) {
rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
rt_format |= util_logbase2(sf->width) << 16;
rt_format |= util_logbase2(sf->height) << 24;
} else {
rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
}
refn.bo = mt->base.bo;
refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
if (nouveau_pushbuf_space(push, 16, 1, 0) ||
nouveau_pushbuf_refn (push, &refn, 1))
return;
BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);
BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
PUSH_DATA (push, sf->width << 16);
PUSH_DATA (push, sf->height << 16);
PUSH_DATA (push, rt_format);
BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2);
if (eng3d->oclass < NV40_3D_CLASS)
PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
else
PUSH_DATA (push, sf->pitch);
PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
PUSH_DATA (push, (w << 16) | x);
PUSH_DATA (push, (h << 16) | y);
BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2);
PUSH_DATA (push, pack_rgba(ps->format, color->f));
PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R |
NV30_3D_CLEAR_BUFFERS_COLOR_G |
NV30_3D_CLEAR_BUFFERS_COLOR_B |
NV30_3D_CLEAR_BUFFERS_COLOR_A);
nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
}
static void
nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps,
unsigned buffers, double depth, unsigned stencil,
unsigned x, unsigned y, unsigned w, unsigned h)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_surface *sf = nv30_surface(ps);
struct nv30_miptree *mt = nv30_miptree(ps->texture);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_object *eng3d = nv30->screen->eng3d;
struct nouveau_pushbuf_refn refn;
uint32_t rt_format, mode = 0;
rt_format = nv30_format(pipe->screen, ps->format)->hw;
if (util_format_get_blocksize(ps->format) == 4)
rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
else
rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
if (nv30_miptree(ps->texture)->swizzled) {
rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
rt_format |= util_logbase2(sf->width) << 16;
rt_format |= util_logbase2(sf->height) << 24;
} else {
rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
}
if (buffers & PIPE_CLEAR_DEPTH)
mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
if (buffers & PIPE_CLEAR_STENCIL)
mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
refn.bo = mt->base.bo;
refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
if (nouveau_pushbuf_space(push, 32, 1, 0) ||
nouveau_pushbuf_refn (push, &refn, 1))
return;
BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
PUSH_DATA (push, sf->width << 16);
PUSH_DATA (push, sf->height << 16);
PUSH_DATA (push, rt_format);
if (eng3d->oclass < NV40_3D_CLASS) {
BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1);
PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
} else {
BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
PUSH_DATA (push, sf->pitch);
}
BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1);
PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
PUSH_DATA (push, (w << 16) | x);
PUSH_DATA (push, (h << 16) | y);
BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1);
PUSH_DATA (push, pack_zeta(ps->format, depth, stencil));
BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1);
PUSH_DATA (push, mode);
nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
}
void
nv30_clear_init(struct pipe_context *pipe)
{
pipe->clear = nv30_clear;
pipe->clear_render_target = nv30_clear_render_target;
pipe->clear_depth_stencil = nv30_clear_depth_stencil;
}
+174
View File
@@ -0,0 +1,174 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "draw/draw_context.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nouveau/nouveau_fence.h"
#include "nv30_context.h"
#include "nv30_transfer.h"
#include "nv30_state.h"
static void
nv30_context_kick_notify(struct nouveau_pushbuf *push)
{
struct nouveau_screen *screen;
struct nv30_context *nv30;
if (!push->user_priv)
return;
nv30 = container_of(push->user_priv, nv30, bufctx);
screen = &nv30->screen->base;
nouveau_fence_next(screen);
nouveau_fence_update(screen, TRUE);
if (push->bufctx) {
struct nouveau_bufref *bref;
LIST_FOR_EACH_ENTRY(bref, &push->bufctx->current, thead) {
struct nv04_resource *res = bref->priv;
if (res && res->mm) {
nouveau_fence_ref(screen->fence.current, &res->fence);
if (bref->flags & NOUVEAU_BO_RD)
res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
if (bref->flags & NOUVEAU_BO_WR) {
nouveau_fence_ref(screen->fence.current, &res->fence_wr);
res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
}
}
}
}
}
static void
nv30_context_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
if (fence)
nouveau_fence_ref(nv30->screen->base.fence.current,
(struct nouveau_fence **)fence);
PUSH_KICK(push);
}
static void
nv30_context_destroy(struct pipe_context *pipe)
{
struct nv30_context *nv30 = nv30_context(pipe);
if (nv30->draw)
draw_destroy(nv30->draw);
nouveau_bufctx_del(&nv30->bufctx);
if (nv30->screen->cur_ctx == nv30)
nv30->screen->cur_ctx = NULL;
FREE(nv30);
}
#define FAIL_CONTEXT_INIT(str, err) \
do { \
NOUVEAU_ERR(str, err); \
nv30_context_destroy(pipe); \
return NULL; \
} while(0)
struct pipe_context *
nv30_context_create(struct pipe_screen *pscreen, void *priv)
{
struct nv30_screen *screen = nv30_screen(pscreen);
struct nv30_context *nv30 = CALLOC_STRUCT(nv30_context);
struct nouveau_pushbuf *push;
struct pipe_context *pipe;
int ret;
if (!nv30)
return NULL;
nv30->screen = screen;
nv30->base.screen = &screen->base;
nv30->base.copy_data = nv30_transfer_copy_data;
pipe = &nv30->base.pipe;
pipe->screen = pscreen;
pipe->priv = priv;
pipe->destroy = nv30_context_destroy;
pipe->flush = nv30_context_flush;
/*XXX: *cough* per-context client */
nv30->base.client = screen->base.client;
/*XXX: *cough* per-context pushbufs */
push = screen->base.pushbuf;
nv30->base.pushbuf = push;
nv30->base.pushbuf->user_priv = push->user_priv; /* hack at validate time */
nv30->base.pushbuf->rsvd_kick = 16; /* hack in screen before first space */
nv30->base.pushbuf->kick_notify = nv30_context_kick_notify;
ret = nouveau_bufctx_new(nv30->base.client, 64, &nv30->bufctx);
if (ret) {
nv30_context_destroy(pipe);
return NULL;
}
/*XXX: make configurable with performance vs quality, these defaults
* match the binary driver's defaults
*/
if (screen->eng3d->oclass < NV40_3D_CLASS)
nv30->config.filter = 0x00000004;
else
nv30->config.filter = 0x00002dc4;
nv30->config.aniso = NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_OFF;
if (debug_get_bool_option("NV30_SWTNL", FALSE))
nv30->draw_flags |= NV30_NEW_SWTNL;
/*XXX: nvfx... */
nv30->is_nv4x = (screen->eng3d->oclass >= NV40_3D_CLASS) ? ~0 : 0;
nv30->use_nv4x = (screen->eng3d->oclass >= NV40_3D_CLASS) ? ~0 : 0;
nv30->render_mode = HW;
nv30_vbo_init(pipe);
nv30_query_init(pipe);
nv30_state_init(pipe);
nv30_resource_init(pipe);
nv30_clear_init(pipe);
nv30_fragprog_init(pipe);
nv30_vertprog_init(pipe);
nv30_texture_init(pipe);
nv30_fragtex_init(pipe);
nv40_verttex_init(pipe);
nv30_draw_init(pipe);
return pipe;
}
+231
View File
@@ -0,0 +1,231 @@
#ifndef __NV30_CONTEXT_H__
#define __NV30_CONTEXT_H__
#include "pipe/p_format.h"
#include "nv30_screen.h"
#include "nv30_state.h"
#include "nouveau/nouveau_context.h"
#define BUFCTX_FB 0
#define BUFCTX_VTXTMP 1
#define BUFCTX_VTXBUF 2
#define BUFCTX_IDXBUF 3
#define BUFCTX_VERTTEX(n) (4 + (n))
#define BUFCTX_FRAGPROG 8
#define BUFCTX_FRAGTEX(n) (9 + (n))
#define NV30_NEW_BLEND (1 << 0)
#define NV30_NEW_RASTERIZER (1 << 1)
#define NV30_NEW_ZSA (1 << 2)
#define NV30_NEW_VERTPROG (1 << 3)
#define NV30_NEW_VERTCONST (1 << 4)
#define NV30_NEW_FRAGPROG (1 << 5)
#define NV30_NEW_FRAGCONST (1 << 6)
#define NV30_NEW_BLEND_COLOUR (1 << 7)
#define NV30_NEW_STENCIL_REF (1 << 8)
#define NV30_NEW_CLIP (1 << 9)
#define NV30_NEW_SAMPLE_MASK (1 << 10)
#define NV30_NEW_FRAMEBUFFER (1 << 11)
#define NV30_NEW_STIPPLE (1 << 12)
#define NV30_NEW_SCISSOR (1 << 13)
#define NV30_NEW_VIEWPORT (1 << 14)
#define NV30_NEW_ARRAYS (1 << 15)
#define NV30_NEW_VERTEX (1 << 16)
#define NV30_NEW_CONSTBUF (1 << 17)
#define NV30_NEW_FRAGTEX (1 << 18)
#define NV30_NEW_VERTTEX (1 << 19)
#define NV30_NEW_SWTNL (1 << 31)
#define NV30_NEW_ALL 0x000fffff
struct nv30_context {
struct nouveau_context base;
struct nv30_screen *screen;
struct nouveau_bufctx *bufctx;
struct {
unsigned rt_enable;
unsigned scissor_off;
unsigned num_vtxelts;
boolean prim_restart;
struct nv30_fragprog *fragprog;
} state;
uint32_t dirty;
struct draw_context *draw;
uint32_t draw_flags;
uint32_t draw_dirty;
struct nv30_blend_stateobj *blend;
struct nv30_rasterizer_stateobj *rast;
struct nv30_zsa_stateobj *zsa;
struct nv30_vertex_stateobj *vertex;
struct {
unsigned filter;
unsigned aniso;
} config;
struct {
struct nv30_vertprog *program;
struct pipe_resource *constbuf;
unsigned constbuf_nr;
struct pipe_sampler_view *textures[PIPE_MAX_SAMPLERS];
unsigned num_textures;
struct nv30_sampler_state *samplers[PIPE_MAX_SAMPLERS];
unsigned num_samplers;
unsigned dirty_samplers;
} vertprog;
struct {
struct nv30_fragprog *program;
struct pipe_resource *constbuf;
unsigned constbuf_nr;
struct pipe_sampler_view *textures[PIPE_MAX_SAMPLERS];
unsigned num_textures;
struct nv30_sampler_state *samplers[PIPE_MAX_SAMPLERS];
unsigned num_samplers;
unsigned dirty_samplers;
} fragprog;
struct pipe_framebuffer_state framebuffer;
struct pipe_blend_color blend_colour;
struct pipe_stencil_ref stencil_ref;
struct pipe_poly_stipple stipple;
struct pipe_scissor_state scissor;
struct pipe_viewport_state viewport;
struct pipe_clip_state clip;
unsigned sample_mask;
struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
unsigned num_vtxbufs;
struct pipe_index_buffer idxbuf;
uint32_t vbo_fifo;
uint32_t vbo_user;
unsigned vbo_min_index;
unsigned vbo_max_index;
boolean vbo_push_hint;
struct nouveau_heap *blit_vp;
struct pipe_resource *blit_fp;
/*XXX: nvfx state, DO NOT USE EVER OUTSIDE "STOLEN" NVFX code */
unsigned is_nv4x;
unsigned use_nv4x;
bool hw_pointsprite_control;
enum {
HW,
} render_mode;
};
static INLINE struct nv30_context *
nv30_context(struct pipe_context *pipe)
{
return (struct nv30_context *)pipe;
}
struct pipe_context *
nv30_context_create(struct pipe_screen *pscreen, void *priv);
void
nv30_vbo_init(struct pipe_context *pipe);
void
nv30_vbo_validate(struct nv30_context *nv30);
void
nv30_query_init(struct pipe_context *pipe);
void
nv30_state_init(struct pipe_context *pipe);
void
nv30_clear_init(struct pipe_context *pipe);
void
nv30_vertprog_init(struct pipe_context *pipe);
void
nv30_vertprog_validate(struct nv30_context *nv30);
void
nv30_fragprog_init(struct pipe_context *pipe);
void
nv30_fragprog_validate(struct nv30_context *nv30);
void
nv30_texture_init(struct pipe_context *pipe);
void
nv30_texture_validate(struct nv30_context *nv30);
void
nv30_fragtex_init(struct pipe_context *pipe);
void
nv30_fragtex_validate(struct nv30_context *nv30);
void
nv40_verttex_init(struct pipe_context *pipe);
void
nv40_verttex_validate(struct nv30_context *nv30);
void
nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info);
void
nv30_draw_init(struct pipe_context *pipe);
void
nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info);
boolean
nv30_state_validate(struct nv30_context *nv30, boolean hwtnl);
void
nv30_state_release(struct nv30_context *nv30);
//XXX: needed to make it build, clean this up!
void
_nvfx_fragprog_translate(struct nv30_context *nvfx, struct nv30_fragprog *fp,
boolean emulate_sprite_flipping);
boolean
_nvfx_vertprog_translate(struct nv30_context *nv30, struct nv30_vertprog *vp);
#ifdef NV30_3D_VERTEX_BEGIN_END
#define NV30_PRIM_GL_CASE(n) \
case PIPE_PRIM_##n: return NV30_3D_VERTEX_BEGIN_END_##n
static INLINE unsigned
nv30_prim_gl(unsigned prim)
{
switch (prim) {
NV30_PRIM_GL_CASE(POINTS);
NV30_PRIM_GL_CASE(LINES);
NV30_PRIM_GL_CASE(LINE_LOOP);
NV30_PRIM_GL_CASE(LINE_STRIP);
NV30_PRIM_GL_CASE(TRIANGLES);
NV30_PRIM_GL_CASE(TRIANGLE_STRIP);
NV30_PRIM_GL_CASE(TRIANGLE_FAN);
NV30_PRIM_GL_CASE(QUADS);
NV30_PRIM_GL_CASE(QUAD_STRIP);
NV30_PRIM_GL_CASE(POLYGON);
default:
return NV30_3D_VERTEX_BEGIN_END_POINTS;
break;
}
}
#endif
#endif
+496
View File
@@ -0,0 +1,496 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pipe.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_private.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_format.h"
struct nv30_render {
struct vbuf_render base;
struct nv30_context *nv30;
struct pipe_transfer *transfer;
struct pipe_resource *buffer;
unsigned offset;
unsigned length;
struct vertex_info vertex_info;
struct nouveau_heap *vertprog;
uint32_t vtxprog[16][4];
uint32_t vtxfmt[16];
uint32_t vtxptr[16];
uint32_t prim;
};
static INLINE struct nv30_render *
nv30_render(struct vbuf_render *render)
{
return (struct nv30_render *)render;
}
static const struct vertex_info *
nv30_render_get_vertex_info(struct vbuf_render *render)
{
return &nv30_render(render)->vertex_info;
}
static boolean
nv30_render_allocate_vertices(struct vbuf_render *render,
ushort vertex_size, ushort nr_vertices)
{
struct nv30_render *r = nv30_render(render);
struct nv30_context *nv30 = r->nv30;
r->length = vertex_size * nr_vertices;
if (r->offset + r->length >= render->max_vertex_buffer_bytes) {
pipe_resource_reference(&r->buffer, NULL);
r->buffer = pipe_buffer_create(&nv30->screen->base.base,
PIPE_BIND_VERTEX_BUFFER, 0,
render->max_vertex_buffer_bytes);
if (!r->buffer)
return FALSE;
r->offset = 0;
}
return TRUE;
}
static void *
nv30_render_map_vertices(struct vbuf_render *render)
{
struct nv30_render *r = nv30_render(render);
char *map = pipe_buffer_map(&r->nv30->base.pipe, r->buffer,
PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_UNSYNCHRONIZED, &r->transfer);
return map + r->offset;
}
static void
nv30_render_unmap_vertices(struct vbuf_render *render,
ushort min_index, ushort max_index)
{
struct nv30_render *r = nv30_render(render);
pipe_buffer_unmap(&r->nv30->base.pipe, r->transfer);
}
static void
nv30_render_set_primitive(struct vbuf_render *render, unsigned prim)
{
struct nv30_render *r = nv30_render(render);
r->prim = nv30_prim_gl(prim);
}
static void
nv30_render_draw_elements(struct vbuf_render *render,
const ushort *indices, uint count)
{
struct nv30_render *r = nv30_render(render);
struct nv30_context *nv30 = r->nv30;
struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
unsigned i;
BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
for (i = 0; i < r->vertex_info.num_attribs; i++) {
PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
nv04_resource(r->buffer), r->offset + r->vtxptr[i],
NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
}
if (!nv30_state_validate(nv30, FALSE))
return;
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, r->prim);
if (count & 1) {
BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
PUSH_DATA (push, *indices++);
}
count >>= 1;
while (count) {
unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
count -= npush;
BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
while (npush--) {
PUSH_DATA(push, (indices[1] << 16) | indices[0]);
indices += 2;
}
}
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
PUSH_RESET(push, BUFCTX_VTXTMP);
}
static void
nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr)
{
struct nv30_render *r = nv30_render(render);
struct nv30_context *nv30 = r->nv30;
struct nouveau_pushbuf *push = nv30->base.pushbuf;
unsigned fn = nr >> 8, pn = nr & 0xff;
unsigned ps = fn + (pn ? 1 : 0);
unsigned i;
BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
for (i = 0; i < r->vertex_info.num_attribs; i++) {
PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
nv04_resource(r->buffer), r->offset + r->vtxptr[i],
NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
}
if (!nv30_state_validate(nv30, FALSE))
return;
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, r->prim);
BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps);
while (fn--) {
PUSH_DATA (push, 0xff000000 | start);
start += 256;
}
if (pn)
PUSH_DATA (push, ((pn - 1) << 24) | start);
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
PUSH_RESET(push, BUFCTX_VTXTMP);
}
static void
nv30_render_release_vertices(struct vbuf_render *render)
{
struct nv30_render *r = nv30_render(render);
r->offset += r->length;
}
static const struct {
unsigned emit;
unsigned interp;
unsigned vp30;
unsigned vp40;
unsigned ow40;
} vroute [] = {
[TGSI_SEMANTIC_POSITION] = { EMIT_4F, INTERP_PERSPECTIVE, 0, 0, 0x00000000 },
[TGSI_SEMANTIC_COLOR ] = { EMIT_4F, INTERP_LINEAR , 3, 1, 0x00000001 },
[TGSI_SEMANTIC_BCOLOR ] = { EMIT_4F, INTERP_LINEAR , 1, 3, 0x00000004 },
[TGSI_SEMANTIC_FOG ] = { EMIT_4F, INTERP_PERSPECTIVE, 5, 5, 0x00000010 },
[TGSI_SEMANTIC_PSIZE ] = { EMIT_1F_PSIZE, INTERP_POS , 6, 6, 0x00000020 },
[TGSI_SEMANTIC_GENERIC ] = { EMIT_4F, INTERP_PERSPECTIVE, 8, 7, 0x00004000 }
};
static boolean
vroute_add(struct nv30_render *r, uint attrib, uint sem, uint *idx)
{
struct pipe_screen *pscreen = &r->nv30->screen->base.base;
struct nv30_fragprog *fp = r->nv30->fragprog.program;
struct vertex_info *vinfo = &r->vertex_info;
enum pipe_format format;
uint emit = EMIT_OMIT;
uint result = *idx;
if (sem == TGSI_SEMANTIC_GENERIC && result >= 8) {
for (result = 0; result < 8; result++) {
if (fp->texcoord[result] == *idx) {
emit = vroute[sem].emit;
break;
}
}
} else {
emit = vroute[sem].emit;
}
if (emit == EMIT_OMIT)
return FALSE;
draw_emit_vertex_attr(vinfo, emit, vroute[sem].interp, attrib);
format = draw_translate_vinfo_format(emit);
r->vtxfmt[attrib] = nv30_vtxfmt(pscreen, format)->hw;
r->vtxptr[attrib] = vinfo->size | NV30_3D_VTXBUF_DMA1;
vinfo->size += draw_translate_vinfo_size(emit);
if (nv30_screen(pscreen)->eng3d->oclass < NV40_3D_CLASS) {
r->vtxprog[attrib][0] = 0x001f38d8;
r->vtxprog[attrib][1] = 0x0080001b | (attrib << 9);
r->vtxprog[attrib][2] = 0x0836106c;
r->vtxprog[attrib][3] = 0x2000f800 | (result + vroute[sem].vp30) << 2;
} else {
r->vtxprog[attrib][0] = 0x401f9c6c;
r->vtxprog[attrib][1] = 0x0040000d | (attrib << 8);
r->vtxprog[attrib][2] = 0x8106c083;
r->vtxprog[attrib][3] = 0x6041ff80 | (result + vroute[sem].vp40) << 2;
}
*idx = vroute[sem].ow40 << result;
return TRUE;
}
static boolean
nv30_render_validate(struct nv30_context *nv30)
{
struct nv30_render *r = nv30_render(nv30->draw->render);
struct nv30_rasterizer_stateobj *rast = nv30->rast;
struct pipe_screen *pscreen = &nv30->screen->base.base;
struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
struct nouveau_object *eng3d = nv30->screen->eng3d;
struct nv30_vertprog *vp = nv30->vertprog.program;
struct vertex_info *vinfo = &r->vertex_info;
unsigned vp_attribs = 0;
unsigned vp_results = 0;
unsigned attrib = 0;
unsigned pntc;
int i;
if (!r->vertprog) {
struct nouveau_heap *heap = nv30_screen(pscreen)->vp_exec_heap;
if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) {
while (heap->next && heap->size < 16) {
struct nouveau_heap **evict = heap->next->priv;
nouveau_heap_free(evict);
}
if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog))
return FALSE;
}
}
vinfo->num_attribs = 0;
vinfo->size = 0;
/* setup routing for all necessary vp outputs */
for (i = 0; i < vp->info.num_outputs && attrib < 16; i++) {
uint semantic = vp->info.output_semantic_name[i];
uint index = vp->info.output_semantic_index[i];
if (vroute_add(r, attrib, semantic, &index)) {
vp_attribs |= (1 << attrib++);
vp_results |= index;
}
}
/* setup routing for replaced point coords not written by vp */
if (rast && rast->pipe.point_quad_rasterization)
pntc = rast->pipe.sprite_coord_enable & 0x000002ff;
else
pntc = 0;
while (pntc && attrib < 16) {
uint index = ffs(pntc) - 1; pntc &= ~(1 << index);
if (vroute_add(r, attrib, TGSI_SEMANTIC_GENERIC, &index)) {
vp_attribs |= (1 << attrib++);
vp_results |= index;
}
}
/* modify vertex format for correct stride, and stub out unused ones */
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);
PUSH_DATA (push, r->vertprog->start);
r->vtxprog[attrib - 1][3] |= 1;
for (i = 0; i < attrib; i++) {
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
PUSH_DATAp(push, r->vtxprog[i], 4);
r->vtxfmt[i] |= vinfo->size << 8;
}
for (; i < 16; i++)
r->vtxfmt[i] = NV30_3D_VTXFMT_TYPE_V32_FLOAT;
BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 1.0);
PUSH_DATAf(push, 1.0);
PUSH_DATAf(push, 1.0);
PUSH_DATAf(push, 1.0);
BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 1.0);
BEGIN_NV04(push, NV30_3D(VTXFMT(0)), 16);
PUSH_DATAp(push, r->vtxfmt, 16);
BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
PUSH_DATA (push, r->vertprog->start);
BEGIN_NV04(push, NV30_3D(ENGINE), 1);
PUSH_DATA (push, 0x00000103);
if (eng3d->oclass >= NV40_3D_CLASS) {
BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
PUSH_DATA (push, vp_attribs);
PUSH_DATA (push, vp_results);
}
vinfo->size /= 4;
return TRUE;
}
void
nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct draw_context *draw = nv30->draw;
struct pipe_transfer *transfer[PIPE_MAX_ATTRIBS];
struct pipe_transfer *transferi = NULL;
int i;
nv30_render_validate(nv30);
if (nv30->draw_dirty & NV30_NEW_VIEWPORT)
draw_set_viewport_state(draw, &nv30->viewport);
if (nv30->draw_dirty & NV30_NEW_RASTERIZER)
draw_set_rasterizer_state(draw, &nv30->rast->pipe, NULL);
if (nv30->draw_dirty & NV30_NEW_CLIP)
draw_set_clip_state(draw, &nv30->clip);
if (nv30->draw_dirty & NV30_NEW_ARRAYS) {
draw_set_vertex_buffers(draw, nv30->num_vtxbufs, nv30->vtxbuf);
draw_set_vertex_elements(draw, nv30->vertex->num_elements, nv30->vertex->pipe);
}
if (nv30->draw_dirty & NV30_NEW_FRAGPROG) {
struct nv30_fragprog *fp = nv30->fragprog.program;
if (!fp->draw)
fp->draw = draw_create_fragment_shader(draw, &fp->pipe);
draw_bind_fragment_shader(draw, fp->draw);
}
if (nv30->draw_dirty & NV30_NEW_VERTPROG) {
struct nv30_vertprog *vp = nv30->vertprog.program;
if (!vp->draw)
vp->draw = draw_create_vertex_shader(draw, &vp->pipe);
draw_bind_vertex_shader(draw, vp->draw);
}
if (nv30->draw_dirty & NV30_NEW_VERTCONST) {
if (nv30->vertprog.constbuf) {
void *map = nv04_resource(nv30->vertprog.constbuf)->data;
draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
map, nv30->vertprog.constbuf_nr);
}
}
for (i = 0; i < nv30->num_vtxbufs; i++) {
void *map = pipe_buffer_map(pipe, nv30->vtxbuf[i].buffer,
PIPE_TRANSFER_UNSYNCHRONIZED |
PIPE_TRANSFER_READ, &transfer[i]);
draw_set_mapped_vertex_buffer(draw, i, map);
}
if (info->indexed) {
void *map = pipe_buffer_map(pipe, nv30->idxbuf.buffer,
PIPE_TRANSFER_UNSYNCHRONIZED |
PIPE_TRANSFER_READ, &transferi);
draw_set_index_buffer(draw, &nv30->idxbuf);
draw_set_mapped_index_buffer(draw, map);
} else {
draw_set_mapped_index_buffer(draw, NULL);
}
draw_vbo(draw, info);
draw_flush(draw);
if (info->indexed)
pipe_buffer_unmap(pipe, transferi);
for (i = 0; i < nv30->num_vtxbufs; i++)
pipe_buffer_unmap(pipe, transfer[i]);
nv30->draw_dirty = 0;
nv30_state_release(nv30);
}
static void
nv30_render_destroy(struct vbuf_render *render)
{
FREE(render);
}
static struct vbuf_render *
nv30_render_create(struct nv30_context *nv30)
{
struct nv30_render *r = CALLOC_STRUCT(nv30_render);
if (!r)
return NULL;
r->nv30 = nv30;
r->offset = 1 * 1024 * 1024;
r->base.max_indices = 16 * 1024;
r->base.max_vertex_buffer_bytes = r->offset;
r->base.get_vertex_info = nv30_render_get_vertex_info;
r->base.allocate_vertices = nv30_render_allocate_vertices;
r->base.map_vertices = nv30_render_map_vertices;
r->base.unmap_vertices = nv30_render_unmap_vertices;
r->base.set_primitive = nv30_render_set_primitive;
r->base.draw_elements = nv30_render_draw_elements;
r->base.draw_arrays = nv30_render_draw_arrays;
r->base.release_vertices = nv30_render_release_vertices;
r->base.destroy = nv30_render_destroy;
return &r->base;
}
void
nv30_draw_init(struct pipe_context *pipe)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct vbuf_render *render;
struct draw_context *draw;
struct draw_stage *stage;
draw = draw_create(pipe);
if (!draw)
return;
render = nv30_render_create(nv30);
if (!render) {
draw_destroy(draw);
return;
}
stage = draw_vbuf_stage(draw, render);
if (!stage) {
render->destroy(render);
draw_destroy(draw);
return;
}
draw_set_render(draw, render);
draw_set_rasterize_stage(draw, stage);
draw_wide_line_threshold(draw, 10000000.f);
draw_wide_point_threshold(draw, 10000000.f);
draw_wide_point_sprites(draw, TRUE);
nv30->draw = draw;
}
+265
View File
@@ -0,0 +1,265 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_format.h"
#define NV30_3D_RT_FORMAT_COLOR_X1R5G5B5 2
#define NV30_3D_TEX_FORMAT_FORMAT_A16L16 NV30_3D_TEX_FORMAT_FORMAT_HILO16
#define NV30_3D_TEX_FORMAT_FORMAT_A16L16_RECT NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT
#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
#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 NV30_3D_TEX_FORMAT_FORMAT_RG16F 0xdeadcafe
#define NV30_3D_TEX_FORMAT_FORMAT_RG16F_RECT 0xdeadcafe
#define NV40_3D_TEX_FORMAT_FORMAT_R32F 0x00001c00
#define NV40_3D_TEX_FORMAT_FORMAT_RG16F 0x00001f00
#define ____ 0
#define S___ PIPE_BIND_SAMPLER_VIEW
#define _R__ PIPE_BIND_RENDER_TARGET
#define _B__ PIPE_BIND_RENDER_TARGET | PIPE_BIND_BLENDABLE
#define _Z__ PIPE_BIND_DEPTH_STENCIL
#define __V_ PIPE_BIND_VERTEX_BUFFER
#define SR__ (S___ | _R__)
#define SB__ (S___ | _B__)
#define SZ__ (S___ | _Z__)
#define S_V_ (S___ | __V_)
#define SRV_ (SR__ | __V_)
#define SBV_ (SB__ | __V_)
#define _(a,b) [PIPE_FORMAT_##a] = { \
.bindings = (b), \
}
const struct nv30_format_info
nv30_format_info_table[PIPE_FORMAT_COUNT] = {
_(L8_UNORM , S___),
_(L8_SNORM , S___),
_(L8_SRGB , S___),
_(I8_UNORM , S___),
_(I8_SNORM , S___),
_(A8_UNORM , S___),
_(A8_SNORM , S___),
_(R8_UNORM , S_V_),
_(R8_SNORM , S___),
_(B5G5R5X1_UNORM , SB__),
_(B5G5R5A1_UNORM , S___),
_(B4G4R4X4_UNORM , S___),
_(B4G4R4A4_UNORM , S___),
_(B5G6R5_UNORM , SB__),
_(B8G8R8X8_UNORM , SB__),
_(B8G8R8X8_SRGB , S___),
_(B8G8R8A8_UNORM , SB__),
_(B8G8R8A8_SRGB , S___),
_(R8G8B8A8_UNORM , __V_),
_(R8G8B8A8_SNORM , S___),
_(DXT1_RGB , S___),
_(DXT1_SRGB , S___),
_(DXT1_RGBA , S___),
_(DXT1_SRGBA , S___),
_(DXT3_RGBA , S___),
_(DXT3_SRGBA , S___),
_(DXT5_RGBA , S___),
_(DXT5_SRGBA , S___),
_(L8A8_UNORM , S___),
_(L8A8_SRGB , S___),
_(R8G8_UNORM , S_V_),
_(R8G8_SNORM , S___),
_(R8G8B8_UNORM , __V_),
_(Z16_UNORM , SZ__),
_(X8Z24_UNORM , SZ__),
_(S8_UINT_Z24_UNORM , SZ__),
_(L16_UNORM , S___),
_(L16_SNORM , S___),
_(I16_UNORM , S___),
_(I16_SNORM , S___),
_(A16_UNORM , S___),
_(A16_SNORM , S___),
_(R16_UNORM , S___),
_(R16_SNORM , S_V_),
_(R16G16_SNORM , __V_),
_(R16G16B16_SNORM , __V_),
_(R16G16B16A16_SNORM , __V_),
_(R8_USCALED , __V_),
_(R8G8_USCALED , __V_),
_(R8G8B8_USCALED , __V_),
_(R8G8B8A8_USCALED , __V_),
_(R16_FLOAT , __V_),
_(R16G16_FLOAT , __V_), //S_V_),
_(R16G16B16_FLOAT , __V_),
_(R16G16B16A16_FLOAT , __V_), //SBV_),
_(R16_SSCALED , __V_),
_(R16G16_SSCALED , __V_),
_(R16G16B16_SSCALED , __V_),
_(R16G16B16A16_SSCALED, __V_),
_(R32_FLOAT , __V_), //SRV_),
_(R32G32_FLOAT , __V_),
_(R32G32B32_FLOAT , __V_),
_(R32G32B32A32_FLOAT , __V_), //SRV_),
};
#undef _
#undef ____
#define R_(a,b) [PIPE_FORMAT_##a] = { \
.hw = NV30_3D_RT_FORMAT_COLOR_##b, \
}
#define Z_(a,b) [PIPE_FORMAT_##a] = { \
.hw = NV30_3D_RT_FORMAT_ZETA_##b, \
}
const struct nv30_format
nv30_format_table[PIPE_FORMAT_COUNT] = {
R_(B5G5R5X1_UNORM , X1R5G5B5 ),
R_(B5G6R5_UNORM , R5G6B5 ),
R_(B8G8R8X8_UNORM , X8R8G8B8 ),
R_(B8G8R8A8_UNORM , A8R8G8B8 ),
Z_(Z16_UNORM , Z16 ),
Z_(X8Z24_UNORM , Z24S8 ),
Z_(S8_UINT_Z24_UNORM , Z24S8 ),
R_(R16G16B16A16_FLOAT, A16B16G16R16_FLOAT),
R_(R32G32B32A32_FLOAT, A32B32G32R32_FLOAT),
R_(R32_FLOAT , R32_FLOAT ),
};
#define _(a,b,c) [PIPE_FORMAT_##a] = { \
.hw = NV30_3D_VTXFMT_TYPE_##b | ((c) << NV30_3D_VTXFMT_SIZE__SHIFT) \
}
const struct nv30_vtxfmt
nv30_vtxfmt_table[PIPE_FORMAT_COUNT] = {
_(R8_UNORM , U8_UNORM , 1),
_(R8G8_UNORM , U8_UNORM , 2),
_(R8G8B8_UNORM , U8_UNORM , 3),
_(R8G8B8A8_UNORM , U8_UNORM , 4),
_(R8_USCALED , U8_USCALED , 1),
_(R8G8_USCALED , U8_USCALED , 2),
_(R8G8B8_USCALED , U8_USCALED , 3),
_(R8G8B8A8_USCALED , U8_USCALED , 4),
_(R16_SNORM , V16_SNORM , 1),
_(R16G16_SNORM , V16_SNORM , 2),
_(R16G16B16_SNORM , V16_SNORM , 3),
_(R16G16B16A16_SNORM , V16_SNORM , 4),
_(R16_SSCALED , V16_SSCALED, 1),
_(R16G16_SSCALED , V16_SSCALED, 2),
_(R16G16B16_SSCALED , V16_SSCALED, 3),
_(R16G16B16A16_SSCALED, V16_SSCALED, 4),
_(R16_FLOAT , V16_FLOAT , 1),
_(R16G16_FLOAT , V16_FLOAT , 2),
_(R16G16B16_FLOAT , V16_FLOAT , 3),
_(R16G16B16A16_FLOAT , V16_FLOAT , 4),
_(R32_FLOAT , V32_FLOAT , 1),
_(R32G32_FLOAT , V32_FLOAT , 2),
_(R32G32B32_FLOAT , V32_FLOAT , 3),
_(R32G32B32A32_FLOAT , V32_FLOAT , 4),
};
#undef _
#define SWZ_OUT_0 0
#define SWZ_OUT_1 1
#define SWZ_OUT_C 2
#define SWZ_SRC_0 3
#define SWZ_SRC_1 2
#define SWZ_SRC_2 1
#define SWZ_SRC_3 0
#define SWZ_SRC_x 0
#define NONE 0x00000000
#define SRGB 0x00700000
#define ____ 0x00000000
#define SSSS 0xf0000000
#define _(a,b,c,d,e,f,g,h,i,j,k,l,m) [PIPE_FORMAT_##a] = { \
.nv30 = NV30_3D_TEX_FORMAT_FORMAT_##b, \
.nv30_rect = NV30_3D_TEX_FORMAT_FORMAT_##b##_RECT, \
.nv40 = NV40_3D_TEX_FORMAT_FORMAT_##b, \
.swz[0] = { SWZ_OUT_##d, SWZ_SRC_##h }, \
.swz[1] = { SWZ_OUT_##e, SWZ_SRC_##i }, \
.swz[2] = { SWZ_OUT_##f, SWZ_SRC_##j }, \
.swz[3] = { SWZ_OUT_##g, SWZ_SRC_##k }, \
.swz[4] = { SWZ_OUT_0, SWZ_SRC_x }, \
.swz[5] = { SWZ_OUT_1, SWZ_SRC_x }, \
.swizzle = (c) * 0x00010000, \
.wrap = (l), \
.filter = (m), \
}
const struct nv30_texfmt
nv30_texfmt_table[PIPE_FORMAT_COUNT] = {
_(L8_UNORM , L8 , 0, C, C, C, 1, 0, 0, 0, x, NONE, ____),
_(L8_SNORM , L8 , 0, C, C, C, 1, 0, 0, 0, x, NONE, SSSS),
_(L8_SRGB , L8 , 0, C, C, C, 1, 0, 0, 0, x, SRGB, ____),
_(I8_UNORM , L8 , 0, C, C, C, C, 0, 0, 0, 0, NONE, ____),
_(I8_SNORM , L8 , 0, C, C, C, C, 0, 0, 0, 0, NONE, SSSS),
_(A8_UNORM , L8 , 0, 0, 0, 0, C, x, x, x, 0, NONE, ____),
_(A8_SNORM , L8 , 0, 0, 0, 0, C, x, x, x, 0, NONE, SSSS),
_(R8_UNORM , L8 , 0, C, 0, 0, 1, 0, x, x, x, NONE, ____),
_(R8_SNORM , L8 , 0, C, 0, 0, 1, 0, x, x, x, NONE, SSSS),
_(B5G5R5X1_UNORM , A1R5G5B5, 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
_(B5G5R5A1_UNORM , A1R5G5B5, 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
_(B4G4R4X4_UNORM , A4R4G4B4, 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
_(B4G4R4A4_UNORM , A4R4G4B4, 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
_(B5G6R5_UNORM , R5G6B5 , 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
_(B8G8R8X8_UNORM , A8R8G8B8, 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
_(B8G8R8X8_SRGB , A8R8G8B8, 0, C, C, C, 1, 2, 1, 0, x, SRGB, ____),
_(B8G8R8A8_UNORM , A8R8G8B8, 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
_(B8G8R8A8_SRGB , A8R8G8B8, 0, C, C, C, C, 2, 1, 0, 3, SRGB, ____),
_(R8G8B8A8_SNORM , A8R8G8B8, 0, C, C, C, C, 0, 1, 2, 3, NONE, SSSS),
_(DXT1_RGB , DXT1 , 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
_(DXT1_SRGB , DXT1 , 0, C, C, C, 1, 2, 1, 0, x, SRGB, ____),
_(DXT1_RGBA , DXT1 , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
_(DXT1_SRGBA , DXT1 , 0, C, C, C, C, 2, 1, 0, 3, SRGB, ____),
_(DXT3_RGBA , DXT3 , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
_(DXT3_SRGBA , DXT3 , 0, C, C, C, C, 2, 1, 0, 3, SRGB, ____),
_(DXT5_RGBA , DXT5 , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
_(DXT5_SRGBA , DXT5 , 0, C, C, C, C, 2, 1, 0, 3, SRGB, ____),
_(L8A8_UNORM , A8L8 , 0, C, C, C, C, 0, 0, 0, 3, NONE, ____),
_(L8A8_SRGB , A8L8 , 0, C, C, C, C, 0, 0, 0, 3, SRGB, ____),
_(R8G8_UNORM , A8L8 , 0, C, C, 0, 1, 0, 3, x, x, NONE, ____),
_(R8G8_SNORM , A8L8 , 0, C, C, 0, 1, 0, 3, x, x, NONE, SSSS),
_(Z16_UNORM , Z16 , 0, C, C, C, 1, 3, 3, 3, x, NONE, ____),
_(X8Z24_UNORM , Z24 , 0, C, C, C, 1, 3, 3, 3, x, NONE, ____),
_(S8_UINT_Z24_UNORM , Z24 , 0, C, C, C, 1, 3, 3, 3, x, NONE, ____),
_(L16_UNORM , A16 , 0, C, C, C, 1, 1, 1, 1, 1, NONE, ____),
_(L16_SNORM , A16 , 0, C, C, C, 1, 1, 1, 1, 1, NONE, SSSS),
_(I16_UNORM , A16 , 0, C, C, C, C, 1, 1, 1, 1, NONE, ____),
_(I16_SNORM , A16 , 0, C, C, C, C, 1, 1, 1, 1, NONE, SSSS),
_(A16_UNORM , A16 , 0, 0, 0, 0, C, 1, 1, 1, 1, NONE, ____),
_(A16_SNORM , A16 , 0, 0, 0, 0, C, 1, 1, 1, 1, NONE, SSSS),
_(R16_UNORM , A16 , 0, C, 0, 0, 1, 1, 1, 1, 1, NONE, ____),
_(R16_SNORM , A16 , 0, C, 0, 0, 1, 1, 1, 1, 1, NONE, SSSS),
_(R16G16_FLOAT , RG16F , 0, C, C, 0, 1, 2, 1, 0, 3, NONE, ____),
_(R16G16B16A16_FLOAT, RGBA16F , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
_(R32_FLOAT , R32F , 0, C, 0, 0, 1, 2, 1, 0, 3, NONE, ____),
_(R32G32B32A32_FLOAT, RGBA32F , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
};
#undef _
+57
View File
@@ -0,0 +1,57 @@
#ifndef __NV30_FORMAT_H__
#define __NV30_FORMAT_H__
struct nv30_format_info {
unsigned bindings;
};
struct nv30_format {
unsigned hw;
};
struct nv30_vtxfmt {
unsigned hw;
};
struct nv30_texfmt {
unsigned nv30;
unsigned nv30_rect;
unsigned nv40;
struct {
unsigned src;
unsigned cmp;
} swz[6];
unsigned swizzle;
unsigned filter;
unsigned wrap;
};
extern const struct nv30_format_info nv30_format_info_table[];
static INLINE const struct nv30_format_info *
nv30_format_info(struct pipe_screen *pscreen, enum pipe_format format)
{
return &nv30_format_info_table[format];
}
extern const struct nv30_format nv30_format_table[];
static INLINE const struct nv30_format *
nv30_format(struct pipe_screen *pscreen, enum pipe_format format)
{
return &nv30_format_table[format];
}
extern const struct nv30_vtxfmt nv30_vtxfmt_table[];
static INLINE const struct nv30_vtxfmt *
nv30_vtxfmt(struct pipe_screen *pscreen, enum pipe_format format)
{
return &nv30_vtxfmt_table[format];
}
extern const struct nv30_texfmt nv30_texfmt_table[];
static INLINE const struct nv30_texfmt *
nv30_texfmt(struct pipe_screen *pscreen, enum pipe_format format)
{
return &nv30_texfmt_table[format];
}
#endif
+170
View File
@@ -0,0 +1,170 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "tgsi/tgsi_parse.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nvfx_shader.h"
static void
nv30_fragprog_upload(struct nv30_context *nv30)
{
struct nouveau_context *nv = &nv30->base;
struct nv30_fragprog *fp = nv30->fragprog.program;
struct pipe_context *pipe = &nv30->base.pipe;
struct pipe_transfer *transfer;
uint32_t *map;
int i; (void)i;
if (unlikely(!fp->buffer)) {
fp->buffer = pipe_buffer_create(pipe->screen, 0, 0, fp->insn_len * 4);
}
map = pipe_buffer_map(pipe, fp->buffer, PIPE_TRANSFER_WRITE, &transfer);
#ifndef PIPE_ARCH_BIG_ENDIAN
memcpy(map, fp->insn, fp->insn_len * 4);
#else
for (i = 0; i < fp->insn_len; i++)
*map++ = (fp->insn[i] >> 16) | (fp->insn[i] << 16);
#endif
pipe_buffer_unmap(pipe, transfer);
if (nv04_resource(fp->buffer)->domain != NOUVEAU_BO_VRAM)
nouveau_buffer_migrate(nv, nv04_resource(fp->buffer), NOUVEAU_BO_VRAM);
}
void
nv30_fragprog_validate(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_object *eng3d = nv30->screen->eng3d;
struct nv30_fragprog *fp = nv30->fragprog.program;
boolean upload = FALSE;
int i;
if (!fp->translated) {
_nvfx_fragprog_translate(nv30, fp, FALSE);
if (!fp->translated)
return;
upload = TRUE;
}
/* update constants, also needs to be done on every fp switch as we
* have no idea whether the constbuf changed in the meantime
*/
if (nv30->fragprog.constbuf) {
struct pipe_resource *constbuf = nv30->fragprog.constbuf;
uint32_t *cbuf = (uint32_t *)nv04_resource(constbuf)->data;
for (i = 0; i < fp->nr_consts; i++) {
unsigned off = fp->consts[i].offset;
unsigned idx = fp->consts[i].index * 4;
if (!memcmp(&fp->insn[off], &cbuf[idx], 4 * 4))
continue;
memcpy(&fp->insn[off], &cbuf[idx], 4 * 4);
upload = TRUE;
}
}
if (upload)
nv30_fragprog_upload(nv30);
/* FP_ACTIVE_PROGRAM needs to be done again even if only the consts
* were updated. TEX_CACHE_CTL magic is not enough to convince the
* GPU that it should re-read the fragprog from VRAM... sigh.
*/
if (nv30->state.fragprog != fp || upload) {
struct nv04_resource *r = nv04_resource(fp->buffer);
if (!PUSH_SPACE(push, 8))
return;
PUSH_RESET(push, BUFCTX_FRAGPROG);
BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);
PUSH_RESRC(push, NV30_3D(FP_ACTIVE_PROGRAM), BUFCTX_FRAGPROG, r, 0,
NOUVEAU_BO_LOW | NOUVEAU_BO_RD | NOUVEAU_BO_OR,
NV30_3D_FP_ACTIVE_PROGRAM_DMA0,
NV30_3D_FP_ACTIVE_PROGRAM_DMA1);
BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);
PUSH_DATA (push, fp->fp_control);
if (eng3d->oclass < NV40_3D_CLASS) {
BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1);
PUSH_DATA (push, 0x00010004);
BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1);
PUSH_DATA (push, fp->samplers);
} else {
BEGIN_NV04(push, SUBC_3D(0x0b40), 1);
PUSH_DATA (push, 0x00000000);
}
nv30->state.fragprog = fp;
}
}
static void *
nv30_fp_state_create(struct pipe_context *pipe,
const struct pipe_shader_state *cso)
{
struct nv30_fragprog *fp = CALLOC_STRUCT(nv30_fragprog);
if (!fp)
return NULL;
fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
tgsi_scan_shader(fp->pipe.tokens, &fp->info);
return fp;
}
static void
nv30_fp_state_delete(struct pipe_context *pipe, void *hwcso)
{
struct nv30_fragprog *fp = hwcso;
pipe_resource_reference(&fp->buffer, NULL);
FREE((void *)fp->pipe.tokens);
FREE(fp->insn);
FREE(fp);
}
static void
nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->fragprog.program = hwcso;
nv30->dirty |= NV30_NEW_FRAGPROG;
}
void
nv30_fragprog_init(struct pipe_context *pipe)
{
pipe->create_fs_state = nv30_fp_state_create;
pipe->bind_fs_state = nv30_fp_state_bind;
pipe->delete_fs_state = nv30_fp_state_delete;
}
+202
View File
@@ -0,0 +1,202 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_inlines.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_format.h"
void
nv30_fragtex_validate(struct nv30_context *nv30)
{
struct pipe_screen *pscreen = &nv30->screen->base.base;
struct nouveau_object *eng3d = nv30->screen->eng3d;
struct nouveau_pushbuf *push = nv30->base.pushbuf;
unsigned dirty = nv30->fragprog.dirty_samplers;
while (dirty) {
unsigned unit = ffs(dirty) - 1;
struct nv30_sampler_view *sv = (void *)nv30->fragprog.textures[unit];
struct nv30_sampler_state *ss = nv30->fragprog.samplers[unit];
PUSH_RESET(push, BUFCTX_FRAGTEX(unit));
if (ss && sv) {
const struct nv30_texfmt *fmt = nv30_texfmt(pscreen, sv->pipe.format);
struct pipe_resource *pt = sv->pipe.texture;
struct nv30_miptree *mt = nv30_miptree(pt);
unsigned min_lod, max_lod;
u32 filter = sv->filt | (ss->filt & sv->filt_mask);
u32 format = sv->fmt | ss->fmt;
u32 enable = ss->en;
/* handle base_level when not using a mip filter, min/max level
* is unfortunately ignored by the hardware otherwise
*/
if (ss->pipe.min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
if (sv->base_lod)
filter += 0x00020000; /* N/L -> NMN/LMN */
max_lod = sv->base_lod;
min_lod = sv->base_lod;
} else {
max_lod = MIN2(ss->max_lod + sv->base_lod, sv->high_lod);
min_lod = MIN2(ss->min_lod + sv->base_lod, max_lod);
}
if (eng3d->oclass >= NV40_3D_CLASS) {
/* this is a tad stupid of the hardware, but there's no non-rcomp
* z16/z24 texture formats to be had, we have to suffer and lose
* some precision to handle this case.
*/
if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z16)
format |= NV40_3D_TEX_FORMAT_FORMAT_A8L8;
else
if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z24)
format |= NV40_3D_TEX_FORMAT_FORMAT_A16L16;
else
format |= fmt->nv40;
} else {
format |= fmt->nv40;
}
enable |= (min_lod << 19) | (max_lod << 7);
enable |= NV40_3D_TEX_ENABLE_ENABLE;
BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1);
PUSH_DATA (push, sv->npot_size1);
} else {
/* this is a tad stupid of the hardware, but there's no non-rcomp
* z16/z24 texture formats to be had, we have to suffer and lose
* some precision to handle this case.
*/
if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z16) {
if (ss->pipe.normalized_coords)
format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8;
else
format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT;
} else
if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z24) {
if (ss->pipe.normalized_coords)
format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16;
else
format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT;
} else {
if (ss->pipe.normalized_coords)
format |= fmt->nv30;
else
format |= fmt->nv30_rect;
}
} else {
if (ss->pipe.normalized_coords)
format |= fmt->nv30;
else
format |= fmt->nv30_rect;
}
enable |= NV30_3D_TEX_ENABLE_ENABLE;
enable |= (min_lod << 18) | (max_lod << 6);
}
BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8);
PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), BUFCTX_FRAGTEX(unit),
mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), BUFCTX_FRAGTEX(unit),
mt->base.bo, format, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD,
NV30_3D_TEX_FORMAT_DMA0,
NV30_3D_TEX_FORMAT_DMA1);
PUSH_DATA (push, sv->wrap | (ss->wrap & sv->wrap_mask));
PUSH_DATA (push, enable);
PUSH_DATA (push, sv->swz);
PUSH_DATA (push, filter);
PUSH_DATA (push, sv->npot_size0);
PUSH_DATA (push, ss->bcol);
BEGIN_NV04(push, NV30_3D(TEX_FILTER_OPTIMIZATION(unit)), 1);
PUSH_DATA (push, nv30->config.filter);
} else {
BEGIN_NV04(push, NV30_3D(TEX_ENABLE(unit)), 1);
PUSH_DATA (push, 0);
}
dirty &= ~(1 << unit);
}
nv30->fragprog.dirty_samplers = 0;
}
static void
nv30_fragtex_sampler_states_bind(struct pipe_context *pipe,
unsigned nr, void **hwcso)
{
struct nv30_context *nv30 = nv30_context(pipe);
unsigned i;
for (i = 0; i < nr; i++) {
nv30->fragprog.samplers[i] = hwcso[i];
nv30->fragprog.dirty_samplers |= (1 << i);
}
for (; i < nv30->fragprog.num_samplers; i++) {
nv30->fragprog.samplers[i] = NULL;
nv30->fragprog.dirty_samplers |= (1 << i);
}
nv30->fragprog.num_samplers = nr;
nv30->dirty |= NV30_NEW_FRAGTEX;
}
static void
nv30_fragtex_set_sampler_views(struct pipe_context *pipe, unsigned nr,
struct pipe_sampler_view **views)
{
struct nv30_context *nv30 = nv30_context(pipe);
unsigned i;
for (i = 0; i < nr; i++) {
nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i));
pipe_sampler_view_reference(&nv30->fragprog.textures[i], views[i]);
nv30->fragprog.dirty_samplers |= (1 << i);
}
for (; i < nv30->fragprog.num_textures; i++) {
nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i));
pipe_sampler_view_reference(&nv30->fragprog.textures[i], NULL);
nv30->fragprog.dirty_samplers |= (1 << i);
}
nv30->fragprog.num_textures = nr;
nv30->dirty |= NV30_NEW_FRAGTEX;
}
void
nv30_fragtex_init(struct pipe_context *pipe)
{
pipe->bind_fragment_sampler_states = nv30_fragtex_sampler_states_bind;
pipe->set_fragment_sampler_views = nv30_fragtex_set_sampler_views;
}
+442
View File
@@ -0,0 +1,442 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_surface.h"
#include "nouveau/nv_m2mf.xml.h"
#include "nv30_screen.h"
#include "nv30_context.h"
#include "nv30_resource.h"
#include "nv30_transfer.h"
static INLINE unsigned
layer_offset(struct pipe_resource *pt, unsigned level, unsigned layer)
{
struct nv30_miptree *mt = nv30_miptree(pt);
struct nv30_miptree_level *lvl = &mt->level[level];
if (pt->target == PIPE_TEXTURE_CUBE)
return (layer * mt->layer_size) + lvl->offset;
return lvl->offset + (layer * lvl->zslice_size);
}
static boolean
nv30_miptree_get_handle(struct pipe_screen *pscreen,
struct pipe_resource *pt,
struct winsys_handle *handle)
{
struct nv30_miptree *mt = nv30_miptree(pt);
unsigned stride;
if (!mt || !mt->base.bo)
return FALSE;
stride = util_format_get_stride(mt->base.base.format,
mt->base.base.width0);
return nouveau_screen_bo_get_handle(pscreen, mt->base.bo, stride, handle);
}
static void
nv30_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
{
struct nv30_miptree *mt = nv30_miptree(pt);
nouveau_bo_ref(NULL, &mt->base.bo);
FREE(mt);
}
struct nv30_transfer {
struct pipe_transfer base;
struct nv30_rect img;
struct nv30_rect tmp;
unsigned nblocksx;
unsigned nblocksy;
};
static INLINE struct nv30_transfer *
nv30_transfer(struct pipe_transfer *ptx)
{
return (struct nv30_transfer *)ptx;
}
static INLINE void
define_rect(struct pipe_resource *pt, unsigned level, unsigned z,
unsigned x, unsigned y, unsigned w, unsigned h,
struct nv30_rect *rect)
{
struct nv30_miptree *mt = nv30_miptree(pt);
struct nv30_miptree_level *lvl = &mt->level[level];
rect->w = u_minify(pt->width0, level) << mt->ms_x;
rect->w = util_format_get_nblocksx(pt->format, rect->w);
rect->h = u_minify(pt->height0, level) << mt->ms_y;
rect->h = util_format_get_nblocksy(pt->format, rect->h);
rect->d = 1;
rect->z = 0;
if (mt->swizzled) {
if (pt->target == PIPE_TEXTURE_3D) {
rect->d = u_minify(pt->depth0, level);
rect->z = z; z = 0;
}
rect->pitch = 0;
} else {
rect->pitch = lvl->pitch;
}
rect->bo = mt->base.bo;
rect->domain = NOUVEAU_BO_VRAM;
rect->offset = layer_offset(pt, level, z);
rect->cpp = util_format_get_blocksize(pt->format);
rect->x0 = util_format_get_nblocksx(pt->format, x) << mt->ms_x;
rect->y0 = util_format_get_nblocksy(pt->format, y) << mt->ms_y;
rect->x1 = rect->x0 + (w << mt->ms_x);
rect->y1 = rect->y0 + (h << mt->ms_y);
}
void
nv30_resource_copy_region(struct pipe_context *pipe,
struct pipe_resource *dstres, unsigned dst_level,
unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *srcres, unsigned src_level,
const struct pipe_box *src_box)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_rect src, dst;
if (dstres->target == PIPE_BUFFER && srcres->target == PIPE_BUFFER) {
util_resource_copy_region(pipe, dstres, dst_level, dstx, dsty, dstz,
srcres, src_level, src_box);
return;
}
define_rect(srcres, src_level, src_box->z, src_box->x, src_box->y,
src_box->width, src_box->height, &src);
define_rect(dstres, dst_level, dstz, dstx, dsty,
src_box->width, src_box->height, &dst);
nv30_transfer_rect(nv30, NEAREST, &src, &dst);
}
void
nv30_resource_resolve(struct pipe_context *pipe,
const struct pipe_resolve_info *info)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_rect src, dst;
define_rect(info->src.res, 0, 0, info->src.x0, info->src.y0,
info->src.x1 - info->src.x0, info->src.y1 - info->src.y0, &src);
define_rect(info->dst.res, info->dst.level, 0, info->dst.x0, info->dst.y0,
info->dst.x1 - info->dst.x0, info->dst.y1 - info->dst.y0, &dst);
nv30_transfer_rect(nv30, BILINEAR, &src, &dst);
}
static struct pipe_transfer *
nv30_miptree_transfer_new(struct pipe_context *pipe, struct pipe_resource *pt,
unsigned level, unsigned usage,
const struct pipe_box *box)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nouveau_device *dev = nv30->screen->base.device;
struct nv30_transfer *tx;
int ret;
tx = CALLOC_STRUCT(nv30_transfer);
if (!tx)
return NULL;
pipe_resource_reference(&tx->base.resource, pt);
tx->base.level = level;
tx->base.usage = usage;
tx->base.box = *box;
tx->base.stride = util_format_get_nblocksx(pt->format, box->width) *
util_format_get_blocksize(pt->format);
tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) *
tx->base.stride;
tx->nblocksx = util_format_get_nblocksx(pt->format, box->width);
tx->nblocksy = util_format_get_nblocksy(pt->format, box->height);
define_rect(pt, level, box->z, box->x, box->y,
tx->nblocksx, tx->nblocksy, &tx->img);
ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
tx->base.layer_stride, NULL, &tx->tmp.bo);
if (ret) {
pipe_resource_reference(&tx->base.resource, NULL);
FREE(tx);
return NULL;
}
tx->tmp.domain = NOUVEAU_BO_GART;
tx->tmp.offset = 0;
tx->tmp.pitch = tx->base.stride;
tx->tmp.cpp = tx->img.cpp;
tx->tmp.w = tx->nblocksx;
tx->tmp.h = tx->nblocksy;
tx->tmp.d = 1;
tx->tmp.x0 = 0;
tx->tmp.y0 = 0;
tx->tmp.x1 = tx->tmp.w;
tx->tmp.y1 = tx->tmp.h;
tx->tmp.z = 0;
if (usage & PIPE_TRANSFER_READ)
nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp);
return &tx->base;
}
static void
nv30_miptree_transfer_del(struct pipe_context *pipe, struct pipe_transfer *ptx)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_transfer *tx = nv30_transfer(ptx);
if (ptx->usage & PIPE_TRANSFER_WRITE)
nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img);
nouveau_bo_ref(NULL, &tx->tmp.bo);
pipe_resource_reference(&ptx->resource, NULL);
FREE(tx);
}
static void *
nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_transfer *tx = nv30_transfer(ptx);
unsigned access = 0;
int ret;
if (tx->tmp.bo->map)
return tx->tmp.bo->map;
if (ptx->usage & PIPE_TRANSFER_READ)
access |= NOUVEAU_BO_RD;
if (ptx->usage & PIPE_TRANSFER_WRITE)
access |= NOUVEAU_BO_WR;
ret = nouveau_bo_map(tx->tmp.bo, access, nv30->base.client);
if (ret)
return NULL;
return tx->tmp.bo->map;
}
static void
nv30_miptree_transfer_unmap(struct pipe_context *pipe,
struct pipe_transfer *ptx)
{
}
const struct u_resource_vtbl nv30_miptree_vtbl = {
nv30_miptree_get_handle,
nv30_miptree_destroy,
nv30_miptree_transfer_new,
nv30_miptree_transfer_del,
nv30_miptree_transfer_map,
u_default_transfer_flush_region,
nv30_miptree_transfer_unmap,
u_default_transfer_inline_write
};
struct pipe_resource *
nv30_miptree_create(struct pipe_screen *pscreen,
const struct pipe_resource *tmpl)
{
struct nouveau_device *dev = nouveau_screen(pscreen)->device;
struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree);
struct pipe_resource *pt = &mt->base.base;
unsigned blocksz, size;
unsigned w, h, d, l;
int ret;
switch (tmpl->nr_samples) {
case 4:
mt->ms_mode = 0x00004000;
mt->ms_x = 1;
mt->ms_y = 1;
break;
case 2:
mt->ms_mode = 0x00003000;
mt->ms_x = 1;
mt->ms_y = 0;
break;
default:
mt->ms_mode = 0x00000000;
mt->ms_x = 0;
mt->ms_y = 0;
break;
}
mt->base.vtbl = &nv30_miptree_vtbl;
*pt = *tmpl;
pipe_reference_init(&pt->reference, 1);
pt->screen = pscreen;
w = pt->width0 << mt->ms_x;
h = pt->height0 << mt->ms_y;
d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1;
blocksz = util_format_get_blocksize(pt->format);
if ((pt->target == PIPE_TEXTURE_RECT) ||
!util_is_power_of_two(pt->width0) ||
!util_is_power_of_two(pt->height0) ||
!util_is_power_of_two(pt->depth0) ||
util_format_is_compressed(pt->format) ||
util_format_is_float(pt->format) || mt->ms_mode) {
mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz;
mt->uniform_pitch = align(mt->uniform_pitch, 64);
}
if (!mt->uniform_pitch)
mt->swizzled = TRUE;
size = 0;
for (l = 0; l <= pt->last_level; l++) {
struct nv30_miptree_level *lvl = &mt->level[l];
unsigned nbx = util_format_get_nblocksx(pt->format, w);
unsigned nby = util_format_get_nblocksx(pt->format, h);
lvl->offset = size;
lvl->pitch = mt->uniform_pitch;
if (!lvl->pitch)
lvl->pitch = nbx * blocksz;
lvl->zslice_size = lvl->pitch * nby;
size += lvl->zslice_size * d;
w = u_minify(w, 1);
h = u_minify(h, 1);
d = u_minify(d, 1);
}
mt->layer_size = size;
if (pt->target == PIPE_TEXTURE_CUBE) {
if (!mt->uniform_pitch)
mt->layer_size = align(mt->layer_size, 128);
size = mt->layer_size * 6;
}
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo);
if (ret) {
FREE(mt);
return NULL;
}
mt->base.domain = NOUVEAU_BO_VRAM;
return &mt->base.base;
}
struct pipe_resource *
nv30_miptree_from_handle(struct pipe_screen *pscreen,
const struct pipe_resource *tmpl,
struct winsys_handle *handle)
{
struct nv30_miptree *mt;
unsigned stride;
/* only supports 2D, non-mipmapped textures for the moment */
if ((tmpl->target != PIPE_TEXTURE_2D &&
tmpl->target != PIPE_TEXTURE_RECT) ||
tmpl->last_level != 0 ||
tmpl->depth0 != 1 ||
tmpl->array_size > 1)
return NULL;
mt = CALLOC_STRUCT(nv30_miptree);
if (!mt)
return NULL;
mt->base.bo = nouveau_screen_bo_from_handle(pscreen, handle, &stride);
if (mt->base.bo == NULL) {
FREE(mt);
return NULL;
}
mt->base.base = *tmpl;
mt->base.vtbl = &nv30_miptree_vtbl;
pipe_reference_init(&mt->base.base.reference, 1);
mt->base.base.screen = pscreen;
mt->uniform_pitch = stride;
mt->level[0].pitch = mt->uniform_pitch;
mt->level[0].offset = 0;
/* no need to adjust bo reference count */
return &mt->base.base;
}
struct pipe_surface *
nv30_miptree_surface_new(struct pipe_context *pipe,
struct pipe_resource *pt,
const struct pipe_surface *tmpl)
{
struct nv30_miptree *mt = nv30_miptree(pt); /* guaranteed */
struct nv30_surface *ns;
struct pipe_surface *ps;
struct nv30_miptree_level *lvl = &mt->level[tmpl->u.tex.level];
ns = CALLOC_STRUCT(nv30_surface);
if (!ns)
return NULL;
ps = &ns->base;
pipe_reference_init(&ps->reference, 1);
pipe_resource_reference(&ps->texture, pt);
ps->context = pipe;
ps->format = tmpl->format;
ps->usage = tmpl->usage;
ps->u.tex.level = tmpl->u.tex.level;
ps->u.tex.first_layer = tmpl->u.tex.first_layer;
ps->u.tex.last_layer = tmpl->u.tex.last_layer;
ns->width = u_minify(pt->width0, ps->u.tex.level);
ns->height = u_minify(pt->height0, ps->u.tex.level);
ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
ns->offset = layer_offset(pt, ps->u.tex.level, ps->u.tex.first_layer);
if (mt->swizzled)
ns->pitch = 4096; /* random, just something the hw won't reject.. */
else
ns->pitch = lvl->pitch;
/* comment says there are going to be removed, but they're used by the st */
ps->width = ns->width;
ps->height = ns->height;
return ps;
}
void
nv30_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
{
struct nv30_surface *ns = nv30_surface(ps);
pipe_resource_reference(&ps->texture, NULL);
FREE(ns);
}
+280
View File
@@ -0,0 +1,280 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "translate/translate.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_resource.h"
struct push_context {
struct nouveau_pushbuf *push;
void *idxbuf;
float edgeflag;
int edgeflag_attr;
uint32_t vertex_words;
uint32_t packet_vertex_limit;
struct translate *translate;
boolean primitive_restart;
uint32_t prim;
uint32_t restart_index;
};
static INLINE unsigned
prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
{
unsigned i;
for (i = 0; i < push; ++i)
if (elts[i] == index)
break;
return i;
}
static INLINE unsigned
prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)
{
unsigned i;
for (i = 0; i < push; ++i)
if (elts[i] == index)
break;
return i;
}
static INLINE unsigned
prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)
{
unsigned i;
for (i = 0; i < push; ++i)
if (elts[i] == index)
break;
return i;
}
static void
emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
{
uint8_t *elts = (uint8_t *)ctx->idxbuf + start;
while (count) {
unsigned push = MIN2(count, ctx->packet_vertex_limit);
unsigned size, nr;
nr = push;
if (ctx->primitive_restart)
nr = prim_restart_search_i08(elts, push, ctx->restart_index);
size = ctx->vertex_words * nr;
BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
ctx->translate->run_elts8(ctx->translate, elts, nr, 0, ctx->push->cur);
ctx->push->cur += size;
count -= nr;
elts += nr;
if (nr != push) {
BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
PUSH_DATA (ctx->push, ctx->restart_index);
count--;
elts++;
}
}
}
static void
emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
{
uint16_t *elts = (uint16_t *)ctx->idxbuf + start;
while (count) {
unsigned push = MIN2(count, ctx->packet_vertex_limit);
unsigned size, nr;
nr = push;
if (ctx->primitive_restart)
nr = prim_restart_search_i16(elts, push, ctx->restart_index);
size = ctx->vertex_words * nr;
BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
ctx->translate->run_elts16(ctx->translate, elts, nr, 0, ctx->push->cur);
ctx->push->cur += size;
count -= nr;
elts += nr;
if (nr != push) {
BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
PUSH_DATA (ctx->push, ctx->restart_index);
count--;
elts++;
}
}
}
static void
emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
{
uint32_t *elts = (uint32_t *)ctx->idxbuf + start;
while (count) {
unsigned push = MIN2(count, ctx->packet_vertex_limit);
unsigned size, nr;
nr = push;
if (ctx->primitive_restart)
nr = prim_restart_search_i32(elts, push, ctx->restart_index);
size = ctx->vertex_words * nr;
BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
ctx->translate->run_elts(ctx->translate, elts, nr, 0, ctx->push->cur);
ctx->push->cur += size;
count -= nr;
elts += nr;
if (nr != push) {
BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
PUSH_DATA (ctx->push, ctx->restart_index);
count--;
elts++;
}
}
}
static void
emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
{
while (count) {
unsigned push = MIN2(count, ctx->packet_vertex_limit);
unsigned size = ctx->vertex_words * push;
BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
ctx->translate->run(ctx->translate, start, push, 0, ctx->push->cur);
ctx->push->cur += size;
count -= push;
start += push;
}
}
void
nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info)
{
struct push_context ctx;
unsigned i, index_size;
boolean apply_bias = info->indexed && info->index_bias;
ctx.push = nv30->base.pushbuf;
ctx.translate = nv30->vertex->translate;
ctx.packet_vertex_limit = nv30->vertex->vtx_per_packet_max;
ctx.vertex_words = nv30->vertex->vtx_size;
for (i = 0; i < nv30->num_vtxbufs; ++i) {
uint8_t *data;
struct pipe_vertex_buffer *vb = &nv30->vtxbuf[i];
struct nv04_resource *res = nv04_resource(vb->buffer);
data = nouveau_resource_map_offset(&nv30->base, res,
vb->buffer_offset, NOUVEAU_BO_RD);
if (apply_bias)
data += info->index_bias * vb->stride;
ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
}
if (info->indexed) {
ctx.idxbuf = nouveau_resource_map_offset(&nv30->base,
nv04_resource(nv30->idxbuf.buffer),
nv30->idxbuf.offset, NOUVEAU_BO_RD);
if (!ctx.idxbuf) {
nv30_state_release(nv30);
return;
}
index_size = nv30->idxbuf.index_size;
ctx.primitive_restart = info->primitive_restart;
ctx.restart_index = info->restart_index;
} else {
ctx.idxbuf = NULL;
index_size = 0;
ctx.primitive_restart = FALSE;
ctx.restart_index = 0;
}
if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) {
BEGIN_NV04(ctx.push, NV40_3D(PRIM_RESTART_ENABLE), 2);
PUSH_DATA (ctx.push, info->primitive_restart);
PUSH_DATA (ctx.push, info->restart_index);
nv30->state.prim_restart = info->primitive_restart;
}
ctx.prim = nv30_prim_gl(info->mode);
PUSH_RESET(ctx.push, BUFCTX_IDXBUF);
BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (ctx.push, ctx.prim);
switch (index_size) {
case 0:
emit_vertices_seq(&ctx, info->start, info->count);
break;
case 1:
emit_vertices_i08(&ctx, info->start, info->count);
break;
case 2:
emit_vertices_i16(&ctx, info->start, info->count);
break;
case 4:
emit_vertices_i32(&ctx, info->start, info->count);
break;
default:
assert(0);
break;
}
BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (ctx.push, NV30_3D_VERTEX_BEGIN_END_STOP);
if (info->indexed)
nouveau_resource_unmap(nv04_resource(nv30->idxbuf.buffer));
for (i = 0; i < nv30->num_vtxbufs; ++i)
nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer));
nv30_state_release(nv30);
}
+263
View File
@@ -0,0 +1,263 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_screen.h"
#include "nv30_context.h"
#define LIST_FIRST_ENTRY(__type, __item, __field) \
LIST_ENTRY(__type, (__item)->next, __field)
struct nv30_query_object {
struct list_head list;
struct nouveau_heap *hw;
};
static volatile void *
nv30_ntfy(struct nv30_screen *screen, struct nv30_query_object *qo)
{
struct nv04_notify *query = screen->query->data;
struct nouveau_bo *notify = screen->notify;
volatile void *ntfy = NULL;
if (qo && qo->hw)
ntfy = (char *)notify->map + query->offset + qo->hw->start;
return ntfy;
}
static void
nv30_query_object_del(struct nv30_screen *screen, struct nv30_query_object **po)
{
struct nv30_query_object *qo = *po; *po = NULL;
if (qo) {
volatile uint32_t *ntfy = nv30_ntfy(screen, qo);
while (ntfy[3] & 0xff000000) {
}
nouveau_heap_free(&qo->hw);
LIST_DEL(&qo->list);
FREE(qo);
}
}
static struct nv30_query_object *
nv30_query_object_new(struct nv30_screen *screen)
{
struct nv30_query_object *oq, *qo = CALLOC_STRUCT(nv30_query_object);
volatile uint32_t *ntfy;
if (!qo)
return NULL;
/* allocate a new hw query object, if no hw objects left we need to
* spin waiting for one to become free
*/
while (nouveau_heap_alloc(screen->query_heap, 32, NULL, &qo->hw)) {
oq = LIST_FIRST_ENTRY(struct nv30_query_object, &screen->queries, list);
nv30_query_object_del(screen, &oq);
}
LIST_ADDTAIL(&qo->list, &screen->queries);
ntfy = nv30_ntfy(screen, qo);
ntfy[0] = 0x00000000;
ntfy[1] = 0x00000000;
ntfy[2] = 0x00000000;
ntfy[3] = 0x01000000;
return qo;
}
struct nv30_query {
struct nv30_query_object *qo[2];
unsigned type;
uint32_t report;
uint32_t enable;
uint64_t result;
};
static INLINE struct nv30_query *
nv30_query(struct pipe_query *pipe)
{
return (struct nv30_query *)pipe;
}
static struct pipe_query *
nv30_query_create(struct pipe_context *pipe, unsigned type)
{
struct nv30_query *q = CALLOC_STRUCT(nv30_query);
if (!q)
return NULL;
q->type = type;
switch (q->type) {
case PIPE_QUERY_TIME_ELAPSED:
q->enable = 0x0000;
q->report = 1;
break;
case PIPE_QUERY_OCCLUSION_COUNTER:
q->enable = NV30_3D_QUERY_ENABLE;
q->report = 1;
break;
case NV30_QUERY_ZCULL_0:
case NV30_QUERY_ZCULL_1:
case NV30_QUERY_ZCULL_2:
case NV30_QUERY_ZCULL_3:
q->enable = 0x1804;
q->report = 2 + (q->type - NV30_QUERY_ZCULL_0);
break;
default:
FREE(q);
return NULL;
}
return (struct pipe_query *)q;
}
static void
nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
{
FREE(pq);
}
static void
nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_query *q = nv30_query(pq);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
switch (q->type) {
case PIPE_QUERY_TIME_ELAPSED:
q->qo[0] = nv30_query_object_new(nv30->screen);
if (q->qo[0]) {
BEGIN_NV04(push, NV30_3D(QUERY_GET), 1);
PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start);
}
break;
default:
BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1);
PUSH_DATA (push, q->report);
break;
}
if (q->enable) {
BEGIN_NV04(push, SUBC_3D(q->enable), 1);
PUSH_DATA (push, 1);
}
}
static void
nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_screen *screen = nv30->screen;
struct nv30_query *q = nv30_query(pq);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
q->qo[1] = nv30_query_object_new(screen);
if (q->qo[1]) {
BEGIN_NV04(push, NV30_3D(QUERY_GET), 1);
PUSH_DATA (push, (q->report << 24) | q->qo[1]->hw->start);
}
if (q->enable) {
BEGIN_NV04(push, SUBC_3D(q->enable), 1);
PUSH_DATA (push, 0);
}
PUSH_KICK (push);
}
static boolean
nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
boolean wait, void *result)
{
struct nv30_screen *screen = nv30_screen(pipe->screen);
struct nv30_query *q = nv30_query(pq);
volatile uint32_t *ntfy0 = nv30_ntfy(screen, q->qo[0]);
volatile uint32_t *ntfy1 = nv30_ntfy(screen, q->qo[1]);
uint64_t *res64 = result;
if (ntfy1) {
while (ntfy1[3] & 0xff000000) {
if (!wait)
return FALSE;
}
switch (q->type) {
case PIPE_QUERY_TIME_ELAPSED:
q->result = *(uint64_t *)&ntfy1[0] - *(uint64_t *)&ntfy0[0];
break;
default:
q->result = ntfy1[2];
break;
}
nv30_query_object_del(screen, &q->qo[0]);
nv30_query_object_del(screen, &q->qo[1]);
}
*res64 = q->result;
return TRUE;
}
static void
nv40_query_render_condition(struct pipe_context *pipe,
struct pipe_query *pq, uint mode)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_query *q = nv30_query(pq);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
if (!pq) {
BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
PUSH_DATA (push, 0x01000000);
return;
}
if (mode == PIPE_RENDER_COND_WAIT ||
mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
BEGIN_NV04(push, SUBC_3D(0x0110), 1);
PUSH_DATA (push, 0);
}
BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
PUSH_DATA (push, 0x02000000 | q->qo[1]->hw->start);
}
void
nv30_query_init(struct pipe_context *pipe)
{
struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
pipe->create_query = nv30_query_create;
pipe->destroy_query = nv30_query_destroy;
pipe->begin_query = nv30_query_begin;
pipe->end_query = nv30_query_end;
pipe->get_query_result = nv30_query_result;
if (eng3d->oclass >= NV40_3D_CLASS)
pipe->render_condition = nv40_query_render_condition;
}
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "nv30_screen.h"
#include "nv30_context.h"
#include "nv30_resource.h"
#include "nv30_transfer.h"
static struct pipe_resource *
nv30_resource_create(struct pipe_screen *pscreen,
const struct pipe_resource *tmpl)
{
switch (tmpl->target) {
case PIPE_BUFFER:
return nouveau_buffer_create(pscreen, tmpl);
default:
return nv30_miptree_create(pscreen, tmpl);
}
}
static struct pipe_resource *
nv30_resource_from_handle(struct pipe_screen *pscreen,
const struct pipe_resource *tmpl,
struct winsys_handle *handle)
{
if (tmpl->target == PIPE_BUFFER)
return NULL;
else
return nv30_miptree_from_handle(pscreen, tmpl, handle);
}
void
nv30_resource_screen_init(struct pipe_screen *pscreen)
{
pscreen->resource_create = nv30_resource_create;
pscreen->resource_from_handle = nv30_resource_from_handle;
pscreen->resource_get_handle = u_resource_get_handle_vtbl;
pscreen->resource_destroy = u_resource_destroy_vtbl;
pscreen->user_buffer_create = nouveau_user_buffer_create;
}
void
nv30_resource_init(struct pipe_context *pipe)
{
pipe->get_transfer = u_get_transfer_vtbl;
pipe->transfer_map = u_transfer_map_vtbl;
pipe->transfer_flush_region = u_transfer_flush_region_vtbl;
pipe->transfer_unmap = u_transfer_unmap_vtbl;
pipe->transfer_destroy = u_transfer_destroy_vtbl;
pipe->transfer_inline_write = u_transfer_inline_write_vtbl;
pipe->create_surface = nv30_miptree_surface_new;
pipe->surface_destroy = nv30_miptree_surface_del;
pipe->resource_copy_region = nv30_resource_copy_region;
pipe->resource_resolve = nv30_resource_resolve;
}
+71
View File
@@ -0,0 +1,71 @@
#ifndef __NV30_RESOURCE_H__
#define __NV30_RESOURCE_H__
#include "nouveau/nouveau_buffer.h"
void nv30_resource_screen_init(struct pipe_screen *);
void nv30_resource_init(struct pipe_context *);
struct nv30_surface {
struct pipe_surface base;
uint32_t offset;
uint32_t pitch;
uint32_t width;
uint16_t height;
uint16_t depth;
};
static INLINE struct nv30_surface *
nv30_surface(struct pipe_surface *ps)
{
return (struct nv30_surface *)ps;
}
struct nv30_miptree_level {
uint32_t offset;
uint32_t pitch;
uint32_t zslice_size;
};
struct nv30_miptree {
struct nv04_resource base;
struct nv30_miptree_level level[13];
uint32_t uniform_pitch;
uint32_t layer_size;
boolean swizzled;
unsigned ms_mode;
unsigned ms_x:1;
unsigned ms_y:1;
};
static INLINE struct nv30_miptree *
nv30_miptree(struct pipe_resource *pt)
{
return (struct nv30_miptree *)pt;
}
struct pipe_resource *
nv30_miptree_create(struct pipe_screen *, const struct pipe_resource *);
struct pipe_resource *
nv30_miptree_from_handle(struct pipe_screen *, const struct pipe_resource *,
struct winsys_handle *);
struct pipe_surface *
nv30_miptree_surface_new(struct pipe_context *, struct pipe_resource *,
const struct pipe_surface *);
void
nv30_miptree_surface_del(struct pipe_context *, struct pipe_surface *);
void
nv30_resource_copy_region(struct pipe_context *pipe,
struct pipe_resource *dst, unsigned dst_level,
unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *src, unsigned src_level,
const struct pipe_box *src_box);
void
nv30_resource_resolve(struct pipe_context *, const struct pipe_resolve_info *);
#endif
+565
View File
@@ -0,0 +1,565 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_format_s3tc.h"
#include "nouveau/nv_object.xml.h"
#include "nouveau/nv_m2mf.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv01_2d.xml.h"
#include "nouveau/nouveau_fence.h"
#include "nv30_screen.h"
#include "nv30_context.h"
#include "nv30_resource.h"
#include "nv30_format.h"
#define RANKINE_0397_CHIPSET 0x00000003
#define RANKINE_0497_CHIPSET 0x000001e0
#define RANKINE_0697_CHIPSET 0x00000010
#define CURIE_4097_CHIPSET 0x00000baf
#define CURIE_4497_CHIPSET 0x00005450
#define CURIE_4497_CHIPSET6X 0x00000088
static int
nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
{
struct nv30_screen *screen = nv30_screen(pscreen);
struct nouveau_object *eng3d = screen->eng3d;
switch (param) {
/* non-boolean capabilities */
case PIPE_CAP_MAX_RENDER_TARGETS:
return (eng3d->oclass >= NV40_3D_CLASS) ? 4 : 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_MAX_COMBINED_SAMPLERS:
return 16;
case PIPE_CAP_GLSL_FEATURE_LEVEL:
return 120;
/* supported capabilities */
case PIPE_CAP_TWO_SIDED_STENCIL:
case PIPE_CAP_ANISOTROPIC_FILTER:
case PIPE_CAP_POINT_SPRITE:
case PIPE_CAP_SCALED_RESOLVE:
case PIPE_CAP_OCCLUSION_QUERY:
case PIPE_CAP_TIMER_QUERY:
case PIPE_CAP_TEXTURE_SHADOW_MAP:
case PIPE_CAP_TEXTURE_SWIZZLE:
case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
case PIPE_CAP_DEPTH_CLIP_DISABLE:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
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_PIXEL_CENTER_INTEGER:
return 1;
/* nv4x capabilities */
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
case PIPE_CAP_NPOT_TEXTURES:
case PIPE_CAP_CONDITIONAL_RENDER:
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
case PIPE_CAP_PRIMITIVE_RESTART:
return (eng3d->oclass >= NV40_3D_CLASS) ? 1 : 0;
/* unsupported */
case PIPE_CAP_DUAL_SOURCE_BLEND:
case PIPE_CAP_SM3:
case PIPE_CAP_INDEP_BLEND_ENABLE:
case PIPE_CAP_INDEP_BLEND_FUNC:
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
case PIPE_CAP_SHADER_STENCIL_EXPORT:
case PIPE_CAP_TGSI_INSTANCEID:
case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: /* XXX: yes? */
case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
case PIPE_CAP_MIN_TEXEL_OFFSET:
case PIPE_CAP_MAX_TEXEL_OFFSET:
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_TEXTURE_BARRIER:
case PIPE_CAP_SEAMLESS_CUBE_MAP:
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
return 0;
default:
debug_printf("unknown param %d\n", param);
return 0;
}
}
static float
nv30_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
{
struct nv30_screen *screen = nv30_screen(pscreen);
struct nouveau_object *eng3d = screen->eng3d;
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 (eng3d->oclass >= NV40_3D_CLASS) ? 16.0 : 8.0;
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
return 15.0;
default:
debug_printf("unknown paramf %d\n", param);
return 0;
}
}
static int
nv30_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
enum pipe_shader_cap param)
{
struct nv30_screen *screen = nv30_screen(pscreen);
struct nouveau_object *eng3d = screen->eng3d;
switch (shader) {
case PIPE_SHADER_VERTEX:
switch (param) {
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
return (eng3d->oclass >= NV40_3D_CLASS) ? 512 : 256;
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
return (eng3d->oclass >= NV40_3D_CLASS) ? 512 : 0;
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
return 0;
case PIPE_SHADER_CAP_MAX_INPUTS:
return 16;
case PIPE_SHADER_CAP_MAX_CONSTS:
return (eng3d->oclass >= NV40_3D_CLASS) ? (468 - 6): (256 - 6);
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
return 1;
case PIPE_SHADER_CAP_MAX_TEMPS:
return (eng3d->oclass >= NV40_3D_CLASS) ? 32 : 13;
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
return 0;
case PIPE_SHADER_CAP_MAX_ADDRS:
return 2;
case PIPE_SHADER_CAP_MAX_PREDS:
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
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:
case PIPE_SHADER_CAP_SUBROUTINES:
case PIPE_SHADER_CAP_INTEGERS:
return 0;
default:
debug_printf("unknown vertex shader param %d\n", param);
return 0;
}
break;
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:
return 0;
case PIPE_SHADER_CAP_MAX_INPUTS:
return (eng3d->oclass >= NV40_3D_CLASS) ? 12 : 10;
case PIPE_SHADER_CAP_MAX_CONSTS:
return (eng3d->oclass >= NV40_3D_CLASS) ? 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 (eng3d->oclass >= NV40_3D_CLASS) ? 1 : 0;
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
return 16;
case PIPE_SHADER_CAP_MAX_PREDS:
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
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:
case PIPE_SHADER_CAP_SUBROUTINES:
return 0;
default:
debug_printf("unknown fragment shader param %d\n", param);
return 0;
}
break;
default:
return 0;
}
}
static boolean
nv30_screen_is_format_supported(struct pipe_screen *pscreen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned bindings)
{
if (!(0x00000017 & (1 << sample_count)))
return FALSE;
if (!util_format_s3tc_enabled) {
switch (format) {
case PIPE_FORMAT_DXT1_RGB:
case PIPE_FORMAT_DXT1_RGBA:
case PIPE_FORMAT_DXT3_RGBA:
case PIPE_FORMAT_DXT5_RGBA:
return FALSE;
default:
break;
}
}
/* transfers & shared are always supported */
bindings &= ~(PIPE_BIND_TRANSFER_READ |
PIPE_BIND_TRANSFER_WRITE |
PIPE_BIND_SHARED);
return (nv30_format_info(pscreen, format)->bindings & bindings) == bindings;
}
static void
nv30_screen_fence_emit(struct pipe_screen *pscreen, uint32_t *sequence)
{
struct nv30_screen *screen = nv30_screen(pscreen);
struct nouveau_pushbuf *push = screen->base.pushbuf;
*sequence = ++screen->base.fence.sequence;
BEGIN_NV04(push, NV30_3D(FENCE_OFFSET), 2);
PUSH_DATA (push, 0);
PUSH_DATA (push, *sequence);
}
static uint32_t
nv30_screen_fence_update(struct pipe_screen *pscreen)
{
struct nv30_screen *screen = nv30_screen(pscreen);
struct nv04_notify *fence = screen->fence->data;
return *(uint32_t *)((char *)screen->notify->map + fence->offset);
}
static void
nv30_screen_destroy(struct pipe_screen *pscreen)
{
struct nv30_screen *screen = nv30_screen(pscreen);
if (screen->base.fence.current &&
screen->base.fence.current->state >= NOUVEAU_FENCE_STATE_EMITTED) {
nouveau_fence_wait(screen->base.fence.current);
nouveau_fence_ref (NULL, &screen->base.fence.current);
}
nouveau_object_del(&screen->query);
nouveau_object_del(&screen->fence);
nouveau_object_del(&screen->ntfy);
nouveau_object_del(&screen->sifm);
nouveau_object_del(&screen->swzsurf);
nouveau_object_del(&screen->surf2d);
nouveau_object_del(&screen->m2mf);
nouveau_object_del(&screen->eng3d);
nouveau_object_del(&screen->null);
nouveau_screen_fini(&screen->base);
FREE(screen);
}
#define FAIL_SCREEN_INIT(str, err) \
do { \
NOUVEAU_ERR(str, err); \
nv30_screen_destroy(pscreen); \
return NULL; \
} while(0)
struct pipe_screen *
nv30_screen_create(struct nouveau_device *dev)
{
struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
struct pipe_screen *pscreen;
struct nouveau_pushbuf *push;
struct nv04_fifo *fifo;
unsigned oclass = 0;
int ret, i;
if (!screen)
return NULL;
switch (dev->chipset & 0xf0) {
case 0x30:
if (RANKINE_0397_CHIPSET & (1 << (dev->chipset & 0x0f)))
oclass = NV30_3D_CLASS;
else
if (RANKINE_0697_CHIPSET & (1 << (dev->chipset & 0x0f)))
oclass = NV34_3D_CLASS;
else
if (RANKINE_0497_CHIPSET & (1 << (dev->chipset & 0x0f)))
oclass = NV35_3D_CLASS;
break;
case 0x40:
if (CURIE_4097_CHIPSET & (1 << (dev->chipset & 0x0f)))
oclass = NV40_3D_CLASS;
else
if (CURIE_4497_CHIPSET & (1 << (dev->chipset & 0x0f)))
oclass = NV44_3D_CLASS;
break;
case 0x60:
if (CURIE_4497_CHIPSET6X & (1 << (dev->chipset & 0x0f)))
oclass = NV44_3D_CLASS;
break;
default:
break;
}
if (!oclass) {
NOUVEAU_ERR("unknown 3d class for 0x%02x\n", dev->chipset);
return NULL;
}
pscreen = &screen->base.base;
pscreen->destroy = nv30_screen_destroy;
pscreen->get_param = nv30_screen_get_param;
pscreen->get_paramf = nv30_screen_get_paramf;
pscreen->get_shader_param = nv30_screen_get_shader_param;
pscreen->context_create = nv30_context_create;
pscreen->is_format_supported = nv30_screen_is_format_supported;
nv30_resource_screen_init(pscreen);
screen->base.fence.emit = nv30_screen_fence_emit;
screen->base.fence.update = nv30_screen_fence_update;
screen->base.sysmem_bindings = PIPE_BIND_CONSTANT_BUFFER;
if (oclass != NV40_3D_CLASS)
screen->base.sysmem_bindings |= PIPE_BIND_INDEX_BUFFER;
ret = nouveau_screen_init(&screen->base, dev);
if (ret)
FAIL_SCREEN_INIT("nv30_screen_init failed: %d\n", ret);
fifo = screen->base.channel->data;
push = screen->base.pushbuf;
push->rsvd_kick = 16;
ret = nouveau_object_new(screen->base.channel, 0x00000000, NV01_NULL_CLASS,
NULL, 0, &screen->null);
if (ret)
FAIL_SCREEN_INIT("error allocating null object: %d\n", ret);
/* DMA_FENCE refuses to accept DMA objects with "adjust" filled in,
* this means that the address pointed at by the DMA object must
* be 4KiB aligned, which means this object needs to be the first
* one allocated on the channel.
*/
ret = nouveau_object_new(screen->base.channel, 0xbeef1e00,
NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
.length = 32 }, sizeof(struct nv04_notify),
&screen->fence);
if (ret)
FAIL_SCREEN_INIT("error allocating fence notifier: %d\n", ret);
/* DMA_NOTIFY object, we don't actually use this but M2MF fails without */
ret = nouveau_object_new(screen->base.channel, 0xbeef0301,
NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
.length = 32 }, sizeof(struct nv04_notify),
&screen->ntfy);
if (ret)
FAIL_SCREEN_INIT("error allocating sync notifier: %d\n", ret);
/* DMA_QUERY, used to implement occlusion queries, we attempt to allocate
* the remainder of the "notifier block" assigned by the kernel for
* use as query objects
*/
ret = nouveau_object_new(screen->base.channel, 0xbeef0351,
NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
.length = 4096 - 128 }, sizeof(struct nv04_notify),
&screen->query);
if (ret)
FAIL_SCREEN_INIT("error allocating query notifier: %d\n", ret);
ret = nouveau_heap_init(&screen->query_heap, 0, 4096 - 128);
if (ret)
FAIL_SCREEN_INIT("error creating query heap: %d\n", ret);
LIST_INITHEAD(&screen->queries);
/* Vertex program resources (code/data), currently 6 of the constant
* slots are reserved to implement user clipping planes
*/
if (oclass < NV40_3D_CLASS) {
nouveau_heap_init(&screen->vp_exec_heap, 0, 256);
nouveau_heap_init(&screen->vp_data_heap, 6, 256 - 6);
} else {
nouveau_heap_init(&screen->vp_exec_heap, 0, 512);
nouveau_heap_init(&screen->vp_data_heap, 6, 468 - 6);
}
ret = nouveau_bo_wrap(screen->base.device, fifo->notify, &screen->notify);
if (ret == 0)
nouveau_bo_map(screen->notify, 0, screen->base.client);
if (ret)
FAIL_SCREEN_INIT("error mapping notifier memory: %d\n", ret);
ret = nouveau_object_new(screen->base.channel, 0xbeef3097, oclass,
NULL, 0, &screen->eng3d);
if (ret)
FAIL_SCREEN_INIT("error allocating 3d object: %d\n", ret);
BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1);
PUSH_DATA (push, screen->eng3d->handle);
BEGIN_NV04(push, NV30_3D(DMA_NOTIFY), 13);
PUSH_DATA (push, screen->ntfy->handle);
PUSH_DATA (push, fifo->vram); /* TEXTURE0 */
PUSH_DATA (push, fifo->gart); /* TEXTURE1 */
PUSH_DATA (push, fifo->vram); /* COLOR1 */
PUSH_DATA (push, screen->null->handle); /* UNK190 */
PUSH_DATA (push, fifo->vram); /* COLOR0 */
PUSH_DATA (push, fifo->vram); /* ZETA */
PUSH_DATA (push, fifo->vram); /* VTXBUF0 */
PUSH_DATA (push, fifo->gart); /* VTXBUF1 */
PUSH_DATA (push, screen->fence->handle); /* FENCE */
PUSH_DATA (push, screen->query->handle); /* QUERY - intr 0x80 if nullobj */
PUSH_DATA (push, screen->null->handle); /* UNK1AC */
PUSH_DATA (push, screen->null->handle); /* UNK1B0 */
BEGIN_NV04(push, NV30_3D(VIEWPORT_CLIP_MODE), 1);
PUSH_DATA (push, 0);
if (screen->eng3d->oclass < NV40_3D_CLASS) {
BEGIN_NV04(push, SUBC_3D(0x03b0), 1);
PUSH_DATA (push, 0x00100000);
BEGIN_NV04(push, SUBC_3D(0x1d80), 1);
PUSH_DATA (push, 3);
BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, SUBC_3D(0x17e0), 3);
PUSH_DATA (push, fui(0.0));
PUSH_DATA (push, fui(0.0));
PUSH_DATA (push, fui(1.0));
BEGIN_NV04(push, SUBC_3D(0x1f80), 16);
for (i = 0; i < 16; i++)
PUSH_DATA (push, (i == 8) ? 0x0000ffff : 0);
BEGIN_NV04(push, NV30_3D(RC_ENABLE), 1);
PUSH_DATA (push, 0);
} else {
BEGIN_NV04(push, NV40_3D(DMA_COLOR2), 2);
PUSH_DATA (push, fifo->vram);
PUSH_DATA (push, fifo->vram); /* COLOR3 */
BEGIN_NV04(push, SUBC_3D(0x1450), 1);
PUSH_DATA (push, 0x00000004);
BEGIN_NV04(push, SUBC_3D(0x1ea4), 3); /* ZCULL */
PUSH_DATA (push, 0x00000010);
PUSH_DATA (push, 0x01000100);
PUSH_DATA (push, 0xff800006);
/* vtxprog output routing */
BEGIN_NV04(push, SUBC_3D(0x1fc4), 1);
PUSH_DATA (push, 0x06144321);
BEGIN_NV04(push, SUBC_3D(0x1fc8), 2);
PUSH_DATA (push, 0xedcba987);
PUSH_DATA (push, 0x0000006f);
BEGIN_NV04(push, SUBC_3D(0x1fd0), 1);
PUSH_DATA (push, 0x00171615);
BEGIN_NV04(push, SUBC_3D(0x1fd4), 1);
PUSH_DATA (push, 0x001b1a19);
BEGIN_NV04(push, SUBC_3D(0x1ef8), 1);
PUSH_DATA (push, 0x0020ffff);
BEGIN_NV04(push, SUBC_3D(0x1d64), 1);
PUSH_DATA (push, 0x01d300d4);
BEGIN_NV04(push, NV40_3D(MIPMAP_ROUNDING), 1);
PUSH_DATA (push, NV40_3D_MIPMAP_ROUNDING_MODE_DOWN);
}
ret = nouveau_object_new(screen->base.channel, 0xbeef3901, NV03_M2MF_CLASS,
NULL, 0, &screen->m2mf);
if (ret)
FAIL_SCREEN_INIT("error allocating m2mf object: %d\n", ret);
BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
PUSH_DATA (push, screen->m2mf->handle);
BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
PUSH_DATA (push, screen->ntfy->handle);
ret = nouveau_object_new(screen->base.channel, 0xbeef6201,
NV10_SURFACE_2D_CLASS, NULL, 0, &screen->surf2d);
if (ret)
FAIL_SCREEN_INIT("error allocating surf2d object: %d\n", ret);
BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1);
PUSH_DATA (push, screen->surf2d->handle);
BEGIN_NV04(push, NV04_SF2D(DMA_NOTIFY), 1);
PUSH_DATA (push, screen->ntfy->handle);
if (dev->chipset < 0x40)
oclass = NV30_SURFACE_SWZ_CLASS;
else
oclass = NV40_SURFACE_SWZ_CLASS;
ret = nouveau_object_new(screen->base.channel, 0xbeef5201, oclass,
NULL, 0, &screen->swzsurf);
if (ret)
FAIL_SCREEN_INIT("error allocating swizzled surface object: %d\n", ret);
BEGIN_NV04(push, NV01_SUBC(SSWZ, OBJECT), 1);
PUSH_DATA (push, screen->swzsurf->handle);
BEGIN_NV04(push, NV04_SSWZ(DMA_NOTIFY), 1);
PUSH_DATA (push, screen->ntfy->handle);
if (dev->chipset < 0x40)
oclass = NV30_SIFM_CLASS;
else
oclass = NV40_SIFM_CLASS;
ret = nouveau_object_new(screen->base.channel, 0xbeef7701, oclass,
NULL, 0, &screen->sifm);
if (ret)
FAIL_SCREEN_INIT("error allocating scaled image object: %d\n", ret);
BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1);
PUSH_DATA (push, screen->sifm->handle);
BEGIN_NV04(push, NV03_SIFM(DMA_NOTIFY), 1);
PUSH_DATA (push, screen->ntfy->handle);
BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1);
PUSH_DATA (push, NV05_SIFM_COLOR_CONVERSION_TRUNCATE);
nouveau_pushbuf_kick(push, push->channel);
nouveau_fence_new(&screen->base, &screen->base.fence.current, FALSE);
return pscreen;
}
+51
View File
@@ -0,0 +1,51 @@
#ifndef __NV30_SCREEN_H__
#define __NV30_SCREEN_H__
#include <stdio.h>
#define NOUVEAU_ERR(fmt, args...) \
fprintf(stderr, "%s:%d - "fmt, __FUNCTION__, __LINE__, ##args);
#include "util/u_double_list.h"
#include "nouveau/nouveau_screen.h"
#include "nouveau/nouveau_fence.h"
#include "nouveau/nouveau_heap.h"
#include "nv30_winsys.h"
#include "nv30_resource.h"
struct nv30_context;
struct nv30_screen {
struct nouveau_screen base;
struct nv30_context *cur_ctx;
struct nouveau_bo *notify;
struct nouveau_object *ntfy;
struct nouveau_object *fence;
struct nouveau_object *query;
struct nouveau_heap *query_heap;
struct list_head queries;
struct nouveau_object *null;
struct nouveau_object *eng3d;
struct nouveau_object *m2mf;
struct nouveau_object *surf2d;
struct nouveau_object *swzsurf;
struct nouveau_object *sifm;
/*XXX: nvfx state */
struct nouveau_heap *vp_exec_heap;
struct nouveau_heap *vp_data_heap;
};
static INLINE struct nv30_screen *
nv30_screen(struct pipe_screen *pscreen)
{
return (struct nv30_screen *)pscreen;
}
#endif
+447
View File
@@ -0,0 +1,447 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_inlines.h"
#include "nouveau/nouveau_gldefs.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_winsys.h"
#define NV40_3D_MRT_BLEND_ENABLE 0x0000036c
static void *
nv30_blend_state_create(struct pipe_context *pipe,
const struct pipe_blend_state *cso)
{
struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
struct nv30_blend_stateobj *so;
uint32_t blend[2], cmask[2];
int i;
so = CALLOC_STRUCT(nv30_blend_stateobj);
if (!so)
return NULL;
so->pipe = *cso;
if (cso->logicop_enable) {
SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 2);
SB_DATA (so, 1);
SB_DATA (so, nvgl_logicop_func(cso->logicop_func));
} else {
SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 1);
SB_DATA (so, 0);
}
SB_MTHD30(so, DITHER_ENABLE, 1);
SB_DATA (so, cso->dither);
blend[0] = cso->rt[0].blend_enable;
cmask[0] = !!(cso->rt[0].colormask & PIPE_MASK_A) << 24 |
!!(cso->rt[0].colormask & PIPE_MASK_R) << 16 |
!!(cso->rt[0].colormask & PIPE_MASK_G) << 8 |
!!(cso->rt[0].colormask & PIPE_MASK_B);
if (cso->independent_blend_enable) {
blend[1] = 0;
cmask[1] = 0;
for (i = 1; i < 4; i++) {
blend[1] |= cso->rt[i].blend_enable << i;
cmask[1] |= !!(cso->rt[i].colormask & PIPE_MASK_A) << (0 + (i * 4)) |
!!(cso->rt[i].colormask & PIPE_MASK_R) << (1 + (i * 4)) |
!!(cso->rt[i].colormask & PIPE_MASK_G) << (2 + (i * 4)) |
!!(cso->rt[i].colormask & PIPE_MASK_B) << (3 + (i * 4));
}
} else {
blend[1] = 0x0000000e * (blend[0] & 0x00000001);
cmask[1] = 0x00001110 * !!(cmask[0] & 0x01000000);
cmask[1] |= 0x00002220 * !!(cmask[0] & 0x00010000);
cmask[1] |= 0x00004440 * !!(cmask[0] & 0x00000100);
cmask[1] |= 0x00008880 * !!(cmask[0] & 0x00000001);
}
if (eng3d->oclass >= NV40_3D_CLASS) {
SB_MTHD40(so, MRT_BLEND_ENABLE, 2);
SB_DATA (so, blend[1]);
SB_DATA (so, cmask[1]);
}
if (blend[0] || blend[1]) {
SB_MTHD30(so, BLEND_FUNC_ENABLE, 3);
SB_DATA (so, blend[0]);
SB_DATA (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) |
nvgl_blend_func(cso->rt[0].rgb_src_factor));
SB_DATA (so, (nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16) |
nvgl_blend_func(cso->rt[0].rgb_dst_factor));
if (eng3d->oclass < NV40_3D_CLASS) {
SB_MTHD30(so, BLEND_EQUATION, 1);
SB_DATA (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
} else {
SB_MTHD40(so, BLEND_EQUATION, 1);
SB_DATA (so, (nvgl_blend_eqn(cso->rt[0].alpha_func) << 16) |
nvgl_blend_eqn(cso->rt[0].rgb_func));
}
} else {
SB_MTHD30(so, BLEND_FUNC_ENABLE, 1);
SB_DATA (so, blend[0]);
}
SB_MTHD30(so, COLOR_MASK, 1);
SB_DATA (so, cmask[0]);
return so;
}
static void
nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->blend = hwcso;
nv30->dirty |= NV30_NEW_BLEND;
}
static void
nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso)
{
FREE(hwcso);
}
static void *
nv30_rasterizer_state_create(struct pipe_context *pipe,
const struct pipe_rasterizer_state *cso)
{
struct nv30_rasterizer_stateobj *so;
so = CALLOC_STRUCT(nv30_rasterizer_stateobj);
if (!so)
return NULL;
so->pipe = *cso;
SB_MTHD30(so, SHADE_MODEL, 1);
SB_DATA (so, cso->flatshade ? NV30_3D_SHADE_MODEL_FLAT :
NV30_3D_SHADE_MODEL_SMOOTH);
SB_MTHD30(so, POLYGON_MODE_FRONT, 6);
SB_DATA (so, nvgl_polygon_mode(cso->fill_front));
SB_DATA (so, nvgl_polygon_mode(cso->fill_back));
if (cso->cull_face == PIPE_FACE_FRONT_AND_BACK)
SB_DATA (so, NV30_3D_CULL_FACE_FRONT_AND_BACK);
else
if (cso->cull_face == PIPE_FACE_FRONT)
SB_DATA (so, NV30_3D_CULL_FACE_FRONT);
else
SB_DATA (so, NV30_3D_CULL_FACE_BACK);
SB_DATA (so, cso->front_ccw ? NV30_3D_FRONT_FACE_CCW :
NV30_3D_FRONT_FACE_CW);
SB_DATA (so, cso->poly_smooth);
SB_DATA (so, cso->cull_face != PIPE_FACE_NONE);
SB_MTHD30(so, POLYGON_OFFSET_POINT_ENABLE, 3);
SB_DATA (so, cso->offset_point);
SB_DATA (so, cso->offset_line);
SB_DATA (so, cso->offset_tri);
if (cso->offset_point || cso->offset_line || cso->offset_tri) {
SB_MTHD30(so, POLYGON_OFFSET_FACTOR, 2);
SB_DATA (so, fui(cso->offset_scale));
SB_DATA (so, fui(cso->offset_units * 2.0));
}
SB_MTHD30(so, LINE_WIDTH, 2);
SB_DATA (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
SB_DATA (so, cso->line_smooth);
SB_MTHD30(so, LINE_STIPPLE_ENABLE, 2);
SB_DATA (so, cso->line_stipple_enable);
SB_DATA (so, (cso->line_stipple_pattern << 16) |
cso->line_stipple_factor);
SB_MTHD30(so, VERTEX_TWO_SIDE_ENABLE, 1);
SB_DATA (so, cso->light_twoside);
SB_MTHD30(so, POLYGON_STIPPLE_ENABLE, 1);
SB_DATA (so, cso->poly_stipple_enable);
SB_MTHD30(so, POINT_SIZE, 1);
SB_DATA (so, fui(cso->point_size));
SB_MTHD30(so, FLATSHADE_FIRST, 1);
SB_DATA (so, cso->flatshade_first);
SB_MTHD30(so, DEPTH_CONTROL, 1);
SB_DATA (so, cso->depth_clip ? 0x00000001 : 0x00000010);
return so;
}
static void
nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->rast = hwcso;
nv30->dirty |= NV30_NEW_RASTERIZER;
}
static void
nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
{
FREE(hwcso);
}
static void *
nv30_zsa_state_create(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *cso)
{
struct nv30_zsa_stateobj *so;
so = CALLOC_STRUCT(nv30_zsa_stateobj);
if (!so)
return NULL;
so->pipe = *cso;
SB_MTHD30(so, DEPTH_FUNC, 3);
SB_DATA (so, nvgl_comparison_op(cso->depth.func));
SB_DATA (so, cso->depth.writemask);
SB_DATA (so, cso->depth.enabled);
if (cso->stencil[0].enabled) {
SB_MTHD30(so, STENCIL_ENABLE(0), 3);
SB_DATA (so, 1);
SB_DATA (so, cso->stencil[0].writemask);
SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func));
SB_MTHD30(so, STENCIL_FUNC_MASK(0), 4);
SB_DATA (so, cso->stencil[0].valuemask);
SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op));
SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
} else {
SB_MTHD30(so, STENCIL_ENABLE(0), 2);
SB_DATA (so, 0);
SB_DATA (so, 0x000000ff);
}
if (cso->stencil[1].enabled) {
SB_MTHD30(so, STENCIL_ENABLE(1), 3);
SB_DATA (so, 1);
SB_DATA (so, cso->stencil[1].writemask);
SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func));
SB_MTHD30(so, STENCIL_FUNC_MASK(1), 4);
SB_DATA (so, cso->stencil[1].valuemask);
SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op));
SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
} else {
SB_MTHD30(so, STENCIL_ENABLE(1), 1);
SB_DATA (so, 0);
}
SB_MTHD30(so, ALPHA_FUNC_ENABLE, 3);
SB_DATA (so, cso->alpha.enabled ? 1 : 0);
SB_DATA (so, nvgl_comparison_op(cso->alpha.func));
SB_DATA (so, float_to_ubyte(cso->alpha.ref_value));
return so;
}
static void
nv30_zsa_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->zsa = hwcso;
nv30->dirty |= NV30_NEW_ZSA;
}
static void
nv30_zsa_state_delete(struct pipe_context *pipe, void *hwcso)
{
FREE(hwcso);
}
static void
nv30_set_blend_color(struct pipe_context *pipe,
const struct pipe_blend_color *bcol)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->blend_colour = *bcol;
nv30->dirty |= NV30_NEW_BLEND_COLOUR;
}
static void
nv30_set_stencil_ref(struct pipe_context *pipe,
const struct pipe_stencil_ref *sr)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->stencil_ref = *sr;
nv30->dirty |= NV30_NEW_STENCIL_REF;
}
static void
nv30_set_clip_state(struct pipe_context *pipe,
const struct pipe_clip_state *clip)
{
struct nv30_context *nv30 = nv30_context(pipe);
memcpy(nv30->clip.ucp, clip->ucp, sizeof(clip->ucp));
nv30->dirty |= NV30_NEW_CLIP;
}
static void
nv30_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->sample_mask = sample_mask;
nv30->dirty |= NV30_NEW_SAMPLE_MASK;
}
static void
nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
struct pipe_resource *buf)
{
struct nv30_context *nv30 = nv30_context(pipe);
unsigned size;
size = 0;
if (buf)
size = buf->width0 / (4 * sizeof(float));
if (shader == PIPE_SHADER_VERTEX) {
pipe_resource_reference(&nv30->vertprog.constbuf, buf);
nv30->vertprog.constbuf_nr = size;
nv30->dirty |= NV30_NEW_VERTCONST;
} else
if (shader == PIPE_SHADER_FRAGMENT) {
pipe_resource_reference(&nv30->fragprog.constbuf, buf);
nv30->fragprog.constbuf_nr = size;
nv30->dirty |= NV30_NEW_FRAGCONST;
}
}
static void
nv30_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct nv30_context *nv30 = nv30_context(pipe);
nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB);
nv30->framebuffer = *fb;
nv30->dirty |= NV30_NEW_FRAMEBUFFER;
}
static void
nv30_set_polygon_stipple(struct pipe_context *pipe,
const struct pipe_poly_stipple *stipple)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->stipple = *stipple;
nv30->dirty |= NV30_NEW_STIPPLE;
}
static void
nv30_set_scissor_state(struct pipe_context *pipe,
const struct pipe_scissor_state *scissor)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->scissor = *scissor;
nv30->dirty |= NV30_NEW_SCISSOR;
}
static void
nv30_set_viewport_state(struct pipe_context *pipe,
const struct pipe_viewport_state *vpt)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->viewport = *vpt;
nv30->dirty |= NV30_NEW_VIEWPORT;
}
static void
nv30_set_vertex_buffers(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_buffer *vb)
{
struct nv30_context *nv30 = nv30_context(pipe);
unsigned i;
nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
for (i = 0; i < count; ++i)
pipe_resource_reference(&nv30->vtxbuf[i].buffer, vb[i].buffer);
for (; i < nv30->num_vtxbufs; ++i)
pipe_resource_reference(&nv30->vtxbuf[i].buffer, NULL);
memcpy(nv30->vtxbuf, vb, sizeof(*vb) * count);
nv30->num_vtxbufs = count;
nv30->dirty |= NV30_NEW_ARRAYS;
}
static void
nv30_set_index_buffer(struct pipe_context *pipe,
const struct pipe_index_buffer *ib)
{
struct nv30_context *nv30 = nv30_context(pipe);
if (ib) {
pipe_resource_reference(&nv30->idxbuf.buffer, ib->buffer);
memcpy(&nv30->idxbuf, ib, sizeof(nv30->idxbuf));
} else {
pipe_resource_reference(&nv30->idxbuf.buffer, NULL);
}
}
void
nv30_state_init(struct pipe_context *pipe)
{
pipe->create_blend_state = nv30_blend_state_create;
pipe->bind_blend_state = nv30_blend_state_bind;
pipe->delete_blend_state = nv30_blend_state_delete;
pipe->create_rasterizer_state = nv30_rasterizer_state_create;
pipe->bind_rasterizer_state = nv30_rasterizer_state_bind;
pipe->delete_rasterizer_state = nv30_rasterizer_state_delete;
pipe->create_depth_stencil_alpha_state = nv30_zsa_state_create;
pipe->bind_depth_stencil_alpha_state = nv30_zsa_state_bind;
pipe->delete_depth_stencil_alpha_state = nv30_zsa_state_delete;
pipe->set_blend_color = nv30_set_blend_color;
pipe->set_stencil_ref = nv30_set_stencil_ref;
pipe->set_clip_state = nv30_set_clip_state;
pipe->set_sample_mask = nv30_set_sample_mask;
pipe->set_constant_buffer = nv30_set_constant_buffer;
pipe->set_framebuffer_state = nv30_set_framebuffer_state;
pipe->set_polygon_stipple = nv30_set_polygon_stipple;
pipe->set_scissor_state = nv30_set_scissor_state;
pipe->set_viewport_state = nv30_set_viewport_state;
pipe->set_vertex_buffers = nv30_set_vertex_buffers;
pipe->set_index_buffer = nv30_set_index_buffer;
pipe->redefine_user_buffer = u_default_redefine_user_buffer;
}
+144
View File
@@ -0,0 +1,144 @@
#ifndef __NV30_STATE_H__
#define __NV30_STATE_H__
#include "pipe/p_state.h"
#include "tgsi/tgsi_scan.h"
#include "util/u_dynarray.h"
#define NV30_QUERY_ZCULL_0 (PIPE_QUERY_TYPES + 0)
#define NV30_QUERY_ZCULL_1 (PIPE_QUERY_TYPES + 1)
#define NV30_QUERY_ZCULL_2 (PIPE_QUERY_TYPES + 2)
#define NV30_QUERY_ZCULL_3 (PIPE_QUERY_TYPES + 3)
#define SB_DATA(so, u) (so)->data[(so)->size++] = (u)
#define SB_MTHD30(so, mthd, size) \
SB_DATA((so), ((size) << 18) | (7 << 13) | NV30_3D_##mthd)
#define SB_MTHD40(so, mthd, size) \
SB_DATA((so), ((size) << 18) | (7 << 13) | NV40_3D_##mthd)
struct nv30_blend_stateobj {
struct pipe_blend_state pipe;
unsigned data[16];
unsigned size;
};
struct nv30_rasterizer_stateobj {
struct pipe_rasterizer_state pipe;
unsigned data[32];
unsigned size;
};
struct nv30_zsa_stateobj {
struct pipe_depth_stencil_alpha_state pipe;
unsigned data[32];
unsigned size;
};
struct nv30_sampler_state {
struct pipe_sampler_state pipe;
unsigned fmt;
unsigned wrap;
unsigned en;
unsigned filt;
unsigned bcol;
/* 4.8 */
unsigned min_lod;
unsigned max_lod;
};
struct nv30_sampler_view {
struct pipe_sampler_view pipe;
unsigned fmt;
unsigned swz;
unsigned filt;
unsigned filt_mask;
unsigned wrap;
unsigned wrap_mask;
unsigned npot_size0;
unsigned npot_size1;
/* 4.8 */
unsigned base_lod;
unsigned high_lod;
};
struct nv30_shader_reloc {
unsigned location;
unsigned target;
};
struct nv30_vertprog_exec {
uint32_t data[4];
};
struct nv30_vertprog_data {
int index; /* immediates == -1 */
float value[4];
};
struct nv30_vertprog {
struct pipe_shader_state pipe;
struct tgsi_shader_info info;
struct draw_vertex_shader *draw;
boolean translated;
unsigned enabled_ucps;
uint16_t texcoord[10];
struct util_dynarray branch_relocs;
struct nv30_vertprog_exec *insns;
unsigned nr_insns;
struct util_dynarray const_relocs;
struct nv30_vertprog_data *consts;
unsigned nr_consts;
struct nouveau_heap *exec;
struct nouveau_heap *data;
uint32_t ir;
uint32_t or;
void *nvfx;
};
struct nv30_fragprog_data {
unsigned offset;
unsigned index;
};
struct nv30_fragprog {
struct pipe_shader_state pipe;
struct tgsi_shader_info info;
struct draw_fragment_shader *draw;
boolean translated;
uint32_t *insn;
unsigned insn_len;
uint16_t texcoord[10];
struct nv30_fragprog_data *consts;
unsigned nr_consts;
struct pipe_resource *buffer;
uint32_t vp_or; /* appended to VP_RESULT_EN */
uint32_t fp_control;
uint32_t point_sprite_control;
uint32_t coord_conventions;
uint32_t samplers;
uint32_t rt_enable;
};
struct nv30_vertex_element {
unsigned state;
};
struct nv30_vertex_stateobj {
struct pipe_vertex_element pipe[PIPE_MAX_ATTRIBS];
struct translate *translate;
bool need_conversion;
unsigned num_elements;
unsigned vtx_size;
unsigned vtx_per_packet_max;
struct nv30_vertex_element element[];
};
#endif
@@ -0,0 +1,535 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_half.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_format.h"
static void
nv30_validate_fb(struct nv30_context *nv30)
{
struct pipe_screen *pscreen = &nv30->screen->base.base;
struct pipe_framebuffer_state *fb = &nv30->framebuffer;
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_object *eng3d = nv30->screen->eng3d;
uint32_t rt_format;
int h = fb->height;
int w = fb->width;
int x = 0;
int y = 0;
nv30->state.rt_enable = (NV30_3D_RT_ENABLE_COLOR0 << fb->nr_cbufs) - 1;
if (nv30->state.rt_enable > 1)
nv30->state.rt_enable |= NV30_3D_RT_ENABLE_MRT;
rt_format = 0;
if (fb->nr_cbufs > 0) {
struct nv30_miptree *mt = nv30_miptree(fb->cbufs[0]->texture);
rt_format |= nv30_format(pscreen, fb->cbufs[0]->format)->hw;
rt_format |= mt->ms_mode;
if (mt->swizzled)
rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
else
rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
} else {
if (fb->zsbuf && util_format_get_blocksize(fb->zsbuf->format) > 2)
rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
else
rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
}
if (fb->zsbuf) {
rt_format |= nv30_format(pscreen, fb->zsbuf->format)->hw;
if (nv30_miptree(fb->zsbuf->texture)->swizzled)
rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
else
rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
} else {
if (fb->nr_cbufs && util_format_get_blocksize(fb->cbufs[0]->format) > 2)
rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
else
rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
}
/* 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 aaddress. For these two important square formats
* we can hack around this limitation by adjusting the viewport origin
*/
if (nv30->state.rt_enable) {
int off = nv30_surface(fb->cbufs[0])->offset & 63;
if (off) {
x += off / (util_format_get_blocksize(fb->cbufs[0]->format) * 2);
w = 16;
h = 2;
}
}
if (rt_format & NV30_3D_RT_FORMAT_TYPE_SWIZZLED) {
rt_format |= util_logbase2(w) << 16;
rt_format |= util_logbase2(h) << 24;
}
if (!PUSH_SPACE(push, 64))
return;
PUSH_RESET(push, BUFCTX_FB);
BEGIN_NV04(push, SUBC_3D(0x1da4), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
PUSH_DATA (push, w << 16);
PUSH_DATA (push, h << 16);
PUSH_DATA (push, rt_format);
BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
PUSH_DATA (push, w << 16);
PUSH_DATA (push, h << 16);
BEGIN_NV04(push, NV30_3D(VIEWPORT_TX_ORIGIN), 1);
PUSH_DATA (push, (y << 16) | x);
if ((nv30->state.rt_enable & NV30_3D_RT_ENABLE_COLOR0) || fb->zsbuf) {
struct nv30_surface *rsf = nv30_surface(fb->cbufs[0]);
struct nv30_surface *zsf = nv30_surface(fb->zsbuf);
struct nouveau_bo *rbo, *zbo;
if (!rsf) rsf = zsf;
else if (!zsf) zsf = rsf;
rbo = nv30_miptree(rsf->base.texture)->base.bo;
zbo = nv30_miptree(zsf->base.texture)->base.bo;
if (eng3d->oclass >= NV40_3D_CLASS) {
BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
PUSH_DATA (push, zsf->pitch);
BEGIN_NV04(push, NV40_3D(COLOR0_PITCH), 3);
PUSH_DATA (push, rsf->pitch);
} else {
BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 3);
PUSH_DATA (push, (zsf->pitch << 16) | rsf->pitch);
}
PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), BUFCTX_FB, rbo, rsf->offset & ~63,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
PUSH_MTHDl(push, NV30_3D(ZETA_OFFSET), BUFCTX_FB, zbo, zsf->offset & ~63,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
}
if (nv30->state.rt_enable & NV30_3D_RT_ENABLE_COLOR1) {
struct nv30_surface *sf = nv30_surface(fb->cbufs[1]);
struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
BEGIN_NV04(push, NV30_3D(COLOR1_OFFSET), 2);
PUSH_MTHDl(push, NV30_3D(COLOR1_OFFSET), BUFCTX_FB, bo, sf->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
PUSH_DATA (push, sf->pitch);
}
if (nv30->state.rt_enable & NV40_3D_RT_ENABLE_COLOR2) {
struct nv30_surface *sf = nv30_surface(fb->cbufs[2]);
struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
BEGIN_NV04(push, NV40_3D(COLOR2_OFFSET), 1);
PUSH_MTHDl(push, NV40_3D(COLOR2_OFFSET), BUFCTX_FB, bo, sf->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
BEGIN_NV04(push, NV40_3D(COLOR2_PITCH), 1);
PUSH_DATA (push, sf->pitch);
}
if (nv30->state.rt_enable & NV40_3D_RT_ENABLE_COLOR3) {
struct nv30_surface *sf = nv30_surface(fb->cbufs[3]);
struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
BEGIN_NV04(push, NV40_3D(COLOR3_OFFSET), 1);
PUSH_MTHDl(push, NV40_3D(COLOR3_OFFSET), BUFCTX_FB, bo, sf->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
BEGIN_NV04(push, NV40_3D(COLOR3_PITCH), 1);
PUSH_DATA (push, sf->pitch);
}
}
static void
nv30_validate_blend_colour(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
float *rgba = nv30->blend_colour.color;
if (nv30->framebuffer.nr_cbufs) {
switch (nv30->framebuffer.cbufs[0]->format) {
case PIPE_FORMAT_R16G16B16A16_FLOAT:
case PIPE_FORMAT_R32G32B32A32_FLOAT:
BEGIN_NV04(push, NV30_3D(BLEND_COLOR), 1);
PUSH_DATA (push, (util_float_to_half(rgba[0]) << 0) |
(util_float_to_half(rgba[1]) << 16));
BEGIN_NV04(push, SUBC_3D(0x037c), 1);
PUSH_DATA (push, (util_float_to_half(rgba[2]) << 0) |
(util_float_to_half(rgba[3]) << 16));
break;
default:
break;
}
}
BEGIN_NV04(push, NV30_3D(BLEND_COLOR), 1);
PUSH_DATA (push, (float_to_ubyte(rgba[3]) << 24) |
(float_to_ubyte(rgba[0]) << 16) |
(float_to_ubyte(rgba[1]) << 8) |
(float_to_ubyte(rgba[2]) << 0));
}
static void
nv30_validate_stencil_ref(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
BEGIN_NV04(push, NV30_3D(STENCIL_FUNC_REF(0)), 1);
PUSH_DATA (push, nv30->stencil_ref.ref_value[0]);
BEGIN_NV04(push, NV30_3D(STENCIL_FUNC_REF(1)), 1);
PUSH_DATA (push, nv30->stencil_ref.ref_value[1]);
}
static void
nv30_validate_stipple(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
PUSH_DATAp(push, nv30->stipple.stipple, 32);
}
static void
nv30_validate_scissor(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct pipe_scissor_state *s = &nv30->scissor;
if (!(nv30->dirty & NV30_NEW_SCISSOR) &&
nv30->rast->pipe.scissor != nv30->state.scissor_off)
return;
nv30->state.scissor_off = !nv30->rast->pipe.scissor;
BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
if (nv30->rast->pipe.scissor) {
PUSH_DATA (push, ((s->maxx - s->minx) << 16) | s->minx);
PUSH_DATA (push, ((s->maxy - s->miny) << 16) | s->miny);
} else {
PUSH_DATA (push, 0x10000000);
PUSH_DATA (push, 0x10000000);
}
}
static void
nv30_validate_viewport(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct pipe_viewport_state *vp = &nv30->viewport;
BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
PUSH_DATAf(push, vp->translate[0]);
PUSH_DATAf(push, vp->translate[1]);
PUSH_DATAf(push, vp->translate[2]);
PUSH_DATAf(push, vp->translate[3]);
PUSH_DATAf(push, vp->scale[0]);
PUSH_DATAf(push, vp->scale[1]);
PUSH_DATAf(push, vp->scale[2]);
PUSH_DATAf(push, vp->scale[3]);
BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
PUSH_DATAf(push, vp->translate[2] - fabsf(vp->scale[2]));
PUSH_DATAf(push, vp->translate[2] + fabsf(vp->scale[2]));
}
static void
nv30_validate_clip(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
unsigned i;
uint32_t clpd_enable = 0;
for (i = 0; i < 6; i++) {
if (nv30->rast->pipe.clip_plane_enable & (1 << i)) {
if (nv30->dirty & NV30_NEW_CLIP) {
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 5);
PUSH_DATA (push, i);
PUSH_DATAp(push, nv30->clip.ucp[i], 4);
}
clpd_enable |= 1 << (1 + 4*i);
}
}
BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1);
PUSH_DATA (push, clpd_enable);
}
static void
nv30_validate_blend(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
PUSH_SPACE(push, nv30->blend->size);
PUSH_DATAp(push, nv30->blend->data, nv30->blend->size);
}
static void
nv30_validate_zsa(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
PUSH_SPACE(push, nv30->zsa->size);
PUSH_DATAp(push, nv30->zsa->data, nv30->zsa->size);
}
static void
nv30_validate_rasterizer(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
PUSH_SPACE(push, nv30->rast->size);
PUSH_DATAp(push, nv30->rast->data, nv30->rast->size);
}
static void
nv30_validate_multisample(struct nv30_context *nv30)
{
struct pipe_rasterizer_state *rasterizer = &nv30->rast->pipe;
struct pipe_blend_state *blend = &nv30->blend->pipe;
struct nouveau_pushbuf *push = nv30->base.pushbuf;
uint32_t ctrl = nv30->sample_mask << 16;
if (blend->alpha_to_one)
ctrl |= 0x00000100;
if (blend->alpha_to_coverage)
ctrl |= 0x00000010;
if (rasterizer->multisample)
ctrl |= 0x00000001;
BEGIN_NV04(push, NV30_3D(MULTISAMPLE_CONTROL), 1);
PUSH_DATA (push, ctrl);
}
static void
nv30_validate_fragment(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nv30_fragprog *fp = nv30->fragprog.program;
BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
PUSH_DATA (push, nv30->state.rt_enable & ~fp->rt_enable);
BEGIN_NV04(push, NV30_3D(COORD_CONVENTIONS), 1);
PUSH_DATA (push, fp->coord_conventions | nv30->framebuffer.height);
}
static void
nv30_validate_point_coord(struct nv30_context *nv30)
{
struct pipe_rasterizer_state *rasterizer = &nv30->rast->pipe;
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nv30_fragprog *fp = nv30->fragprog.program;
uint32_t hw = 0x00000000;
if (rasterizer) {
hw |= (nv30->rast->pipe.sprite_coord_enable & 0xff) << 8;
if (fp)
hw |= fp->point_sprite_control;
if (rasterizer->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT) {
if (hw)
nv30->draw_flags |= NV30_NEW_RASTERIZER;
} else
if (rasterizer->point_quad_rasterization) {
hw |= NV30_3D_POINT_SPRITE_ENABLE;
}
}
BEGIN_NV04(push, NV30_3D(POINT_SPRITE), 1);
PUSH_DATA (push, hw);
}
struct state_validate {
void (*func)(struct nv30_context *);
uint32_t mask;
};
static struct state_validate hwtnl_validate_list[] = {
{ nv30_validate_fb, NV30_NEW_FRAMEBUFFER },
{ nv30_validate_blend, NV30_NEW_BLEND },
{ nv30_validate_zsa, NV30_NEW_ZSA },
{ nv30_validate_rasterizer, NV30_NEW_RASTERIZER },
{ nv30_validate_multisample, NV30_NEW_SAMPLE_MASK | NV30_NEW_BLEND |
NV30_NEW_RASTERIZER },
{ nv30_validate_blend_colour, NV30_NEW_BLEND_COLOUR |
NV30_NEW_FRAMEBUFFER },
{ nv30_validate_stencil_ref, NV30_NEW_STENCIL_REF },
{ nv30_validate_stipple, NV30_NEW_STIPPLE },
{ nv30_validate_scissor, NV30_NEW_SCISSOR | NV30_NEW_RASTERIZER },
{ nv30_validate_viewport, NV30_NEW_VIEWPORT },
{ nv30_validate_clip, NV30_NEW_CLIP },
{ nv30_fragprog_validate, NV30_NEW_FRAGPROG | NV30_NEW_FRAGCONST },
{ nv30_vertprog_validate, NV30_NEW_VERTPROG | NV30_NEW_VERTCONST |
NV30_NEW_FRAGPROG | NV30_NEW_RASTERIZER },
{ nv30_validate_fragment, NV30_NEW_FRAMEBUFFER | NV30_NEW_FRAGPROG },
{ nv30_validate_point_coord, NV30_NEW_RASTERIZER | NV30_NEW_FRAGPROG },
{ nv30_fragtex_validate, NV30_NEW_FRAGTEX },
{ nv40_verttex_validate, NV30_NEW_VERTTEX },
{ nv30_vbo_validate, NV30_NEW_VERTEX | NV30_NEW_ARRAYS },
{}
};
#define NV30_SWTNL_MASK (NV30_NEW_VIEWPORT | \
NV30_NEW_CLIP | \
NV30_NEW_VERTPROG | \
NV30_NEW_VERTCONST | \
NV30_NEW_VERTTEX | \
NV30_NEW_VERTEX | \
NV30_NEW_ARRAYS)
static struct state_validate swtnl_validate_list[] = {
{ nv30_validate_fb, NV30_NEW_FRAMEBUFFER },
{ nv30_validate_blend, NV30_NEW_BLEND },
{ nv30_validate_zsa, NV30_NEW_ZSA },
{ nv30_validate_rasterizer, NV30_NEW_RASTERIZER },
{ nv30_validate_multisample, NV30_NEW_SAMPLE_MASK | NV30_NEW_BLEND |
NV30_NEW_RASTERIZER },
{ nv30_validate_blend_colour, NV30_NEW_BLEND_COLOUR |
NV30_NEW_FRAMEBUFFER },
{ nv30_validate_stencil_ref, NV30_NEW_STENCIL_REF },
{ nv30_validate_stipple, NV30_NEW_STIPPLE },
{ nv30_validate_scissor, NV30_NEW_SCISSOR | NV30_NEW_RASTERIZER },
{ nv30_fragprog_validate, NV30_NEW_FRAGPROG | NV30_NEW_FRAGCONST },
{ nv30_validate_fragment, NV30_NEW_FRAMEBUFFER | NV30_NEW_FRAGPROG },
{ nv30_fragtex_validate, NV30_NEW_FRAGTEX },
{}
};
static void
nv30_state_context_switch(struct nv30_context *nv30)
{
struct nv30_context *prev = nv30->screen->cur_ctx;
if (prev)
nv30->state = prev->state;
nv30->dirty = NV30_NEW_ALL;
if (!nv30->vertex)
nv30->dirty &= ~(NV30_NEW_VERTEX | NV30_NEW_ARRAYS);
if (!nv30->vertprog.program)
nv30->dirty &= ~NV30_NEW_VERTPROG;
if (!nv30->fragprog.program)
nv30->dirty &= ~NV30_NEW_FRAGPROG;
if (!nv30->blend)
nv30->dirty &= ~NV30_NEW_BLEND;
if (!nv30->rast)
nv30->dirty &= ~NV30_NEW_RASTERIZER;
if (!nv30->zsa)
nv30->dirty &= ~NV30_NEW_ZSA;
nv30->screen->cur_ctx = nv30;
nv30->base.pushbuf->user_priv = &nv30->bufctx;
}
boolean
nv30_state_validate(struct nv30_context *nv30, boolean hwtnl)
{
struct nouveau_screen *screen = &nv30->screen->base;
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_bufctx *bctx = nv30->bufctx;
struct nouveau_bufref *bref;
struct state_validate *validate;
if (nv30->screen->cur_ctx != nv30)
nv30_state_context_switch(nv30);
if (hwtnl) {
nv30->draw_dirty |= nv30->dirty;
if (nv30->draw_flags) {
nv30->draw_flags &= ~nv30->dirty;
if (!nv30->draw_flags)
nv30->dirty |= NV30_SWTNL_MASK;
}
}
if (!nv30->draw_flags)
validate = hwtnl_validate_list;
else
validate = swtnl_validate_list;
if (nv30->dirty) {
while (validate->func) {
if (nv30->dirty & validate->mask)
validate->func(nv30);
validate++;
}
nv30->dirty = 0;
}
nouveau_pushbuf_bufctx(push, bctx);
if (nouveau_pushbuf_validate(push)) {
nouveau_pushbuf_bufctx(push, NULL);
return FALSE;
}
/*XXX*/
BEGIN_NV04(push, NV30_3D(VTX_CACHE_INVALIDATE_1710), 1);
PUSH_DATA (push, 0);
if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) {
BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
PUSH_DATA (push, 2);
BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
PUSH_DATA (push, 1);
BEGIN_NV04(push, NV30_3D(R1718), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(R1718), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(R1718), 1);
PUSH_DATA (push, 0);
}
LIST_FOR_EACH_ENTRY(bref, &bctx->current, thead) {
struct nv04_resource *res = bref->priv;
if (res && res->mm) {
nouveau_fence_ref(screen->fence.current, &res->fence);
if (bref->flags & NOUVEAU_BO_RD)
res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
if (bref->flags & NOUVEAU_BO_WR) {
nouveau_fence_ref(screen->fence.current, &res->fence_wr);
res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
}
}
}
return TRUE;
}
void
nv30_state_release(struct nv30_context *nv30)
{
nouveau_pushbuf_bufctx(nv30->base.pushbuf, NULL);
}
+306
View File
@@ -0,0 +1,306 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_format.h"
#define NV30_3D_TEX_WRAP_S_MIRROR_REPEAT NV30_3D_TEX_WRAP_S_MIRRORED_REPEAT
#define NV30_WRAP(n) \
case PIPE_TEX_WRAP_##n: ret = NV30_3D_TEX_WRAP_S_##n; break
#define NV40_WRAP(n) \
case PIPE_TEX_WRAP_##n: ret = NV40_3D_TEX_WRAP_S_##n; break
static INLINE unsigned
wrap_mode(unsigned pipe)
{
unsigned ret = NV30_3D_TEX_WRAP_S_REPEAT;
switch (pipe) {
NV30_WRAP(REPEAT);
NV30_WRAP(MIRROR_REPEAT);
NV30_WRAP(CLAMP_TO_EDGE);
NV30_WRAP(CLAMP_TO_BORDER);
NV30_WRAP(CLAMP);
NV40_WRAP(MIRROR_CLAMP_TO_EDGE);
NV40_WRAP(MIRROR_CLAMP_TO_BORDER);
NV40_WRAP(MIRROR_CLAMP);
default:
break;
}
return ret >> NV30_3D_TEX_WRAP_S__SHIFT;
}
static INLINE unsigned
filter_mode(const struct pipe_sampler_state *cso)
{
unsigned filter;
switch (cso->mag_img_filter) {
case PIPE_TEX_FILTER_LINEAR:
filter = NV30_3D_TEX_FILTER_MAG_LINEAR;
break;
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;
default:
filter |= NV30_3D_TEX_FILTER_MIN_LINEAR;
break;
}
break;
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;
default:
filter |= NV30_3D_TEX_FILTER_MIN_NEAREST;
break;
}
break;
}
return filter;
}
static INLINE unsigned
compare_mode(const struct pipe_sampler_state *cso)
{
if (cso->compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE)
return 0;
switch (cso->compare_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:
return 0;
}
}
static void *
nv30_sampler_state_create(struct pipe_context *pipe,
const struct pipe_sampler_state *cso)
{
struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
struct nv30_sampler_state *so;
const float max_lod = 15.0 + (255.0 / 256.0);
so = MALLOC_STRUCT(nv30_sampler_state);
if (!so)
return NULL;
so->pipe = *cso;
so->fmt = 0;
so->wrap = (wrap_mode(cso->wrap_s) << NV30_3D_TEX_WRAP_S__SHIFT) |
(wrap_mode(cso->wrap_t) << NV30_3D_TEX_WRAP_T__SHIFT) |
(wrap_mode(cso->wrap_r) << NV30_3D_TEX_WRAP_R__SHIFT);
so->en = 0;
so->wrap |= compare_mode(cso);
so->filt = filter_mode(cso) | 0x00002000;
so->bcol = (float_to_ubyte(cso->border_color.f[3]) << 24) |
(float_to_ubyte(cso->border_color.f[0]) << 16) |
(float_to_ubyte(cso->border_color.f[1]) << 8) |
(float_to_ubyte(cso->border_color.f[2]) << 0);
if (eng3d->oclass >= NV40_3D_CLASS) {
unsigned aniso = cso->max_anisotropy;
if (!cso->normalized_coords)
so->fmt |= NV40_3D_TEX_FORMAT_RECT;
if (aniso > 1) {
if (aniso >= 16) so->en |= NV40_3D_TEX_ENABLE_ANISO_16X;
else if (aniso >= 12) so->en |= NV40_3D_TEX_ENABLE_ANISO_12X;
else if (aniso >= 10) so->en |= NV40_3D_TEX_ENABLE_ANISO_10X;
else if (aniso >= 8) so->en |= NV40_3D_TEX_ENABLE_ANISO_8X;
else if (aniso >= 6) so->en |= NV40_3D_TEX_ENABLE_ANISO_6X;
else if (aniso >= 4) so->en |= NV40_3D_TEX_ENABLE_ANISO_4X;
else so->en |= NV40_3D_TEX_ENABLE_ANISO_2X;
so->wrap |= nv30_context(pipe)->config.aniso;
}
} else {
so->en |= NV30_3D_TEX_ENABLE_ENABLE;
if (cso->max_anisotropy >= 8) so->en |= NV30_3D_TEX_ENABLE_ANISO_8X;
else if (cso->max_anisotropy >= 4) so->en |= NV30_3D_TEX_ENABLE_ANISO_4X;
else if (cso->max_anisotropy >= 2) so->en |= NV30_3D_TEX_ENABLE_ANISO_2X;
}
so->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
so->max_lod = (int)(CLAMP(cso->max_lod, 0.0, max_lod) * 256.0);
so->min_lod = (int)(CLAMP(cso->min_lod, 0.0, max_lod) * 256.0);
return so;
}
static void
nv30_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
{
FREE(hwcso);
}
static INLINE uint32_t
swizzle(const struct nv30_texfmt *fmt, unsigned cmp, unsigned swz)
{
uint32_t data = fmt->swz[swz].src << 8;
if (swz <= PIPE_SWIZZLE_ALPHA)
data |= fmt->swz[swz].cmp;
else
data |= fmt->swz[cmp].cmp;
return data;
}
static struct pipe_sampler_view *
nv30_sampler_view_create(struct pipe_context *pipe, struct pipe_resource *pt,
const struct pipe_sampler_view *tmpl)
{
const struct nv30_texfmt *fmt = nv30_texfmt(pipe->screen, tmpl->format);
struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
struct nv30_miptree *mt = nv30_miptree(pt);
struct nv30_sampler_view *so;
so = MALLOC_STRUCT(nv30_sampler_view);
if (!so)
return NULL;
so->pipe = *tmpl;
so->pipe.reference.count = 1;
so->pipe.texture = NULL;
so->pipe.context = pipe;
pipe_resource_reference(&so->pipe.texture, pt);
so->fmt = NV30_3D_TEX_FORMAT_NO_BORDER;
switch (pt->target) {
case PIPE_TEXTURE_1D:
so->fmt |= NV30_3D_TEX_FORMAT_DIMS_1D;
break;
case PIPE_TEXTURE_CUBE:
so->fmt |= NV30_3D_TEX_FORMAT_CUBIC;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
so->fmt |= NV30_3D_TEX_FORMAT_DIMS_2D;
break;
case PIPE_TEXTURE_3D:
so->fmt |= NV30_3D_TEX_FORMAT_DIMS_3D;
break;
default:
assert(0);
so->fmt |= NV30_3D_TEX_FORMAT_DIMS_1D;
break;
}
so->filt = fmt->filter;
so->wrap = fmt->wrap;
so->swz = fmt->swizzle;
so->swz |= swizzle(fmt, 3, tmpl->swizzle_a);
so->swz |= swizzle(fmt, 0, tmpl->swizzle_r) << 2;
so->swz |= swizzle(fmt, 1, tmpl->swizzle_g) << 4;
so->swz |= swizzle(fmt, 2, tmpl->swizzle_b) << 6;
/* apparently, we need to ignore the t coordinate for 1D textures to
* fix piglit tex1d-2dborder
*/
so->wrap_mask = ~0;
if (pt->target == PIPE_TEXTURE_1D) {
so->wrap_mask &= ~NV30_3D_TEX_WRAP_T__MASK;
so->wrap |= NV30_3D_TEX_WRAP_T_REPEAT;
}
/* yet more hardware suckage, can't filter 32-bit float formats */
switch (tmpl->format) {
case PIPE_FORMAT_R32_FLOAT:
case PIPE_FORMAT_R32G32B32A32_FLOAT:
so->filt_mask = ~(NV30_3D_TEX_FILTER_MIN__MASK |
NV30_3D_TEX_FILTER_MAG__MASK);
so->filt |= NV30_3D_TEX_FILTER_MIN_NEAREST |
NV30_3D_TEX_FILTER_MAG_NEAREST;
break;
default:
so->filt_mask = ~0;
break;
}
so->npot_size0 = (pt->width0 << 16) | pt->height0;
if (eng3d->oclass >= NV40_3D_CLASS) {
so->npot_size1 = (pt->depth0 << 20) | mt->uniform_pitch;
if (!mt->swizzled)
so->fmt |= NV40_3D_TEX_FORMAT_LINEAR;
so->fmt |= 0x00008000;
so->fmt |= (pt->last_level + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT;
} else {
so->swz |= mt->uniform_pitch << NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT;
if (pt->last_level)
so->fmt |= NV30_3D_TEX_FORMAT_MIPMAP;
so->fmt |= util_logbase2(pt->width0) << 20;
so->fmt |= util_logbase2(pt->height0) << 24;
so->fmt |= util_logbase2(pt->depth0) << 28;
so->fmt |= 0x00010000;
}
so->base_lod = so->pipe.u.tex.first_level << 8;
so->high_lod = MIN2(pt->last_level, so->pipe.u.tex.last_level) << 8;
return &so->pipe;
}
static void
nv30_sampler_view_destroy(struct pipe_context *pipe,
struct pipe_sampler_view *view)
{
pipe_resource_reference(&view->texture, NULL);
FREE(view);
}
void
nv30_texture_init(struct pipe_context *pipe)
{
pipe->create_sampler_state = nv30_sampler_state_create;
pipe->delete_sampler_state = nv30_sampler_state_delete;
pipe->create_sampler_view = nv30_sampler_view_create;
pipe->sampler_view_destroy = nv30_sampler_view_destroy;
}
+755
View File
@@ -0,0 +1,755 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#define XFER_ARGS \
struct nv30_context *nv30, enum nv30_transfer_filter filter, \
struct nv30_rect *src, struct nv30_rect *dst
#include "util/u_math.h"
#include "nouveau/nv_object.xml.h"
#include "nouveau/nv_m2mf.xml.h"
#include "nv01_2d.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_transfer.h"
/* Various helper functions to transfer different types of data in a number
* of different ways.
*/
static INLINE boolean
nv30_transfer_scaled(struct nv30_rect *src, struct nv30_rect *dst)
{
if (src->x1 - src->x0 != dst->x1 - dst->x0)
return TRUE;
if (src->y1 - src->y0 != dst->y1 - dst->y0)
return TRUE;
return FALSE;
}
static INLINE boolean
nv30_transfer_blit(XFER_ARGS)
{
if (nv30->screen->eng3d->oclass < NV40_3D_CLASS)
return FALSE;
if (dst->offset & 63 || dst->pitch & 63 || dst->d > 1)
return FALSE;
if (dst->w < 2 || dst->h < 2)
return FALSE;
if (dst->cpp > 4 || (dst->cpp == 1 && !dst->pitch))
return FALSE;
if (src->cpp > 4)
return FALSE;
return TRUE;
}
static INLINE struct nouveau_heap *
nv30_transfer_rect_vertprog(struct nv30_context *nv30)
{
struct nouveau_heap *heap = nv30->screen->vp_exec_heap;
struct nouveau_heap *vp;
vp = nv30->blit_vp;
if (!vp) {
if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp)) {
while (heap->next && heap->size < 2) {
struct nouveau_heap **evict = heap->next->priv;
nouveau_heap_free(evict);
}
if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp))
return NULL;
}
vp = nv30->blit_vp;
if (vp) {
struct nouveau_pushbuf *push = nv30->base.pushbuf;
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);
PUSH_DATA (push, vp->start);
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
PUSH_DATA (push, 0x401f9c6c); /* mov o[hpos], a[0]; */
PUSH_DATA (push, 0x0040000d);
PUSH_DATA (push, 0x8106c083);
PUSH_DATA (push, 0x6041ff80);
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
PUSH_DATA (push, 0x401f9c6c); /* mov o[tex0], a[8]; end; */
PUSH_DATA (push, 0x0040080d);
PUSH_DATA (push, 0x8106c083);
PUSH_DATA (push, 0x6041ff9d);
}
}
return vp;
}
static INLINE struct nv04_resource *
nv30_transfer_rect_fragprog(struct nv30_context *nv30)
{
struct nv04_resource *fp = nv04_resource(nv30->blit_fp);
struct pipe_context *pipe = &nv30->base.pipe;
if (!fp) {
nv30->blit_fp = pipe_buffer_create(pipe->screen, 0, 0, 12 * 4);
if (nv30->blit_fp) {
struct pipe_transfer *transfer;
u32 *map = pipe_buffer_map(pipe, nv30->blit_fp,
PIPE_TRANSFER_WRITE, &transfer);
if (map) {
map[0] = 0x17009e00; /* texr r0, i[tex0], texture[0]; end; */
map[1] = 0x1c9dc801;
map[2] = 0x0001c800;
map[3] = 0x3fe1c800;
map[4] = 0x01401e81; /* end; */
map[5] = 0x1c9dc800;
map[6] = 0x0001c800;
map[7] = 0x0001c800;
pipe_buffer_unmap(pipe, transfer);
}
fp = nv04_resource(nv30->blit_fp);
nouveau_buffer_migrate(&nv30->base, fp, NOUVEAU_BO_VRAM);
}
}
return fp;
}
static void
nv30_transfer_rect_blit(XFER_ARGS)
{
struct nv04_resource *fp = nv30_transfer_rect_fragprog(nv30);
struct nouveau_heap *vp = nv30_transfer_rect_vertprog(nv30);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_pushbuf_refn refs[] = {
{ fp->bo, fp->domain | NOUVEAU_BO_RD },
{ src->bo, src->domain | NOUVEAU_BO_RD },
{ dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR },
};
u32 texfmt, texswz;
u32 format, stride;
if (nouveau_pushbuf_space(push, 512, 8, 0) ||
nouveau_pushbuf_refn (push, refs, sizeof(refs) / sizeof(refs[0])))
return;
/* various switches depending on cpp of the transfer */
switch (dst->cpp) {
case 4:
format = NV30_3D_RT_FORMAT_COLOR_A8R8G8B8 |
NV30_3D_RT_FORMAT_ZETA_Z24S8;
texfmt = NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8;
texswz = 0x0000aae4;
break;
case 2:
format = NV30_3D_RT_FORMAT_COLOR_R5G6B5 |
NV30_3D_RT_FORMAT_ZETA_Z16;
texfmt = NV40_3D_TEX_FORMAT_FORMAT_R5G6B5;
texswz = 0x0000a9e4;
break;
case 1:
format = NV30_3D_RT_FORMAT_COLOR_B8 |
NV30_3D_RT_FORMAT_ZETA_Z16;
texfmt = NV40_3D_TEX_FORMAT_FORMAT_L8;
texswz = 0x0000aaff;
break;
default:
assert(0);
return;
}
/* render target */
if (!dst->pitch) {
format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
format |= util_logbase2(dst->w) << 16;
format |= util_logbase2(dst->h) << 24;
stride = 64;
} else {
format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
stride = dst->pitch;
}
BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
PUSH_DATA (push, dst->w << 16);
PUSH_DATA (push, dst->h << 16);
BEGIN_NV04(push, NV30_3D(RT_HORIZ), 5);
PUSH_DATA (push, dst->w << 16);
PUSH_DATA (push, dst->h << 16);
PUSH_DATA (push, format);
PUSH_DATA (push, stride);
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);
nv30->dirty |= NV30_NEW_FRAMEBUFFER;
/* viewport state */
BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 1.0);
PUSH_DATAf(push, 1.0);
PUSH_DATAf(push, 1.0);
PUSH_DATAf(push, 1.0);
BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
PUSH_DATAf(push, 0.0);
PUSH_DATAf(push, 1.0);
nv30->dirty |= NV30_NEW_VIEWPORT;
/* blend state */
BEGIN_NV04(push, NV30_3D(COLOR_LOGIC_OP_ENABLE), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(DITHER_ENABLE), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(COLOR_MASK), 1);
PUSH_DATA (push, 0x01010101);
nv30->dirty |= NV30_NEW_BLEND;
/* depth-stencil-alpha state */
BEGIN_NV04(push, NV30_3D(DEPTH_WRITE_ENABLE), 2);
PUSH_DATA (push, 0);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(1)), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(ALPHA_FUNC_ENABLE), 1);
PUSH_DATA (push, 0);
nv30->dirty |= NV30_NEW_ZSA;
/* rasterizer state */
BEGIN_NV04(push, NV30_3D(SHADE_MODEL), 1);
PUSH_DATA (push, NV30_3D_SHADE_MODEL_FLAT);
BEGIN_NV04(push, NV30_3D(CULL_FACE_ENABLE), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(POLYGON_MODE_FRONT), 2);
PUSH_DATA (push, NV30_3D_POLYGON_MODE_FRONT_FILL);
PUSH_DATA (push, NV30_3D_POLYGON_MODE_BACK_FILL);
BEGIN_NV04(push, NV30_3D(POLYGON_OFFSET_FILL_ENABLE), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_ENABLE), 1);
PUSH_DATA (push, 0);
nv30->state.scissor_off = 0;
nv30->dirty |= NV30_NEW_RASTERIZER;
/* vertex program */
BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
PUSH_DATA (push, vp->start);
BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
PUSH_DATA (push, 0x00000101); /* attrib: 0, 8 */
PUSH_DATA (push, 0x00004000); /* result: hpos, tex0 */
BEGIN_NV04(push, NV30_3D(ENGINE), 1);
PUSH_DATA (push, 0x00000103);
BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1);
PUSH_DATA (push, 0x00000000);
nv30->dirty |= NV30_NEW_VERTPROG;
nv30->dirty |= NV30_NEW_CLIP;
/* fragment program */
BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);
PUSH_RELOC(push, fp->bo, fp->offset, fp->domain |
NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
NV30_3D_FP_ACTIVE_PROGRAM_DMA0,
NV30_3D_FP_ACTIVE_PROGRAM_DMA1);
BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);
PUSH_DATA (push, 0x02000000);
nv30->state.fragprog = NULL;
nv30->dirty |= NV30_NEW_FRAGPROG;
/* texture */
texfmt |= 1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT;
texfmt |= NV30_3D_TEX_FORMAT_NO_BORDER;
texfmt |= NV40_3D_TEX_FORMAT_RECT;
texfmt |= 0x00008000;
if (src->d < 2)
texfmt |= NV30_3D_TEX_FORMAT_DIMS_2D;
else
texfmt |= NV30_3D_TEX_FORMAT_DIMS_3D;
if (src->pitch)
texfmt |= NV40_3D_TEX_FORMAT_LINEAR;
BEGIN_NV04(push, NV30_3D(TEX_OFFSET(0)), 8);
PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
PUSH_RELOC(push, src->bo, texfmt, NOUVEAU_BO_OR,
NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE |
NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE |
NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE);
PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE);
PUSH_DATA (push, texswz);
switch (filter) {
case BILINEAR:
PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR |
NV30_3D_TEX_FILTER_MAG_LINEAR | 0x00002000);
break;
default:
PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST |
NV30_3D_TEX_FILTER_MAG_NEAREST | 0x00002000);
break;
}
PUSH_DATA (push, (src->w << 16) | src->h);
PUSH_DATA (push, 0x00000000);
BEGIN_NV04(push, NV40_3D(TEX_SIZE1(0)), 1);
PUSH_DATA (push, 0x00100000 | src->pitch);
BEGIN_NV04(push, SUBC_3D(0x0b40), 1);
PUSH_DATA (push, src->d < 2 ? 0x00000001 : 0x00000000);
BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
PUSH_DATA (push, 1);
nv30->fragprog.dirty_samplers |= 1;
nv30->dirty |= NV30_NEW_FRAGTEX;
/* blit! */
BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
PUSH_DATA (push, (dst->x1 - dst->x0) << 16 | dst->x0);
PUSH_DATA (push, (dst->y1 - dst->y0) << 16 | dst->y0);
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_QUADS);
BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
PUSH_DATAf(push, src->x0);
PUSH_DATAf(push, src->y0);
PUSH_DATAf(push, src->z);
BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
PUSH_DATA (push, (dst->y0 << 16) | dst->x0);
BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
PUSH_DATAf(push, src->x1);
PUSH_DATAf(push, src->y0);
PUSH_DATAf(push, src->z);
BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
PUSH_DATA (push, (dst->y0 << 16) | dst->x1);
BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
PUSH_DATAf(push, src->x1);
PUSH_DATAf(push, src->y1);
PUSH_DATAf(push, src->z);
BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
PUSH_DATA (push, (dst->y1 << 16) | dst->x1);
BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
PUSH_DATAf(push, src->x0);
PUSH_DATAf(push, src->y1);
PUSH_DATAf(push, src->z);
BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
PUSH_DATA (push, (dst->y1 << 16) | dst->x0);
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
}
static boolean
nv30_transfer_sifm(XFER_ARGS)
{
if (!src->pitch || (src->w | src->h) > 1024 || src->w < 2 || src->h < 2)
return FALSE;
if (src->d > 1 || dst->d > 1)
return FALSE;
if (dst->offset & 63)
return FALSE;
if (!dst->pitch) {
if ((dst->w | dst->h) > 2048 || dst->w < 2 || dst->h < 2)
return FALSE;
} else {
if (dst->domain != NOUVEAU_BO_VRAM)
return FALSE;
if (dst->pitch & 63)
return FALSE;
}
return TRUE;
}
static void
nv30_transfer_rect_sifm(XFER_ARGS)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_pushbuf_refn refs[] = {
{ src->bo, src->domain | NOUVEAU_BO_RD },
{ dst->bo, dst->domain | NOUVEAU_BO_WR },
};
struct nv04_fifo *fifo = push->channel->data;
unsigned si_fmt, si_arg;
unsigned ss_fmt;
switch (dst->cpp) {
case 4: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_A8R8G8B8; break;
case 2: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_R5G6B5; break;
default:
ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_Y8;
break;
}
switch (src->cpp) {
case 4: si_fmt = NV03_SIFM_COLOR_FORMAT_A8R8G8B8; break;
case 2: si_fmt = NV03_SIFM_COLOR_FORMAT_R5G6B5; break;
default:
si_fmt = NV03_SIFM_COLOR_FORMAT_AY8;
break;
}
if (filter == NEAREST) {
si_arg = NV03_SIFM_FORMAT_ORIGIN_CENTER;
si_arg |= NV03_SIFM_FORMAT_FILTER_POINT_SAMPLE;
} else {
si_arg = NV03_SIFM_FORMAT_ORIGIN_CORNER;
si_arg |= NV03_SIFM_FORMAT_FILTER_BILINEAR;
}
if (nouveau_pushbuf_space(push, 32, 6, 0) ||
nouveau_pushbuf_refn (push, refs, 2))
return;
if (dst->pitch) {
BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
PUSH_DATA (push, ss_fmt);
PUSH_DATA (push, dst->pitch << 16 | dst->pitch);
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
PUSH_DATA (push, nv30->screen->surf2d->handle);
} else {
BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);
PUSH_DATA (push, ss_fmt | (util_logbase2(dst->w) << 16) |
(util_logbase2(dst->h) << 24));
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
PUSH_DATA (push, nv30->screen->swzsurf->handle);
}
BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);
PUSH_DATA (push, si_fmt);
PUSH_DATA (push, NV03_SIFM_OPERATION_SRCCOPY);
PUSH_DATA (push, ( dst->y0 << 16) | dst->x0);
PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0));
PUSH_DATA (push, ( dst->y0 << 16) | dst->x0);
PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0));
PUSH_DATA (push, ((src->x1 - src->x0) << 20) / (dst->x1 - dst->x0));
PUSH_DATA (push, ((src->y1 - src->y0) << 20) / (dst->y1 - dst->y0));
BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
PUSH_DATA (push, align((src->y1 - src->y0), 2) << 16 |
align((src->x1 - src->x0), 2));
PUSH_DATA (push, src->pitch | si_arg);
PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
PUSH_DATA (push, (src->y0 << 16) | src->x0);
}
/* The NOP+OFFSET_OUT stuff after each M2MF transfer *is* actually required
* to prevent some odd things from happening, easily reproducible by
* attempting to do conditional rendering that has a M2MF transfer done
* some time before it. 0x1e98 will fail with a DMA_W_PROTECTION (assuming
* that name is still accurate on nv4x) error.
*/
static boolean
nv30_transfer_m2mf(XFER_ARGS)
{
if (!src->pitch || !dst->pitch)
return FALSE;
if (nv30_transfer_scaled(src, dst))
return FALSE;
return TRUE;
}
static void
nv30_transfer_rect_m2mf(XFER_ARGS)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_pushbuf_refn refs[] = {
{ src->bo, src->domain | NOUVEAU_BO_RD },
{ dst->bo, dst->domain | NOUVEAU_BO_WR },
};
struct nv04_fifo *fifo = push->channel->data;
unsigned src_offset = src->offset;
unsigned dst_offset = dst->offset;
unsigned w = dst->x1 - dst->x0;
unsigned h = dst->y1 - dst->y0;
src_offset += (src->y0 * src->pitch) + (src->x0 * src->cpp);
dst_offset += (dst->y0 * dst->pitch) + (dst->x0 * dst->cpp);
BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
PUSH_DATA (push, (src->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
PUSH_DATA (push, (dst->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
while (h) {
unsigned lines = (h > 2047) ? 2047 : h;
if (nouveau_pushbuf_space(push, 13, 2, 0) ||
nouveau_pushbuf_refn (push, refs, 2))
return;
BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
PUSH_RELOC(push, src->bo, src_offset, NOUVEAU_BO_LOW, 0, 0);
PUSH_RELOC(push, dst->bo, dst_offset, NOUVEAU_BO_LOW, 0, 0);
PUSH_DATA (push, src->pitch);
PUSH_DATA (push, dst->pitch);
PUSH_DATA (push, w * src->cpp);
PUSH_DATA (push, lines);
PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
NV03_M2MF_FORMAT_OUTPUT_INC_1);
PUSH_DATA (push, 0x00000000);
BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
PUSH_DATA (push, 0x00000000);
BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
PUSH_DATA (push, 0x00000000);
h -= lines;
src_offset += src->pitch * lines;
dst_offset += dst->pitch * lines;
}
}
static boolean
nv30_transfer_cpu(XFER_ARGS)
{
if (nv30_transfer_scaled(src, dst))
return FALSE;
return TRUE;
}
static char *
linear_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
{
return base + (y * rect->pitch) + (x * rect->cpp);
}
static INLINE unsigned
swizzle2d(unsigned v, unsigned s)
{
v = (v | (v << 8)) & 0x00ff00ff;
v = (v | (v << 4)) & 0x0f0f0f0f;
v = (v | (v << 2)) & 0x33333333;
v = (v | (v << 1)) & 0x55555555;
return v << s;
}
static char *
swizzle2d_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
{
unsigned k = util_logbase2(MIN2(rect->w, rect->h));
unsigned km = (1 << k) - 1;
unsigned nx = rect->w >> k;
unsigned tx = x >> k;
unsigned ty = y >> k;
unsigned m;
m = swizzle2d(x & km, 0);
m |= swizzle2d(y & km, 1);
m += ((ty * nx) + tx) << k << k;
return base + (m * rect->cpp);
}
static char *
swizzle3d_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
{
unsigned w = rect->w >> 1;
unsigned h = rect->h >> 1;
unsigned d = rect->d >> 1;
unsigned i = 0, o;
unsigned v = 0;
do {
o = i;
if (w) {
v |= (x & 1) << i++;
x >>= 1;
w >>= 1;
}
if (h) {
v |= (y & 1) << i++;
y >>= 1;
h >>= 1;
}
if (d) {
v |= (z & 1) << i++;
z >>= 1;
d >>= 1;
}
} while(o != i);
return base + (v * rect->cpp);
}
typedef char *(*get_ptr_t)(struct nv30_rect *, char *, int, int, int);
static INLINE get_ptr_t
get_ptr(struct nv30_rect *rect)
{
if (rect->pitch)
return linear_ptr;
if (rect->d <= 1)
return swizzle2d_ptr;
return swizzle3d_ptr;
}
static void
nv30_transfer_rect_cpu(XFER_ARGS)
{
get_ptr_t sp = get_ptr(src);
get_ptr_t dp = get_ptr(dst);
char *srcmap, *dstmap;
int x, y;
nouveau_bo_map(src->bo, NOUVEAU_BO_RD, nv30->base.client);
nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, nv30->base.client);
srcmap = src->bo->map + src->offset;
dstmap = dst->bo->map + dst->offset;
for (y = 0; y < (dst->y1 - dst->y0); y++) {
for (x = 0; x < (dst->x1 - dst->x0); x++) {
memcpy(dp(dst, dstmap, dst->x0 + x, dst->y0 + y, dst->z),
sp(src, srcmap, src->x0 + x, src->y0 + y, src->z), dst->cpp);
}
}
}
void
nv30_transfer_rect(struct nv30_context *nv30, enum nv30_transfer_filter filter,
struct nv30_rect *src, struct nv30_rect *dst)
{
static const struct {
char *name;
boolean (*possible)(XFER_ARGS);
void (*execute)(XFER_ARGS);
} *method, methods[] = {
{ "m2mf", nv30_transfer_m2mf, nv30_transfer_rect_m2mf },
{ "sifm", nv30_transfer_sifm, nv30_transfer_rect_sifm },
{ "blit", nv30_transfer_blit, nv30_transfer_rect_blit },
{ "rect", nv30_transfer_cpu, nv30_transfer_rect_cpu },
{}
};
method = methods - 1;
while ((++method)->possible) {
if (method->possible(nv30, filter, src, dst)) {
method->execute(nv30, filter, src, dst);
return;
}
}
assert(0);
}
void
nv30_transfer_push_data(struct nouveau_context *nv,
struct nouveau_bo *bo, unsigned offset, unsigned domain,
unsigned size, void *data)
{
/* use ifc, or scratch + copy_data? */
fprintf(stderr, "nv30: push_data not implemented\n");
}
void
nv30_transfer_copy_data(struct nouveau_context *nv,
struct nouveau_bo *dst, unsigned d_off, unsigned d_dom,
struct nouveau_bo *src, unsigned s_off, unsigned s_dom,
unsigned size)
{
struct nv04_fifo *fifo = nv->screen->channel->data;
struct nouveau_pushbuf_refn refs[] = {
{ src, s_dom | NOUVEAU_BO_RD },
{ dst, d_dom | NOUVEAU_BO_WR },
};
struct nouveau_pushbuf *push = nv->pushbuf;
unsigned pages, lines;
pages = size >> 12;
size -= (pages << 12);
BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
PUSH_DATA (push, (s_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
PUSH_DATA (push, (d_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
while (pages) {
lines = (pages > 2047) ? 2047 : pages;
pages -= lines;
if (nouveau_pushbuf_space(push, 13, 2, 0) ||
nouveau_pushbuf_refn (push, refs, 2))
return;
BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0);
PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0);
PUSH_DATA (push, 4096);
PUSH_DATA (push, 4096);
PUSH_DATA (push, 4096);
PUSH_DATA (push, lines);
PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
NV03_M2MF_FORMAT_OUTPUT_INC_1);
PUSH_DATA (push, 0x00000000);
BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
PUSH_DATA (push, 0x00000000);
BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
PUSH_DATA (push, 0x00000000);
s_off += (lines << 12);
d_off += (lines << 12);
}
if (size) {
if (nouveau_pushbuf_space(push, 13, 2, 0) ||
nouveau_pushbuf_refn (push, refs, 2))
return;
BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0);
PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0);
PUSH_DATA (push, size);
PUSH_DATA (push, size);
PUSH_DATA (push, size);
PUSH_DATA (push, 1);
PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
NV03_M2MF_FORMAT_OUTPUT_INC_1);
PUSH_DATA (push, 0x00000000);
BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
PUSH_DATA (push, 0x00000000);
BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
PUSH_DATA (push, 0x00000000);
}
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef __NV30_TRANSFER_H__
#define __NV30_TRANSFER_H__
struct nv30_rect {
struct nouveau_bo *bo;
unsigned offset;
unsigned domain;
unsigned pitch;
unsigned cpp;
unsigned w;
unsigned h;
unsigned d;
unsigned z;
unsigned x0;
unsigned x1;
unsigned y0;
unsigned y1;
};
enum nv30_transfer_filter {
NEAREST = 0,
BILINEAR
};
void
nv30_transfer_rect(struct nv30_context *, enum nv30_transfer_filter filter,
struct nv30_rect *, struct nv30_rect *);
void
nv30_transfer_push_data(struct nouveau_context *,
struct nouveau_bo *, unsigned offset, unsigned domain,
unsigned size, void *data);
void
nv30_transfer_copy_data(struct nouveau_context *,
struct nouveau_bo *, unsigned dstoff, unsigned dstdom,
struct nouveau_bo *, unsigned srcoff, unsigned srcdom,
unsigned size);
#endif
+620
View File
@@ -0,0 +1,620 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "translate/translate.h"
#include "nouveau/nouveau_fence.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_format.h"
static void
nv30_emit_vtxattr(struct nv30_context *nv30, struct pipe_vertex_buffer *vb,
struct pipe_vertex_element *ve, unsigned attr)
{
const unsigned nc = util_format_get_nr_components(ve->src_format);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nv04_resource *res = nv04_resource(vb->buffer);
const void *data;
float v[4];
data = nouveau_resource_map_offset(&nv30->base, res, vb->buffer_offset +
ve->src_offset, NOUVEAU_BO_RD);
util_format_read_4f(ve->src_format, v, 0, data, 0, 0, 0, 1, 1);
switch (nc) {
case 4:
BEGIN_NV04(push, NV30_3D(VTX_ATTR_4F(attr)), 4);
PUSH_DATAf(push, v[0]);
PUSH_DATAf(push, v[1]);
PUSH_DATAf(push, v[2]);
PUSH_DATAf(push, v[3]);
break;
case 3:
BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(attr)), 3);
PUSH_DATAf(push, v[0]);
PUSH_DATAf(push, v[1]);
PUSH_DATAf(push, v[2]);
break;
case 2:
BEGIN_NV04(push, NV30_3D(VTX_ATTR_2F(attr)), 2);
PUSH_DATAf(push, v[0]);
PUSH_DATAf(push, v[1]);
break;
case 1:
BEGIN_NV04(push, NV30_3D(VTX_ATTR_1F(attr)), 1);
PUSH_DATAf(push, v[0]);
break;
default:
assert(0);
break;
}
}
static INLINE void
nv30_vbuf_range(struct nv30_context *nv30, int vbi,
uint32_t *base, uint32_t *size)
{
assert(nv30->vbo_max_index != ~0);
*base = nv30->vbo_min_index * nv30->vtxbuf[vbi].stride;
*size = (nv30->vbo_max_index -
nv30->vbo_min_index + 1) * nv30->vtxbuf[vbi].stride;
}
static void
nv30_prevalidate_vbufs(struct nv30_context *nv30)
{
struct pipe_vertex_buffer *vb;
struct nv04_resource *buf;
int i;
uint32_t base, size;
nv30->vbo_fifo = nv30->vbo_user = 0;
for (i = 0; i < nv30->num_vtxbufs; i++) {
vb = &nv30->vtxbuf[i];
if (!vb->stride)
continue;
buf = nv04_resource(vb->buffer);
/* NOTE: user buffers with temporary storage count as mapped by GPU */
if (!nouveau_resource_mapped_by_gpu(vb->buffer)) {
if (nv30->vbo_push_hint) {
nv30->vbo_fifo = ~0;
continue;
} else {
if (buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY) {
nv30->vbo_user |= 1 << i;
assert(vb->stride > vb->buffer_offset);
nv30_vbuf_range(nv30, i, &base, &size);
nouveau_user_buffer_upload(&nv30->base, buf, base, size);
} else {
nouveau_buffer_migrate(&nv30->base, buf, NOUVEAU_BO_GART);
}
nv30->base.vbo_dirty = TRUE;
}
}
}
}
static void
nv30_update_user_vbufs(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
uint32_t base, offset, size;
int i;
uint32_t written = 0;
for (i = 0; i < nv30->vertex->num_elements; i++) {
struct pipe_vertex_element *ve = &nv30->vertex->pipe[i];
const int b = ve->vertex_buffer_index;
struct pipe_vertex_buffer *vb = &nv30->vtxbuf[b];
struct nv04_resource *buf = nv04_resource(vb->buffer);
if (!(nv30->vbo_user & (1 << b)))
continue;
if (!vb->stride) {
nv30_emit_vtxattr(nv30, vb, ve, i);
continue;
}
nv30_vbuf_range(nv30, b, &base, &size);
if (!(written & (1 << b))) {
written |= 1 << b;
nouveau_user_buffer_upload(&nv30->base, buf, base, size);
}
offset = vb->buffer_offset + ve->src_offset;
BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, buf, offset,
NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
0, NV30_3D_VTXBUF_DMA1);
}
nv30->base.vbo_dirty = TRUE;
}
static INLINE void
nv30_release_user_vbufs(struct nv30_context *nv30)
{
uint32_t vbo_user = nv30->vbo_user;
while (vbo_user) {
int i = ffs(vbo_user) - 1;
vbo_user &= ~(1 << i);
nouveau_buffer_release_gpu_storage(nv04_resource(nv30->vtxbuf[i].buffer));
}
nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXTMP);
}
void
nv30_vbo_validate(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nv30_vertex_stateobj *vertex = nv30->vertex;
struct pipe_vertex_element *ve;
struct pipe_vertex_buffer *vb;
unsigned i, redefine;
nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
if (!nv30->vertex || nv30->draw_flags)
return;
if (unlikely(vertex->need_conversion)) {
nv30->vbo_fifo = ~0;
nv30->vbo_user = 0;
} else {
nv30_prevalidate_vbufs(nv30);
}
if (!PUSH_SPACE(push, 128))
return;
redefine = MAX2(vertex->num_elements, nv30->state.num_vtxelts);
BEGIN_NV04(push, NV30_3D(VTXFMT(0)), redefine);
for (i = 0; i < vertex->num_elements; i++) {
ve = &vertex->pipe[i];
vb = &nv30->vtxbuf[ve->vertex_buffer_index];
if (likely(vb->stride) || nv30->vbo_fifo)
PUSH_DATA (push, (vb->stride << 8) | vertex->element[i].state);
else
PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
}
for (; i < nv30->state.num_vtxelts; i++) {
PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
}
for (i = 0; i < vertex->num_elements; i++) {
struct nv04_resource *res;
unsigned offset;
boolean user;
ve = &vertex->pipe[i];
vb = &nv30->vtxbuf[ve->vertex_buffer_index];
user = (nv30->vbo_user & (1 << ve->vertex_buffer_index));
res = nv04_resource(vb->buffer);
if (nv30->vbo_fifo || unlikely(vb->stride == 0)) {
if (!nv30->vbo_fifo)
nv30_emit_vtxattr(nv30, vb, ve, i);
continue;
}
offset = ve->src_offset + vb->buffer_offset;
BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
PUSH_RESRC(push, NV30_3D(VTXBUF(i)), user ? BUFCTX_VTXTMP : BUFCTX_VTXBUF,
res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
0, NV30_3D_VTXBUF_DMA1);
}
nv30->state.num_vtxelts = vertex->num_elements;
}
static void *
nv30_vertex_state_create(struct pipe_context *pipe, unsigned num_elements,
const struct pipe_vertex_element *elements)
{
struct nv30_vertex_stateobj *so;
struct translate_key transkey;
unsigned i;
assert(num_elements);
so = MALLOC(sizeof(*so) + sizeof(*so->element) * num_elements);
if (!so)
return NULL;
memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
so->num_elements = num_elements;
so->need_conversion = FALSE;
transkey.nr_elements = 0;
transkey.output_stride = 0;
for (i = 0; i < num_elements; i++) {
const struct pipe_vertex_element *ve = &elements[i];
const unsigned vbi = ve->vertex_buffer_index;
enum pipe_format fmt = ve->src_format;
so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw;
if (!so->element[i].state) {
switch (util_format_get_nr_components(fmt)) {
case 1: fmt = PIPE_FORMAT_R32_FLOAT; break;
case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break;
case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break;
case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break;
default:
assert(0);
return NULL;
}
so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw;
so->need_conversion = TRUE;
}
if (1) {
unsigned j = transkey.nr_elements++;
transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL;
transkey.element[j].input_format = ve->src_format;
transkey.element[j].input_buffer = vbi;
transkey.element[j].input_offset = ve->src_offset;
transkey.element[j].instance_divisor = ve->instance_divisor;
transkey.element[j].output_format = fmt;
transkey.element[j].output_offset = transkey.output_stride;
transkey.output_stride += (util_format_get_stride(fmt, 1) + 3) & ~3;
}
}
so->translate = translate_create(&transkey);
so->vtx_size = transkey.output_stride / 4;
so->vtx_per_packet_max = NV04_PFIFO_MAX_PACKET_LEN / MAX2(so->vtx_size, 1);
return so;
}
static void
nv30_vertex_state_delete(struct pipe_context *pipe, void *hwcso)
{
struct nv30_vertex_stateobj *so = hwcso;
if (so->translate)
so->translate->release(so->translate);
FREE(hwcso);
}
static void
nv30_vertex_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->vertex = hwcso;
nv30->dirty |= NV30_NEW_VERTEX;
}
static void
nv30_draw_arrays(struct nv30_context *nv30,
unsigned mode, unsigned start, unsigned count,
unsigned instance_count)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
unsigned prim;
prim = nv30_prim_gl(mode);
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, prim);
while (count) {
const unsigned mpush = 2047 * 256;
unsigned npush = (count > mpush) ? mpush : count;
unsigned wpush = ((npush + 255) & ~255) >> 8;
count -= npush;
BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), wpush);
while (npush >= 256) {
PUSH_DATA (push, 0xff000000 | start);
start += 256;
npush -= 256;
}
if (npush)
PUSH_DATA (push, ((npush - 1) << 24) | start);
}
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
}
static void
nv30_draw_elements_inline_u08(struct nouveau_pushbuf *push, uint8_t *map,
unsigned start, unsigned count)
{
map += start;
if (count & 1) {
BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
PUSH_DATA (push, *map++);
}
count >>= 1;
while (count) {
unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
count -= npush;
BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
while (npush--) {
PUSH_DATA (push, (map[1] << 16) | map[0]);
map += 2;
}
}
}
static void
nv30_draw_elements_inline_u16(struct nouveau_pushbuf *push, uint16_t *map,
unsigned start, unsigned count)
{
map += start;
if (count & 1) {
BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
PUSH_DATA (push, *map++);
}
count >>= 1;
while (count) {
unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
count -= npush;
BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
while (npush--) {
PUSH_DATA (push, (map[1] << 16) | map[0]);
map += 2;
}
}
}
static void
nv30_draw_elements_inline_u32(struct nouveau_pushbuf *push, uint32_t *map,
unsigned start, unsigned count)
{
map += start;
while (count) {
const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U32), nr);
PUSH_DATAp(push, map, nr);
map += nr;
count -= nr;
}
}
static void
nv30_draw_elements_inline_u32_short(struct nouveau_pushbuf *push, uint32_t *map,
unsigned start, unsigned count)
{
map += start;
if (count & 1) {
BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
PUSH_DATA (push, *map++);
}
count >>= 1;
while (count) {
unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);;
count -= npush;
BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
while (npush--) {
PUSH_DATA (push, (map[1] << 16) | map[0]);
map += 2;
}
}
}
static void
nv30_draw_elements(struct nv30_context *nv30, boolean shorten,
unsigned mode, unsigned start, unsigned count,
unsigned instance_count, int32_t index_bias)
{
const unsigned index_size = nv30->idxbuf.index_size;
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_object *eng3d = nv30->screen->eng3d;
unsigned prim = nv30_prim_gl(mode);
void *data;
#if 0 /*XXX*/
if (index_bias != nv30->state.index_bias) {
BEGIN_NV04(push, NV30_3D(VB_ELEMENT_BASE), 1);
PUSH_DATA (push, index_bias);
nv30->state.index_bias = index_bias;
}
#endif
if (eng3d->oclass == NV40_3D_CLASS && index_size > 1 &&
nouveau_resource_mapped_by_gpu(nv30->idxbuf.buffer)) {
struct nv04_resource *res = nv04_resource(nv30->idxbuf.buffer);
unsigned offset = nv30->idxbuf.offset;
BEGIN_NV04(push, NV30_3D(IDXBUF_OFFSET), 2);
PUSH_RESRC(push, NV30_3D(IDXBUF_OFFSET), BUFCTX_IDXBUF, res, offset,
NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
PUSH_MTHD (push, NV30_3D(IDXBUF_FORMAT), BUFCTX_IDXBUF, res->bo,
(index_size == 2) ? 0x00000010 : 0x00000000,
res->domain | NOUVEAU_BO_RD,
0, NV30_3D_IDXBUF_FORMAT_DMA1);
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, prim);
while (count) {
const unsigned mpush = 2047 * 256;
unsigned npush = (count > mpush) ? mpush : count;
unsigned wpush = ((npush + 255) & ~255) >> 8;
count -= npush;
BEGIN_NI04(push, NV30_3D(VB_INDEX_BATCH), wpush);
while (npush >= 256) {
PUSH_DATA (push, 0xff000000 | start);
start += 256;
npush -= 256;
}
if (npush)
PUSH_DATA (push, ((npush - 1) << 24) | start);
}
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
PUSH_RESET(push, BUFCTX_IDXBUF);
} else {
data = nouveau_resource_map_offset(&nv30->base,
nv04_resource(nv30->idxbuf.buffer),
nv30->idxbuf.offset, NOUVEAU_BO_RD);
if (!data)
return;
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, prim);
switch (index_size) {
case 1:
nv30_draw_elements_inline_u08(push, data, start, count);
break;
case 2:
nv30_draw_elements_inline_u16(push, data, start, count);
break;
case 4:
if (shorten)
nv30_draw_elements_inline_u32_short(push, data, start, count);
else
nv30_draw_elements_inline_u32(push, data, start, count);
break;
default:
assert(0);
return;
}
BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
}
}
static void
nv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nouveau_pushbuf *push = nv30->base.pushbuf;
/* For picking only a few vertices from a large user buffer, push is better,
* if index count is larger and we expect repeated vertices, suggest upload.
*/
nv30->vbo_push_hint = /* the 64 is heuristic */
!(info->indexed &&
((info->max_index - info->min_index + 64) < info->count));
nv30->vbo_min_index = info->min_index;
nv30->vbo_max_index = info->max_index;
if (nv30->vbo_push_hint != !!nv30->vbo_fifo)
nv30->dirty |= NV30_NEW_ARRAYS;
push->user_priv = &nv30->bufctx;
if (nv30->vbo_user && !(nv30->dirty & (NV30_NEW_VERTEX | NV30_NEW_ARRAYS)))
nv30_update_user_vbufs(nv30);
nv30_state_validate(nv30, TRUE);
if (nv30->draw_flags) {
nv30_render_vbo(pipe, info);
return;
} else
if (nv30->vbo_fifo) {
nv30_push_vbo(nv30, info);
return;
}
if (nv30->base.vbo_dirty) {
BEGIN_NV04(push, NV30_3D(VTX_CACHE_INVALIDATE_1710), 1);
PUSH_DATA (push, 0);
nv30->base.vbo_dirty = FALSE;
}
if (!info->indexed) {
nv30_draw_arrays(nv30,
info->mode, info->start, info->count,
info->instance_count);
} else {
boolean shorten = info->max_index <= 65535;
assert(nv30->idxbuf.buffer);
if (info->primitive_restart != nv30->state.prim_restart) {
if (info->primitive_restart) {
BEGIN_NV04(push, NV40_3D(PRIM_RESTART_ENABLE), 2);
PUSH_DATA (push, 1);
PUSH_DATA (push, info->restart_index);
if (info->restart_index > 65535)
shorten = FALSE;
} else {
BEGIN_NV04(push, NV40_3D(PRIM_RESTART_ENABLE), 1);
PUSH_DATA (push, 0);
}
nv30->state.prim_restart = info->primitive_restart;
} else
if (info->primitive_restart) {
BEGIN_NV04(push, NV40_3D(PRIM_RESTART_INDEX), 1);
PUSH_DATA (push, info->restart_index);
if (info->restart_index > 65535)
shorten = FALSE;
}
nv30_draw_elements(nv30, shorten,
info->mode, info->start, info->count,
info->instance_count, info->index_bias);
}
nv30_state_release(nv30);
nv30_release_user_vbufs(nv30);
}
void
nv30_vbo_init(struct pipe_context *pipe)
{
pipe->create_vertex_elements_state = nv30_vertex_state_create;
pipe->delete_vertex_elements_state = nv30_vertex_state_delete;
pipe->bind_vertex_elements_state = nv30_vertex_state_bind;
pipe->draw_vbo = nv30_draw_vbo;
}
+258
View File
@@ -0,0 +1,258 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_dynarray.h"
#include "tgsi/tgsi_parse.h"
#include "nouveau/nv_object.xml.h"
#include "nv30-40_3d.xml.h"
#include "nv30_context.h"
#include "nv30_state.h"
static void
nv30_vertprog_destroy(struct nv30_vertprog *vp)
{
util_dynarray_fini(&vp->branch_relocs);
nouveau_heap_free(&vp->exec);
FREE(vp->insns);
vp->insns = NULL;
vp->nr_insns = 0;
util_dynarray_fini(&vp->const_relocs);
nouveau_heap_free(&vp->data);
FREE(vp->consts);
vp->consts = NULL;
vp->nr_consts = 0;
vp->translated = FALSE;
}
void
nv30_vertprog_validate(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_object *eng3d = nv30->screen->eng3d;
struct nv30_vertprog *vp = nv30->vertprog.program;
struct nv30_fragprog *fp = nv30->fragprog.program;
boolean upload_code = FALSE;
boolean upload_data = FALSE;
unsigned i;
if (nv30->dirty & NV30_NEW_FRAGPROG) {
if (memcmp(vp->texcoord, fp->texcoord, sizeof(vp->texcoord))) {
if (vp->translated)
nv30_vertprog_destroy(vp);
memcpy(vp->texcoord, fp->texcoord, sizeof(vp->texcoord));
}
}
if (nv30->rast && nv30->rast->pipe.clip_plane_enable != vp->enabled_ucps) {
vp->enabled_ucps = nv30->rast->pipe.clip_plane_enable;
if (vp->translated)
nv30_vertprog_destroy(vp);
}
if (!vp->translated) {
vp->translated = _nvfx_vertprog_translate(nv30, vp);
if (!vp->translated) {
nv30->draw_flags |= NV30_NEW_VERTPROG;
return;
}
nv30->dirty |= NV30_NEW_VERTPROG;
}
if (!vp->exec) {
struct nouveau_heap *heap = nv30->screen->vp_exec_heap;
struct nv30_shader_reloc *reloc = vp->branch_relocs.data;
unsigned nr_reloc = vp->branch_relocs.size / sizeof(*reloc);
uint32_t *inst, target;
if (nouveau_heap_alloc(heap, vp->nr_insns, &vp->exec, &vp->exec)) {
while (heap->next && heap->size < vp->nr_insns) {
struct nouveau_heap **evict = heap->next->priv;
nouveau_heap_free(evict);
}
if (nouveau_heap_alloc(heap, vp->nr_insns, &vp->exec, &vp->exec)) {
nv30->draw_flags |= NV30_NEW_VERTPROG;
return;
}
}
if (eng3d->oclass < NV40_3D_CLASS) {
while (nr_reloc--) {
inst = vp->insns[reloc->location].data;
target = vp->exec->start + reloc->target;
inst[2] &= ~0x000007fc;
inst[2] |= target << 2;
reloc++;
}
} else {
while (nr_reloc--) {
inst = vp->insns[reloc->location].data;
target = vp->exec->start + reloc->target;
inst[2] &= ~0x0000003f;
inst[2] |= target >> 3;
inst[3] &= ~0xe0000000;
inst[3] |= target << 29;
reloc++;
}
}
upload_code = TRUE;
}
if (vp->nr_consts && !vp->data) {
struct nouveau_heap *heap = nv30->screen->vp_data_heap;
struct nv30_shader_reloc *reloc = vp->const_relocs.data;
unsigned nr_reloc = vp->const_relocs.size / sizeof(*reloc);
uint32_t *inst, target;
if (nouveau_heap_alloc(heap, vp->nr_consts, vp, &vp->data)) {
while (heap->next && heap->size < vp->nr_consts) {
struct nv30_vertprog *evp = heap->next->priv;
nouveau_heap_free(&evp->data);
}
if (nouveau_heap_alloc(heap, vp->nr_consts, vp, &vp->data)) {
nv30->draw_flags |= NV30_NEW_VERTPROG;
return;
}
}
if (eng3d->oclass < NV40_3D_CLASS) {
while (nr_reloc--) {
inst = vp->insns[reloc->location].data;
target = vp->data->start + reloc->target;
inst[1] &= ~0x0003fc000;
inst[1] |= target << 14;
reloc++;
}
} else {
while (nr_reloc--) {
inst = vp->insns[reloc->location].data;
target = vp->data->start + reloc->target;
inst[1] &= ~0x0001ff000;
inst[1] |= target << 12;
reloc++;
}
}
upload_code = TRUE;
upload_data = TRUE;
}
if (vp->nr_consts) {
struct nv04_resource *res = nv04_resource(nv30->vertprog.constbuf);
for (i = 0; i < vp->nr_consts; i++) {
struct nv30_vertprog_data *data = &vp->consts[i];
if (data->index < 0) {
if (!upload_data)
continue;
} else {
float *constbuf = (float *)res->data;
if (!upload_data &&
!memcmp(data->value, &constbuf[data->index * 4], 16))
continue;
memcpy(data->value, &constbuf[data->index * 4], 16);
}
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 5);
PUSH_DATA (push, vp->data->start + i);
PUSH_DATAp(push, data->value, 4);
}
}
if (upload_code) {
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);
PUSH_DATA (push, vp->exec->start);
for (i = 0; i < vp->nr_insns; i++) {
BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
PUSH_DATAp(push, vp->insns[i].data, 4);
}
}
if (nv30->dirty & (NV30_NEW_VERTPROG | NV30_NEW_FRAGPROG)) {
BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
PUSH_DATA (push, vp->exec->start);
if (eng3d->oclass < NV40_3D_CLASS) {
BEGIN_NV04(push, NV30_3D(ENGINE), 1);
PUSH_DATA (push, 0x00000013); /* vp instead of ff, somehow */
} else {
BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
PUSH_DATA (push, vp->ir);
PUSH_DATA (push, vp->or | fp->vp_or);
BEGIN_NV04(push, NV30_3D(ENGINE), 1);
PUSH_DATA (push, 0x00000011);
}
}
}
static void *
nv30_vp_state_create(struct pipe_context *pipe,
const struct pipe_shader_state *cso)
{
struct nv30_vertprog *vp = CALLOC_STRUCT(nv30_vertprog);
if (!vp)
return NULL;
vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
tgsi_scan_shader(vp->pipe.tokens, &vp->info);
return vp;
}
static void
nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso)
{
struct nv30_vertprog *vp = hwcso;
if (vp->translated)
nv30_vertprog_destroy(vp);
FREE((void *)vp->pipe.tokens);
FREE(vp);
}
static void
nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv30_context *nv30 = nv30_context(pipe);
nv30->vertprog.program = hwcso;
nv30->dirty |= NV30_NEW_VERTPROG;
}
void
nv30_vertprog_init(struct pipe_context *pipe)
{
pipe->create_vs_state = nv30_vp_state_create;
pipe->bind_vs_state = nv30_vp_state_bind;
pipe->delete_vs_state = nv30_vp_state_delete;
}
+176
View File
@@ -0,0 +1,176 @@
#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
+158
View File
@@ -0,0 +1,158 @@
#ifndef __NV30_WINSYS_H__
#define __NV30_WINSYS_H__
#include <string.h>
#include "nouveau/nouveau_winsys.h"
#include "nouveau/nouveau_buffer.h"
/*XXX: rnn */
#define NV40_3D_VTXTEX_OFFSET(i) (0x0900 + ((i) * 0x20)) // 401e80
#define NV40_3D_VTXTEX_FORMAT(i) (0x0904 + ((i) * 0x20)) // 401e90
#define NV40_3D_VTXTEX_WRAP(i) (0x0908 + ((i) * 0x20)) // 401ea0
#define NV40_3D_VTXTEX_ENABLE(i) (0x090c + ((i) * 0x20)) // 401eb0
#define NV40_3D_VTXTEX_SWZ(i) (0x0910 + ((i) * 0x20)) // 401ec0
#define NV40_3D_VTXTEX_FILTER(i) (0x0914 + ((i) * 0x20)) // 401ed0
#define NV40_3D_VTXTEX_SIZE(i) (0x0918 + ((i) * 0x20)) // 401ee0
#define NV40_3D_VTXTEX_BCOL(i) (0x091c + ((i) * 0x20)) // 401ef0
#define NV30_3D_VTX_CACHE_INVALIDATE_1710 0x1710
#define NV30_3D_R1718 0x1718
#define NV40_3D_PRIM_RESTART_ENABLE 0x1dac
#define NV40_3D_PRIM_RESTART_INDEX 0x1db0
static INLINE void
PUSH_RELOC(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t offset,
uint32_t flags, uint32_t vor, uint32_t tor)
{
nouveau_pushbuf_reloc(push, bo, offset, flags, vor, tor);
}
static INLINE struct nouveau_bufctx *
bufctx(struct nouveau_pushbuf *push)
{
struct nouveau_bufctx **pctx = push->user_priv;
return *pctx;
}
static INLINE void
PUSH_RESET(struct nouveau_pushbuf *push, int bin)
{
nouveau_bufctx_reset(bufctx(push), bin);
}
static INLINE void
PUSH_REFN(struct nouveau_pushbuf *push, int bin,
struct nouveau_bo *bo, uint32_t access)
{
nouveau_bufctx_refn(bufctx(push), bin, bo, access);
}
static INLINE void
PUSH_MTHDl(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
struct nouveau_bo *bo, uint32_t offset, uint32_t access)
{
nouveau_bufctx_mthd(bufctx(push), bin, (1 << 18) | (subc << 13) | mthd,
bo, offset, access | NOUVEAU_BO_LOW, 0, 0)->priv = NULL;
PUSH_DATA(push, bo->offset + offset);
}
static INLINE void
PUSH_MTHDo(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
struct nouveau_bo *bo, uint32_t access, uint32_t vor, uint32_t tor)
{
nouveau_bufctx_mthd(bufctx(push), bin, (1 << 18) | (subc << 13) | mthd,
bo, 0, access | NOUVEAU_BO_OR, vor, tor)->priv = NULL;
if (bo->flags & NOUVEAU_BO_VRAM)
PUSH_DATA(push, vor);
else
PUSH_DATA(push, tor);
}
static INLINE void
PUSH_MTHDs(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
struct nouveau_bo *bo, uint32_t data, uint32_t access,
uint32_t vor, uint32_t tor)
{
nouveau_bufctx_mthd(bufctx(push), bin, (1 << 18) | (subc << 13) | mthd,
bo, data, access | NOUVEAU_BO_OR, vor, tor)->priv = NULL;
if (bo->flags & NOUVEAU_BO_VRAM)
PUSH_DATA(push, data | vor);
else
PUSH_DATA(push, data | tor);
}
static INLINE struct nouveau_bufref *
PUSH_MTHD(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
struct nouveau_bo *bo, uint32_t data, uint32_t access,
uint32_t vor, uint32_t tor)
{
struct nouveau_bufref *bref =
nouveau_bufctx_mthd(bufctx(push), bin, (1 << 18) | (subc << 13) | mthd,
bo, data, access | NOUVEAU_BO_OR, vor, tor);
if (access & NOUVEAU_BO_LOW)
data += bo->offset;
if (bo->flags & NOUVEAU_BO_VRAM)
data |= vor;
else
data |= tor;
PUSH_DATA(push, data);
bref->priv = NULL;
return bref;
}
static INLINE void
PUSH_RESRC(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
struct nv04_resource *r, uint32_t data, uint32_t access,
uint32_t vor, uint32_t tor)
{
PUSH_MTHD(push, subc, mthd, bin, r->bo, r->offset + data,
r->domain | access, vor, tor)->priv = r;
}
static INLINE void
BEGIN_NV04(struct nouveau_pushbuf *push, int subc, int mthd, int size)
{
PUSH_SPACE(push, size + 1);
PUSH_DATA (push, 0x00000000 | (size << 18) | (subc << 13) | mthd);
}
static INLINE void
BEGIN_NI04(struct nouveau_pushbuf *push, int subc, int mthd, int size)
{
PUSH_SPACE(push, size + 1);
PUSH_DATA (push, 0x40000000 | (size << 18) | (subc << 13) | mthd);
}
/* subchannel assignment
*
* 0: <1.0.0 - used by kernel for m2mf
* 1.0.0 - used by kernel for nvsw
*
* 1: <1.0.0 - used by kernel for nvsw
* 1.0.0 - free for userspace
*
* 2-7: free for userspace on all kernel versions
*/
#define SUBC_M2MF(mthd) 2, (mthd)
#define NV03_M2MF(mthd) SUBC_M2MF(NV03_M2MF_##mthd)
#define SUBC_SF2D(mthd) 3, (mthd)
#define NV04_SF2D(mthd) SUBC_SF2D(NV04_SURFACE_2D_##mthd)
#define SUBC_SSWZ(mthd) 4, (mthd)
#define NV04_SSWZ(mthd) SUBC_SSWZ(NV04_SURFACE_SWZ_##mthd)
#define SUBC_SIFM(mthd) 5, (mthd)
#define NV03_SIFM(mthd) SUBC_SIFM(NV03_SIFM_##mthd)
#define NV05_SIFM(mthd) SUBC_SIFM(NV05_SIFM_##mthd)
#define SUBC_3D(mthd) 7, (mthd)
#define NV30_3D(mthd) SUBC_3D(NV30_3D_##mthd)
#define NV40_3D(mthd) SUBC_3D(NV40_3D_##mthd)
#define NV01_SUBC(subc, mthd) SUBC_##subc((NV01_SUBCHAN_##mthd))
#define NV11_SUBC(subc, mthd) SUBC_##subc((NV11_SUBCHAN_##mthd))
#define NV04_GRAPH(subc, mthd) SUBC_##subc((NV04_GRAPH_##mthd))
#endif
+178
View File
@@ -0,0 +1,178 @@
#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
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright 2012 Red Hat 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Ben Skeggs
*
*/
#include "util/u_inlines.h"
#include "nv30_context.h"
void
nv40_verttex_validate(struct nv30_context *nv30)
{
struct nouveau_pushbuf *push = nv30->base.pushbuf;
unsigned dirty = nv30->vertprog.dirty_samplers;
while (dirty) {
unsigned unit = ffs(dirty) - 1;
struct nv30_sampler_view *sv = (void *)nv30->fragprog.textures[unit];
struct nv30_sampler_state *ss = nv30->fragprog.samplers[unit];
if (ss && sv) {
} else {
BEGIN_NV04(push, NV40_3D(VTXTEX_ENABLE(unit)), 1);
PUSH_DATA (push, 0);
}
}
nv30->vertprog.dirty_samplers = 0;
}
static void
nv40_verttex_sampler_states_bind(struct pipe_context *pipe,
unsigned nr, void **hwcso)
{
struct nv30_context *nv30 = nv30_context(pipe);
unsigned i;
for (i = 0; i < nr; i++) {
nv30->vertprog.samplers[i] = hwcso[i];
nv30->vertprog.dirty_samplers |= (1 << i);
}
for (; i < nv30->vertprog.num_samplers; i++) {
nv30->vertprog.samplers[i] = NULL;
nv30->vertprog.dirty_samplers |= (1 << i);
}
nv30->vertprog.num_samplers = nr;
nv30->dirty |= NV30_NEW_VERTTEX;
}
static void
nv40_verttex_set_sampler_views(struct pipe_context *pipe, unsigned nr,
struct pipe_sampler_view **views)
{
struct nv30_context *nv30 = nv30_context(pipe);
unsigned i;
for (i = 0; i < nr; i++) {
nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VERTTEX(i));
pipe_sampler_view_reference(&nv30->vertprog.textures[i], views[i]);
nv30->vertprog.dirty_samplers |= (1 << i);
}
for (; i < nv30->vertprog.num_textures; i++) {
nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VERTTEX(i));
pipe_sampler_view_reference(&nv30->vertprog.textures[i], NULL);
nv30->vertprog.dirty_samplers |= (1 << i);
}
nv30->vertprog.num_textures = nr;
nv30->dirty |= NV30_NEW_VERTTEX;
}
void
nv40_verttex_init(struct pipe_context *pipe)
{
pipe->bind_vertex_sampler_states = nv40_verttex_sampler_states_bind;
pipe->set_vertex_sampler_views = nv40_verttex_set_sampler_views;
}
File diff suppressed because it is too large Load Diff
+525
View File
@@ -0,0 +1,525 @@
#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) + (nv30->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 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
File diff suppressed because it is too large Load Diff
-2
View File
@@ -27,8 +27,6 @@
#include "nv50_screen.h"
#include "nv50_resource.h"
#include "nouveau/nouveau_reloc.h"
static void
nv50_flush(struct pipe_context *pipe,
struct pipe_fence_handle **fence)
+1
View File
@@ -8,6 +8,7 @@ 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/nv30/libnv30.a \
$(TOP)/src/gallium/drivers/nv50/libnv50.a \
$(TOP)/src/gallium/drivers/nvc0/libnvc0.a \
$(TOP)/src/gallium/drivers/nouveau/libnouveau.a
@@ -7,6 +7,7 @@ DRIVER_INCLUDES = $(shell $(PKG_CONFIG) libdrm --cflags-only-I)
PIPE_DRIVERS = \
$(TOP)/src/gallium/winsys/nouveau/drm/libnouveaudrm.a \
$(TOP)/src/gallium/drivers/nv30/libnv30.a \
$(TOP)/src/gallium/drivers/nv50/libnv50.a \
$(TOP)/src/gallium/drivers/nvc0/libnvc0.a \
$(TOP)/src/gallium/drivers/nouveau/libnouveau.a \
@@ -13,6 +13,7 @@ DRIVER_DEFINES = \
DRIVER_PIPES = \
$(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \
$(TOP)/src/gallium/winsys/nouveau/drm/libnouveaudrm.a \
$(TOP)/src/gallium/drivers/nv30/libnv30.a \
$(TOP)/src/gallium/drivers/nv50/libnv50.a \
$(TOP)/src/gallium/drivers/nvc0/libnvc0.a \
$(TOP)/src/gallium/drivers/nouveau/libnouveau.a \
@@ -21,13 +21,11 @@ nouveau_drm_screen_create(int fd)
return NULL;
switch (dev->chipset & 0xf0) {
#if 0
case 0x30:
case 0x40:
case 0x60:
init = nv30_screen_create;
break;
#endif
case 0x50:
case 0x80:
case 0x90: