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:
+1
-1
@@ -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)
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 _
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user