mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-16 22:20:29 +01:00
nv50: replace most of it with nvc0 driver ported to nv50
We'll have to do some unification now to reduce code duplication.
This commit is contained in:
parent
d1dbbf7bf4
commit
f80c03e187
41 changed files with 8740 additions and 6536 deletions
|
|
@ -5,12 +5,10 @@ LIBNAME = nv50
|
|||
|
||||
C_SOURCES = \
|
||||
nv50_buffer.c \
|
||||
nv50_clear.c \
|
||||
nv50_context.c \
|
||||
nv50_draw.c \
|
||||
nv50_formats.c \
|
||||
nv50_miptree.c \
|
||||
nv50_query.c \
|
||||
nv50_resource.c \
|
||||
nv50_screen.c \
|
||||
nv50_state.c \
|
||||
|
|
@ -19,7 +17,6 @@ C_SOURCES = \
|
|||
nv50_tex.c \
|
||||
nv50_transfer.c \
|
||||
nv50_vbo.c \
|
||||
nv50_push.c \
|
||||
nv50_program.c \
|
||||
nv50_shader_state.c \
|
||||
nv50_pc.c \
|
||||
|
|
@ -27,7 +24,11 @@ C_SOURCES = \
|
|||
nv50_pc_emit.c \
|
||||
nv50_tgsi_to_nc.c \
|
||||
nv50_pc_optimize.c \
|
||||
nv50_pc_regalloc.c
|
||||
nv50_pc_regalloc.c \
|
||||
nv50_push.c \
|
||||
nv50_fence.c \
|
||||
nv50_mm.c \
|
||||
nv50_query.c
|
||||
|
||||
LIBRARY_INCLUDES = \
|
||||
$(LIBDRM_CFLAGS)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,10 @@ nv50 = env.ConvenienceLibrary(
|
|||
target = 'nv50',
|
||||
source = [
|
||||
'nv50_buffer.c',
|
||||
'nv50_clear.c',
|
||||
'nv50_context.c',
|
||||
'nv50_draw.c',
|
||||
'nv50_formats.c',
|
||||
'nv50_miptree.c',
|
||||
'nv50_query.c',
|
||||
'nv50_resource.c',
|
||||
'nv50_screen.c',
|
||||
'nv50_state.c',
|
||||
|
|
@ -20,7 +18,6 @@ nv50 = env.ConvenienceLibrary(
|
|||
'nv50_tex.c',
|
||||
'nv50_transfer.c',
|
||||
'nv50_vbo.c',
|
||||
'nv50_push.c',
|
||||
'nv50_program.c',
|
||||
'nv50_shader_state.c',
|
||||
'nv50_pc.c',
|
||||
|
|
@ -29,6 +26,11 @@ nv50 = env.ConvenienceLibrary(
|
|||
'nv50_tgsi_to_nc.c',
|
||||
'nv50_pc_optimize.c',
|
||||
'nv50_pc_regalloc.c',
|
||||
'nv50_push.c',
|
||||
'nv50_push2.c',
|
||||
'nv50_fence.c',
|
||||
'nv50_mm.c',
|
||||
'nv50_query.c'
|
||||
])
|
||||
|
||||
Export('nv50')
|
||||
|
|
|
|||
393
src/gallium/drivers/nv50/nv50_2d.xml.h
Normal file
393
src/gallium/drivers/nv50/nv50_2d.xml.h
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
#ifndef NV50_2D_XML
|
||||
#define NV50_2D_XML
|
||||
|
||||
/* Autogenerated file, DO NOT EDIT manually!
|
||||
|
||||
This file was generated by the rules-ng-ng headergen tool in this git repository:
|
||||
http://0x04.net/cgit/index.cgi/rules-ng-ng
|
||||
git clone git://0x04.net/rules-ng-ng
|
||||
|
||||
The rules-ng-ng source files this header was generated from are:
|
||||
- nv50_2d.xml ( 9799 bytes, from 2010-12-28 17:17:11)
|
||||
- copyright.xml ( 6452 bytes, from 2010-12-15 23:45:18)
|
||||
- nv_object.xml ( 11898 bytes, from 2010-12-28 17:17:11)
|
||||
- nvchipsets.xml ( 3074 bytes, from 2010-12-15 23:45:18)
|
||||
- nv_defs.xml ( 4437 bytes, from 2010-12-15 23:45:18)
|
||||
- nv50_defs.xml ( 4487 bytes, from 2010-12-15 23:45:18)
|
||||
|
||||
Copyright (C) 2006-2010 by the following authors:
|
||||
- Artur Huillet <arthur.huillet@free.fr> (ahuillet)
|
||||
- Ben Skeggs (darktama, darktama_)
|
||||
- B. R. <koala_br@users.sourceforge.net> (koala_br)
|
||||
- Carlos Martin <carlosmn@users.sf.net> (carlosmn)
|
||||
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr)
|
||||
- Dawid Gajownik <gajownik@users.sf.net> (gajownik)
|
||||
- Dmitry Baryshkov
|
||||
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag)
|
||||
- EdB <edb_@users.sf.net> (edb_)
|
||||
- Erik Waling <erikwailing@users.sf.net> (erikwaling)
|
||||
- Francisco Jerez <currojerez@riseup.net> (curro)
|
||||
- imirkin <imirkin@users.sf.net> (imirkin)
|
||||
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome)
|
||||
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy)
|
||||
- Laurent Carlier <lordheavym@gmail.com> (lordheavy)
|
||||
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1)
|
||||
- Maarten Maathuis <madman2003@gmail.com> (stillunknown)
|
||||
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin)
|
||||
- Mark Carey <mark.carey@gmail.com> (careym)
|
||||
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c)
|
||||
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman)
|
||||
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata)
|
||||
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen)
|
||||
- Peter Popov <ironpeter@users.sf.net> (ironpeter)
|
||||
- Richard Hughes <hughsient@users.sf.net> (hughsient)
|
||||
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar)
|
||||
- Serge Martin
|
||||
- Simon Raffeiner
|
||||
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier)
|
||||
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu)
|
||||
- sturmflut <sturmflut@users.sf.net> (sturmflut)
|
||||
- Sylvain Munaut <tnt@246tNt.com>
|
||||
- Victor Stinner <victor.stinner@haypocalc.com> (haypo)
|
||||
- Wladmir van der Laan <laanwj@gmail.com> (miathan6)
|
||||
- Younes Manton <younes.m@gmail.com> (ymanton)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the
|
||||
next paragraph) shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#define NV50_2D_DMA_NOTIFY 0x00000180
|
||||
|
||||
#define NV50_2D_DMA_DST 0x00000184
|
||||
|
||||
#define NV50_2D_DMA_SRC 0x00000188
|
||||
|
||||
#define NV50_2D_DMA_COND 0x0000018c
|
||||
|
||||
#define NV50_2D_DST_FORMAT 0x00000200
|
||||
|
||||
#define NV50_2D_DST_LINEAR 0x00000204
|
||||
|
||||
#define NV50_2D_DST_TILE_MODE 0x00000208
|
||||
|
||||
#define NV50_2D_DST_DEPTH 0x0000020c
|
||||
|
||||
#define NV50_2D_DST_LAYER 0x00000210
|
||||
|
||||
#define NV50_2D_DST_PITCH 0x00000214
|
||||
|
||||
#define NV50_2D_DST_WIDTH 0x00000218
|
||||
|
||||
#define NV50_2D_DST_HEIGHT 0x0000021c
|
||||
|
||||
#define NV50_2D_DST_ADDRESS_HIGH 0x00000220
|
||||
|
||||
#define NV50_2D_DST_ADDRESS_LOW 0x00000224
|
||||
|
||||
#define NV50_2D_UNK228 0x00000228
|
||||
|
||||
#define NV50_2D_SRC_FORMAT 0x00000230
|
||||
|
||||
#define NV50_2D_SRC_LINEAR 0x00000234
|
||||
|
||||
#define NV50_2D_SRC_TILE_MODE 0x00000238
|
||||
|
||||
#define NV50_2D_SRC_DEPTH 0x0000023c
|
||||
|
||||
#define NV50_2D_SRC_LAYER 0x00000240
|
||||
|
||||
#define NV50_2D_SRC_PITCH 0x00000244
|
||||
#define NV50_2D_SRC_PITCH__MAX 0x00040000
|
||||
|
||||
#define NV50_2D_SRC_WIDTH 0x00000248
|
||||
#define NV50_2D_SRC_WIDTH__MAX 0x00010000
|
||||
|
||||
#define NV50_2D_SRC_HEIGHT 0x0000024c
|
||||
#define NV50_2D_SRC_HEIGHT__MAX 0x00010000
|
||||
|
||||
#define NV50_2D_SRC_ADDRESS_HIGH 0x00000250
|
||||
|
||||
#define NV50_2D_SRC_ADDRESS_LOW 0x00000254
|
||||
|
||||
#define NV50_2D_UNK258 0x00000258
|
||||
|
||||
#define NV50_2D_UNK260 0x00000260
|
||||
|
||||
#define NV50_2D_COND_ADDRESS_HIGH 0x00000264
|
||||
|
||||
#define NV50_2D_COND_ADDRESS_LOW 0x00000268
|
||||
|
||||
#define NV50_2D_COND_MODE 0x0000026c
|
||||
#define NV50_2D_COND_MODE_NEVER 0x00000000
|
||||
#define NV50_2D_COND_MODE_ALWAYS 0x00000001
|
||||
#define NV50_2D_COND_MODE_RES_NON_ZERO 0x00000002
|
||||
#define NV50_2D_COND_MODE_EQUAL 0x00000003
|
||||
#define NV50_2D_COND_MODE_NOT_EQUAL 0x00000004
|
||||
|
||||
#define NV50_2D_CLIP_X 0x00000280
|
||||
|
||||
#define NV50_2D_CLIP_Y 0x00000284
|
||||
|
||||
#define NV50_2D_CLIP_W 0x00000288
|
||||
|
||||
#define NV50_2D_CLIP_H 0x0000028c
|
||||
|
||||
#define NV50_2D_CLIP_ENABLE 0x00000290
|
||||
|
||||
#define NV50_2D_COLOR_KEY_FORMAT 0x00000294
|
||||
#define NV50_2D_COLOR_KEY_FORMAT_16BPP 0x00000000
|
||||
#define NV50_2D_COLOR_KEY_FORMAT_15BPP 0x00000001
|
||||
#define NV50_2D_COLOR_KEY_FORMAT_24BPP 0x00000002
|
||||
#define NV50_2D_COLOR_KEY_FORMAT_30BPP 0x00000003
|
||||
#define NV50_2D_COLOR_KEY_FORMAT_8BPP 0x00000004
|
||||
#define NV50_2D_COLOR_KEY_FORMAT_16BPP2 0x00000005
|
||||
#define NV50_2D_COLOR_KEY_FORMAT_32BPP 0x00000006
|
||||
|
||||
#define NV50_2D_COLOR_KEY 0x00000298
|
||||
|
||||
#define NV50_2D_COLOR_KEY_ENABLE 0x0000029c
|
||||
|
||||
#define NV50_2D_ROP 0x000002a0
|
||||
|
||||
#define NV50_2D_BETA1 0x000002a4
|
||||
|
||||
#define NV50_2D_BETA4 0x000002a8
|
||||
|
||||
#define NV50_2D_OPERATION 0x000002ac
|
||||
#define NV50_2D_OPERATION_SRCCOPY_AND 0x00000000
|
||||
#define NV50_2D_OPERATION_ROP_AND 0x00000001
|
||||
#define NV50_2D_OPERATION_BLEND_AND 0x00000002
|
||||
#define NV50_2D_OPERATION_SRCCOPY 0x00000003
|
||||
#define NV50_2D_OPERATION_UNK4 0x00000004
|
||||
#define NV50_2D_OPERATION_SRCCOPY_PREMULT 0x00000005
|
||||
#define NV50_2D_OPERATION_BLEND_PREMULT 0x00000006
|
||||
|
||||
#define NV50_2D_UNK2B0 0x000002b0
|
||||
#define NV50_2D_UNK2B0_UNK0__MASK 0x0000003f
|
||||
#define NV50_2D_UNK2B0_UNK0__SHIFT 0
|
||||
#define NV50_2D_UNK2B0_UNK1__MASK 0x00003f00
|
||||
#define NV50_2D_UNK2B0_UNK1__SHIFT 8
|
||||
|
||||
#define NV50_2D_PATTERN_SELECT 0x000002b4
|
||||
#define NV50_2D_PATTERN_SELECT_MONO_8X8 0x00000000
|
||||
#define NV50_2D_PATTERN_SELECT_MONO_64X1 0x00000001
|
||||
#define NV50_2D_PATTERN_SELECT_MONO_1X64 0x00000002
|
||||
#define NV50_2D_PATTERN_SELECT_COLOR 0x00000003
|
||||
|
||||
#define NV50_2D_PATTERN_COLOR_FORMAT 0x000002e8
|
||||
#define NV50_2D_PATTERN_COLOR_FORMAT_16BPP 0x00000000
|
||||
#define NV50_2D_PATTERN_COLOR_FORMAT_15BPP 0x00000001
|
||||
#define NV50_2D_PATTERN_COLOR_FORMAT_32BPP 0x00000002
|
||||
#define NV50_2D_PATTERN_COLOR_FORMAT_8BPP 0x00000003
|
||||
#define NV50_2D_PATTERN_COLOR_FORMAT_UNK4 0x00000004
|
||||
#define NV50_2D_PATTERN_COLOR_FORMAT_UNK5 0x00000005
|
||||
|
||||
#define NV50_2D_PATTERN_MONO_FORMAT 0x000002ec
|
||||
#define NV50_2D_PATTERN_MONO_FORMAT_CGA6 0x00000000
|
||||
#define NV50_2D_PATTERN_MONO_FORMAT_LE 0x00000001
|
||||
|
||||
#define NV50_2D_PATTERN_COLOR(i0) (0x000002f0 + 0x4*(i0))
|
||||
#define NV50_2D_PATTERN_COLOR__ESIZE 0x00000004
|
||||
#define NV50_2D_PATTERN_COLOR__LEN 0x00000002
|
||||
|
||||
#define NV50_2D_PATTERN_BITMAP(i0) (0x000002f8 + 0x4*(i0))
|
||||
#define NV50_2D_PATTERN_BITMAP__ESIZE 0x00000004
|
||||
#define NV50_2D_PATTERN_BITMAP__LEN 0x00000002
|
||||
|
||||
#define NV50_2D_PATTERN_X8R8G8B8(i0) (0x00000300 + 0x4*(i0))
|
||||
#define NV50_2D_PATTERN_X8R8G8B8__ESIZE 0x00000004
|
||||
#define NV50_2D_PATTERN_X8R8G8B8__LEN 0x00000040
|
||||
#define NV50_2D_PATTERN_X8R8G8B8_B__MASK 0x000000ff
|
||||
#define NV50_2D_PATTERN_X8R8G8B8_B__SHIFT 0
|
||||
#define NV50_2D_PATTERN_X8R8G8B8_G__MASK 0x0000ff00
|
||||
#define NV50_2D_PATTERN_X8R8G8B8_G__SHIFT 8
|
||||
#define NV50_2D_PATTERN_X8R8G8B8_R__MASK 0x00ff0000
|
||||
#define NV50_2D_PATTERN_X8R8G8B8_R__SHIFT 16
|
||||
|
||||
#define NV50_2D_PATTERN_R5G6B5(i0) (0x00000400 + 0x4*(i0))
|
||||
#define NV50_2D_PATTERN_R5G6B5__ESIZE 0x00000004
|
||||
#define NV50_2D_PATTERN_R5G6B5__LEN 0x00000020
|
||||
#define NV50_2D_PATTERN_R5G6B5_B0__MASK 0x0000001f
|
||||
#define NV50_2D_PATTERN_R5G6B5_B0__SHIFT 0
|
||||
#define NV50_2D_PATTERN_R5G6B5_G0__MASK 0x000007e0
|
||||
#define NV50_2D_PATTERN_R5G6B5_G0__SHIFT 5
|
||||
#define NV50_2D_PATTERN_R5G6B5_R0__MASK 0x0000f800
|
||||
#define NV50_2D_PATTERN_R5G6B5_R0__SHIFT 11
|
||||
#define NV50_2D_PATTERN_R5G6B5_B1__MASK 0x001f0000
|
||||
#define NV50_2D_PATTERN_R5G6B5_B1__SHIFT 16
|
||||
#define NV50_2D_PATTERN_R5G6B5_G1__MASK 0x07e00000
|
||||
#define NV50_2D_PATTERN_R5G6B5_G1__SHIFT 21
|
||||
#define NV50_2D_PATTERN_R5G6B5_R1__MASK 0xf8000000
|
||||
#define NV50_2D_PATTERN_R5G6B5_R1__SHIFT 27
|
||||
|
||||
#define NV50_2D_PATTERN_X1R5G5B5(i0) (0x00000480 + 0x4*(i0))
|
||||
#define NV50_2D_PATTERN_X1R5G5B5__ESIZE 0x00000004
|
||||
#define NV50_2D_PATTERN_X1R5G5B5__LEN 0x00000020
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_B0__MASK 0x0000001f
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_B0__SHIFT 0
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_G0__MASK 0x000003e0
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_G0__SHIFT 5
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_R0__MASK 0x00007c00
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_R0__SHIFT 10
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_B1__MASK 0x001f0000
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_B1__SHIFT 16
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_G1__MASK 0x03e00000
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_G1__SHIFT 21
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_R1__MASK 0x7c000000
|
||||
#define NV50_2D_PATTERN_X1R5G5B5_R1__SHIFT 26
|
||||
|
||||
#define NV50_2D_PATTERN_Y8(i0) (0x00000500 + 0x4*(i0))
|
||||
#define NV50_2D_PATTERN_Y8__ESIZE 0x00000004
|
||||
#define NV50_2D_PATTERN_Y8__LEN 0x00000010
|
||||
#define NV50_2D_PATTERN_Y8_Y0__MASK 0x000000ff
|
||||
#define NV50_2D_PATTERN_Y8_Y0__SHIFT 0
|
||||
#define NV50_2D_PATTERN_Y8_Y1__MASK 0x0000ff00
|
||||
#define NV50_2D_PATTERN_Y8_Y1__SHIFT 8
|
||||
#define NV50_2D_PATTERN_Y8_Y2__MASK 0x00ff0000
|
||||
#define NV50_2D_PATTERN_Y8_Y2__SHIFT 16
|
||||
#define NV50_2D_PATTERN_Y8_Y3__MASK 0xff000000
|
||||
#define NV50_2D_PATTERN_Y8_Y3__SHIFT 24
|
||||
|
||||
#define NV50_2D_DRAW_SHAPE 0x00000580
|
||||
#define NV50_2D_DRAW_SHAPE_POINTS 0x00000000
|
||||
#define NV50_2D_DRAW_SHAPE_LINES 0x00000001
|
||||
#define NV50_2D_DRAW_SHAPE_LINE_STRIP 0x00000002
|
||||
#define NV50_2D_DRAW_SHAPE_TRIANGLES 0x00000003
|
||||
#define NV50_2D_DRAW_SHAPE_RECTANGLES 0x00000004
|
||||
|
||||
#define NV50_2D_DRAW_COLOR_FORMAT 0x00000584
|
||||
|
||||
#define NV50_2D_DRAW_COLOR 0x00000588
|
||||
|
||||
#define NV50_2D_UNK58C 0x0000058c
|
||||
#define NV50_2D_UNK58C_0 0x00000001
|
||||
#define NV50_2D_UNK58C_1 0x00000010
|
||||
#define NV50_2D_UNK58C_2 0x00000100
|
||||
#define NV50_2D_UNK58C_3 0x00001000
|
||||
|
||||
#define NV50_2D_DRAW_POINT16 0x000005e0
|
||||
#define NV50_2D_DRAW_POINT16_X__MASK 0x0000ffff
|
||||
#define NV50_2D_DRAW_POINT16_X__SHIFT 0
|
||||
#define NV50_2D_DRAW_POINT16_Y__MASK 0xffff0000
|
||||
#define NV50_2D_DRAW_POINT16_Y__SHIFT 16
|
||||
|
||||
#define NV50_2D_DRAW_POINT32_X(i0) (0x00000600 + 0x8*(i0))
|
||||
#define NV50_2D_DRAW_POINT32_X__ESIZE 0x00000008
|
||||
#define NV50_2D_DRAW_POINT32_X__LEN 0x00000040
|
||||
|
||||
#define NV50_2D_DRAW_POINT32_Y(i0) (0x00000604 + 0x8*(i0))
|
||||
#define NV50_2D_DRAW_POINT32_Y__ESIZE 0x00000008
|
||||
#define NV50_2D_DRAW_POINT32_Y__LEN 0x00000040
|
||||
|
||||
#define NV50_2D_SIFC_BITMAP_ENABLE 0x00000800
|
||||
|
||||
#define NV50_2D_SIFC_FORMAT 0x00000804
|
||||
|
||||
#define NV50_2D_SIFC_BITMAP_FORMAT 0x00000808
|
||||
#define NV50_2D_SIFC_BITMAP_FORMAT_I1 0x00000000
|
||||
#define NV50_2D_SIFC_BITMAP_FORMAT_I4 0x00000001
|
||||
#define NV50_2D_SIFC_BITMAP_FORMAT_I8 0x00000002
|
||||
|
||||
#define NV50_2D_SIFC_BITMAP_LSB_FIRST 0x0000080c
|
||||
|
||||
#define NV50_2D_SIFC_BITMAP_LINE_PACK_MODE 0x00000810
|
||||
#define NV50_2D_SIFC_BITMAP_LINE_PACK_MODE_PACKED 0x00000000
|
||||
#define NV50_2D_SIFC_BITMAP_LINE_PACK_MODE_ALIGN_BYTE 0x00000001
|
||||
#define NV50_2D_SIFC_BITMAP_LINE_PACK_MODE_ALIGN_WORD 0x00000002
|
||||
|
||||
#define NV50_2D_SIFC_BITMAP_COLOR_BIT0 0x00000814
|
||||
|
||||
#define NV50_2D_SIFC_BITMAP_COLOR_BIT1 0x00000818
|
||||
|
||||
#define NV50_2D_SIFC_BITMAP_WRITE_BIT0_ENABLE 0x0000081c
|
||||
|
||||
#define NV50_2D_SIFC_WIDTH 0x00000838
|
||||
|
||||
#define NV50_2D_SIFC_HEIGHT 0x0000083c
|
||||
|
||||
#define NV50_2D_SIFC_DX_DU_FRACT 0x00000840
|
||||
|
||||
#define NV50_2D_SIFC_DX_DU_INT 0x00000844
|
||||
|
||||
#define NV50_2D_SIFC_DY_DV_FRACT 0x00000848
|
||||
|
||||
#define NV50_2D_SIFC_DY_DV_INT 0x0000084c
|
||||
|
||||
#define NV50_2D_SIFC_DST_X_FRACT 0x00000850
|
||||
|
||||
#define NV50_2D_SIFC_DST_X_INT 0x00000854
|
||||
|
||||
#define NV50_2D_SIFC_DST_Y_FRACT 0x00000858
|
||||
|
||||
#define NV50_2D_SIFC_DST_Y_INT 0x0000085c
|
||||
|
||||
#define NV50_2D_SIFC_DATA 0x00000860
|
||||
|
||||
#define NV50_2D_UNK0870 0x00000870
|
||||
|
||||
#define NV50_2D_UNK0880 0x00000880
|
||||
|
||||
#define NV50_2D_UNK0884 0x00000884
|
||||
|
||||
#define NV50_2D_UNK0888 0x00000888
|
||||
|
||||
#define NV50_2D_BLIT_CONTROL 0x0000088c
|
||||
#define NV50_2D_BLIT_CONTROL_ORIGIN__MASK 0x00000001
|
||||
#define NV50_2D_BLIT_CONTROL_ORIGIN__SHIFT 0
|
||||
#define NV50_2D_BLIT_CONTROL_ORIGIN_CENTER 0x00000000
|
||||
#define NV50_2D_BLIT_CONTROL_ORIGIN_CORNER 0x00000001
|
||||
#define NV50_2D_BLIT_CONTROL_FILTER__MASK 0x00000010
|
||||
#define NV50_2D_BLIT_CONTROL_FILTER__SHIFT 4
|
||||
#define NV50_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE 0x00000000
|
||||
#define NV50_2D_BLIT_CONTROL_FILTER_BILINEAR 0x00000010
|
||||
|
||||
#define NV50_2D_BLIT_DST_X 0x000008b0
|
||||
|
||||
#define NV50_2D_BLIT_DST_Y 0x000008b4
|
||||
|
||||
#define NV50_2D_BLIT_DST_W 0x000008b8
|
||||
|
||||
#define NV50_2D_BLIT_DST_H 0x000008bc
|
||||
|
||||
#define NV50_2D_BLIT_DU_DX_FRACT 0x000008c0
|
||||
|
||||
#define NV50_2D_BLIT_DU_DX_INT 0x000008c4
|
||||
|
||||
#define NV50_2D_BLIT_DV_DY_FRACT 0x000008c8
|
||||
|
||||
#define NV50_2D_BLIT_DV_DY_INT 0x000008cc
|
||||
|
||||
#define NV50_2D_BLIT_SRC_X_FRACT 0x000008d0
|
||||
|
||||
#define NV50_2D_BLIT_SRC_X_INT 0x000008d4
|
||||
|
||||
#define NV50_2D_BLIT_SRC_Y_FRACT 0x000008d8
|
||||
|
||||
#define NV50_2D_BLIT_SRC_Y_INT 0x000008dc
|
||||
|
||||
#define NVC0_2D_FIRMWARE(i0) (0x000008e0 + 0x4*(i0))
|
||||
#define NVC0_2D_FIRMWARE__ESIZE 0x00000004
|
||||
#define NVC0_2D_FIRMWARE__LEN 0x00000020
|
||||
|
||||
|
||||
#endif /* NV50_2D_XML */
|
||||
2084
src/gallium/drivers/nv50/nv50_3d.xml.h
Normal file
2084
src/gallium/drivers/nv50/nv50_3d.xml.h
Normal file
File diff suppressed because it is too large
Load diff
98
src/gallium/drivers/nv50/nv50_3ddefs.xml.h
Normal file
98
src/gallium/drivers/nv50/nv50_3ddefs.xml.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#ifndef NV_3DDEFS_XML
|
||||
#define NV_3DDEFS_XML
|
||||
|
||||
/* Autogenerated file, DO NOT EDIT manually!
|
||||
|
||||
This file was generated by the rules-ng-ng headergen tool in this git repository:
|
||||
http://0x04.net/cgit/index.cgi/rules-ng-ng
|
||||
git clone git://0x04.net/rules-ng-ng
|
||||
|
||||
The rules-ng-ng source files this header was generated from are:
|
||||
- nv50_3d.xml ( 26312 bytes, from 2010-10-08 10:10:01)
|
||||
- copyright.xml ( 6498 bytes, from 2010-10-03 13:18:37)
|
||||
- nv_defs.xml ( 4437 bytes, from 2010-07-06 07:43:58)
|
||||
- nv_3ddefs.xml ( 16397 bytes, from 2010-10-08 13:30:38)
|
||||
- nv_object.xml ( 11249 bytes, from 2010-10-07 15:31:28)
|
||||
- nvchipsets.xml ( 2824 bytes, from 2010-07-07 13:41:20)
|
||||
- nv50_defs.xml ( 4482 bytes, from 2010-10-03 13:18:37)
|
||||
|
||||
Copyright (C) 2006-2010 by the following authors:
|
||||
- Artur Huillet <arthur.huillet@free.fr> (ahuillet)
|
||||
- Ben Skeggs (darktama, darktama_)
|
||||
- B. R. <koala_br@users.sourceforge.net> (koala_br)
|
||||
- Carlos Martin <carlosmn@users.sf.net> (carlosmn)
|
||||
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr)
|
||||
- Dawid Gajownik <gajownik@users.sf.net> (gajownik)
|
||||
- Dmitry Baryshkov
|
||||
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag)
|
||||
- EdB <edb_@users.sf.net> (edb_)
|
||||
- Erik Waling <erikwailing@users.sf.net> (erikwaling)
|
||||
- Francisco Jerez <currojerez@riseup.net> (curro, curro_, currojerez)
|
||||
- imirkin <imirkin@users.sf.net> (imirkin)
|
||||
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome)
|
||||
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy)
|
||||
- Laurent Carlier <lordheavym@gmail.com> (lordheavy)
|
||||
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1)
|
||||
- Maarten Maathuis <madman2003@gmail.com> (stillunknown)
|
||||
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin)
|
||||
- Mark Carey <mark.carey@gmail.com> (careym)
|
||||
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c)
|
||||
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman)
|
||||
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata)
|
||||
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen)
|
||||
- Peter Popov <ironpeter@users.sf.net> (ironpeter)
|
||||
- Richard Hughes <hughsient@users.sf.net> (hughsient)
|
||||
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar)
|
||||
- Serge Martin
|
||||
- Simon Raffeiner
|
||||
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier)
|
||||
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu)
|
||||
- sturmflut <sturmflut@users.sf.net> (sturmflut)
|
||||
- Sylvain Munaut <tnt@246tNt.com>
|
||||
- Victor Stinner <victor.stinner@haypocalc.com> (haypo)
|
||||
- Wladmir van der Laan <laanwj@gmail.com> (miathan6)
|
||||
- Younes Manton <younes.m@gmail.com> (ymanton)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the
|
||||
next paragraph) shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#define NV50_3D_BLEND_FACTOR_ZERO 0x00004000
|
||||
#define NV50_3D_BLEND_FACTOR_ONE 0x00004001
|
||||
#define NV50_3D_BLEND_FACTOR_SRC_COLOR 0x00004300
|
||||
#define NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC_COLOR 0x00004301
|
||||
#define NV50_3D_BLEND_FACTOR_SRC_ALPHA 0x00004302
|
||||
#define NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA 0x00004303
|
||||
#define NV50_3D_BLEND_FACTOR_DST_ALPHA 0x00004304
|
||||
#define NV50_3D_BLEND_FACTOR_ONE_MINUS_DST_ALPHA 0x00004305
|
||||
#define NV50_3D_BLEND_FACTOR_DST_COLOR 0x00004306
|
||||
#define NV50_3D_BLEND_FACTOR_ONE_MINUS_DST_COLOR 0x00004307
|
||||
#define NV50_3D_BLEND_FACTOR_SRC_ALPHA_SATURATE 0x00004308
|
||||
#define NV50_3D_BLEND_FACTOR_CONSTANT_COLOR 0x0000c001
|
||||
#define NV50_3D_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR 0x0000c002
|
||||
#define NV50_3D_BLEND_FACTOR_CONSTANT_ALPHA 0x0000c003
|
||||
#define NV50_3D_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA 0x0000c004
|
||||
#define NV50_3D_BLEND_FACTOR_SRC1_COLOR 0x0000c900
|
||||
#define NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR 0x0000c901
|
||||
#define NV50_3D_BLEND_FACTOR_SRC1_ALPHA 0x0000c902
|
||||
#define NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA 0x0000c903
|
||||
|
||||
#endif /* NV_3DDEFS_XML */
|
||||
|
|
@ -3,149 +3,492 @@
|
|||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#define NOUVEAU_NVC0
|
||||
#include "nouveau/nouveau_screen.h"
|
||||
#include "nouveau/nouveau_winsys.h"
|
||||
#undef NOUVEAU_NVC0
|
||||
|
||||
#include "nv50_context.h"
|
||||
#include "nv50_resource.h"
|
||||
|
||||
struct nv50_transfer {
|
||||
struct pipe_transfer base;
|
||||
};
|
||||
|
||||
|
||||
static void nv50_buffer_destroy(struct pipe_screen *pscreen,
|
||||
struct pipe_resource *presource)
|
||||
static INLINE struct nv50_transfer *
|
||||
nv50_transfer(struct pipe_transfer *transfer)
|
||||
{
|
||||
struct nv50_resource *buffer = nv50_resource(presource);
|
||||
|
||||
nouveau_screen_bo_release(pscreen, buffer->bo);
|
||||
FREE(buffer);
|
||||
return (struct nv50_transfer *)transfer;
|
||||
}
|
||||
|
||||
static INLINE boolean
|
||||
nv50_buffer_allocate(struct nv50_screen *screen, struct nv50_resource *buf,
|
||||
unsigned domain)
|
||||
{
|
||||
if (domain == NOUVEAU_BO_VRAM) {
|
||||
buf->mm = nv50_mm_allocate(screen->mm_VRAM, buf->base.width0, &buf->bo,
|
||||
&buf->offset);
|
||||
if (!buf->bo)
|
||||
return nv50_buffer_allocate(screen, buf, NOUVEAU_BO_GART);
|
||||
} else
|
||||
if (domain == NOUVEAU_BO_GART) {
|
||||
buf->mm = nv50_mm_allocate(screen->mm_GART, buf->base.width0, &buf->bo,
|
||||
&buf->offset);
|
||||
if (!buf->bo)
|
||||
return FALSE;
|
||||
}
|
||||
if (domain != NOUVEAU_BO_GART) {
|
||||
if (!buf->data) {
|
||||
buf->data = MALLOC(buf->base.width0);
|
||||
if (!buf->data)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
buf->domain = domain;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
release_allocation(struct nv50_mm_allocation **mm, struct nv50_fence *fence)
|
||||
{
|
||||
if (fence && fence->state != NV50_FENCE_STATE_SIGNALLED) {
|
||||
nv50_fence_sched_release(fence, *mm);
|
||||
} else {
|
||||
nv50_mm_free(*mm);
|
||||
}
|
||||
(*mm) = NULL;
|
||||
}
|
||||
|
||||
INLINE void
|
||||
nv50_buffer_release_gpu_storage(struct nv50_resource *buf)
|
||||
{
|
||||
nouveau_bo_ref(NULL, &buf->bo);
|
||||
|
||||
if (buf->mm)
|
||||
release_allocation(&buf->mm, buf->fence);
|
||||
|
||||
buf->domain = 0;
|
||||
}
|
||||
|
||||
static INLINE boolean
|
||||
nv50_buffer_reallocate(struct nv50_screen *screen, struct nv50_resource *buf,
|
||||
unsigned domain)
|
||||
{
|
||||
nv50_buffer_release_gpu_storage(buf);
|
||||
|
||||
return nv50_buffer_allocate(screen, buf, domain);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_buffer_destroy(struct pipe_screen *pscreen,
|
||||
struct pipe_resource *presource)
|
||||
{
|
||||
struct nv50_resource *res = nv50_resource(presource);
|
||||
|
||||
nv50_buffer_release_gpu_storage(res);
|
||||
|
||||
if (res->data && !(res->status & NV50_BUFFER_STATUS_USER_MEMORY))
|
||||
FREE(res->data);
|
||||
|
||||
FREE(res);
|
||||
}
|
||||
|
||||
/* Maybe just migrate to GART right away if we actually need to do this. */
|
||||
boolean
|
||||
nv50_buffer_download(struct nv50_context *nv50, struct nv50_resource *buf,
|
||||
unsigned start, unsigned size)
|
||||
{
|
||||
struct nv50_mm_allocation *mm;
|
||||
struct nouveau_bo *bounce = NULL;
|
||||
uint32_t offset;
|
||||
|
||||
assert(buf->domain == NOUVEAU_BO_VRAM);
|
||||
|
||||
mm = nv50_mm_allocate(nv50->screen->mm_GART, size, &bounce, &offset);
|
||||
if (!bounce)
|
||||
return FALSE;
|
||||
|
||||
nv50_m2mf_copy_linear(nv50, bounce, offset, NOUVEAU_BO_GART,
|
||||
buf->bo, buf->offset + start, NOUVEAU_BO_VRAM,
|
||||
size);
|
||||
|
||||
if (nouveau_bo_map_range(bounce, offset, size, NOUVEAU_BO_RD))
|
||||
return FALSE;
|
||||
memcpy(buf->data + start, bounce->map, size);
|
||||
nouveau_bo_unmap(bounce);
|
||||
|
||||
buf->status &= ~NV50_BUFFER_STATUS_DIRTY;
|
||||
|
||||
nouveau_bo_ref(NULL, &bounce);
|
||||
if (mm)
|
||||
nv50_mm_free(mm);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static boolean
|
||||
nv50_buffer_upload(struct nv50_context *nv50, struct nv50_resource *buf,
|
||||
unsigned start, unsigned size)
|
||||
{
|
||||
struct nv50_mm_allocation *mm;
|
||||
struct nouveau_bo *bounce = NULL;
|
||||
uint32_t offset;
|
||||
|
||||
if (size <= 192) {
|
||||
nv50_sifc_linear_u8(nv50, buf->bo, buf->domain, buf->offset + start,
|
||||
size, buf->data + start);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
mm = nv50_mm_allocate(nv50->screen->mm_GART, size, &bounce, &offset);
|
||||
if (!bounce)
|
||||
return FALSE;
|
||||
|
||||
nouveau_bo_map_range(bounce, offset, size,
|
||||
NOUVEAU_BO_WR | NOUVEAU_BO_NOSYNC);
|
||||
memcpy(bounce->map, buf->data + start, size);
|
||||
nouveau_bo_unmap(bounce);
|
||||
|
||||
nv50_m2mf_copy_linear(nv50, buf->bo, buf->offset + start, NOUVEAU_BO_VRAM,
|
||||
bounce, offset, NOUVEAU_BO_GART, size);
|
||||
|
||||
nouveau_bo_ref(NULL, &bounce);
|
||||
if (mm)
|
||||
release_allocation(&mm, nv50->screen->fence.current);
|
||||
|
||||
if (start == 0 && size == buf->base.width0)
|
||||
buf->status &= ~NV50_BUFFER_STATUS_DIRTY;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static struct pipe_transfer *
|
||||
nv50_buffer_transfer_get(struct pipe_context *pipe,
|
||||
struct pipe_resource *resource,
|
||||
unsigned level,
|
||||
unsigned usage,
|
||||
const struct pipe_box *box)
|
||||
{
|
||||
struct nv50_resource *buf = nv50_resource(resource);
|
||||
struct nv50_transfer *xfr = CALLOC_STRUCT(nv50_transfer);
|
||||
if (!xfr)
|
||||
return NULL;
|
||||
|
||||
xfr->base.resource = resource;
|
||||
xfr->base.box.x = box->x;
|
||||
xfr->base.box.width = box->width;
|
||||
xfr->base.usage = usage;
|
||||
|
||||
if (buf->domain == NOUVEAU_BO_VRAM) {
|
||||
if (usage & PIPE_TRANSFER_READ) {
|
||||
if (buf->status & NV50_BUFFER_STATUS_DIRTY)
|
||||
nv50_buffer_download(nv50_context(pipe), buf, 0, buf->base.width0);
|
||||
}
|
||||
}
|
||||
|
||||
return &xfr->base;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_buffer_transfer_destroy(struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct nv50_resource *buf = nv50_resource(transfer->resource);
|
||||
struct nv50_transfer *xfr = nv50_transfer(transfer);
|
||||
|
||||
if (xfr->base.usage & PIPE_TRANSFER_WRITE) {
|
||||
/* writing is worse */
|
||||
nv50_buffer_adjust_score(nv50_context(pipe), buf, -5000);
|
||||
|
||||
if (buf->domain == NOUVEAU_BO_VRAM) {
|
||||
nv50_buffer_upload(nv50_context(pipe), buf,
|
||||
transfer->box.x, transfer->box.width);
|
||||
}
|
||||
|
||||
if (buf->domain != 0 && (buf->base.bind & (PIPE_BIND_VERTEX_BUFFER |
|
||||
PIPE_BIND_INDEX_BUFFER)))
|
||||
nv50_context(pipe)->vbo_dirty = TRUE;
|
||||
}
|
||||
|
||||
FREE(xfr);
|
||||
}
|
||||
|
||||
static INLINE boolean
|
||||
nv50_buffer_sync(struct nv50_resource *buf, unsigned rw)
|
||||
{
|
||||
if (rw == PIPE_TRANSFER_READ) {
|
||||
if (!buf->fence_wr)
|
||||
return TRUE;
|
||||
if (!nv50_fence_wait(buf->fence_wr))
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!buf->fence)
|
||||
return TRUE;
|
||||
if (!nv50_fence_wait(buf->fence))
|
||||
return FALSE;
|
||||
|
||||
nv50_fence_reference(&buf->fence, NULL);
|
||||
}
|
||||
nv50_fence_reference(&buf->fence_wr, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INLINE boolean
|
||||
nv50_buffer_busy(struct nv50_resource *buf, unsigned rw)
|
||||
{
|
||||
if (rw == PIPE_TRANSFER_READ)
|
||||
return (buf->fence_wr && !nv50_fence_signalled(buf->fence_wr));
|
||||
else
|
||||
return (buf->fence && !nv50_fence_signalled(buf->fence));
|
||||
}
|
||||
|
||||
/* Utility functions for transfer create/destroy are hooked in and
|
||||
* just record the arguments to those functions.
|
||||
*/
|
||||
static void *
|
||||
nv50_buffer_transfer_map( struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer )
|
||||
nv50_buffer_transfer_map(struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct nv50_resource *buffer = nv50_resource(transfer->resource);
|
||||
uint8_t *map;
|
||||
struct nv50_transfer *xfr = nv50_transfer(transfer);
|
||||
struct nv50_resource *buf = nv50_resource(transfer->resource);
|
||||
struct nouveau_bo *bo = buf->bo;
|
||||
uint8_t *map;
|
||||
int ret;
|
||||
uint32_t offset = xfr->base.box.x;
|
||||
uint32_t flags;
|
||||
|
||||
map = nouveau_screen_bo_map_range( pipe->screen,
|
||||
buffer->bo,
|
||||
transfer->box.x,
|
||||
transfer->box.width,
|
||||
nouveau_screen_transfer_flags(transfer->usage) );
|
||||
if (map == NULL)
|
||||
return NULL;
|
||||
|
||||
return map + transfer->box.x;
|
||||
nv50_buffer_adjust_score(nv50_context(pipe), buf, -250);
|
||||
|
||||
if (buf->domain != NOUVEAU_BO_GART)
|
||||
return buf->data + offset;
|
||||
|
||||
if (buf->mm)
|
||||
flags = NOUVEAU_BO_NOSYNC | NOUVEAU_BO_RDWR;
|
||||
else
|
||||
flags = nouveau_screen_transfer_flags(xfr->base.usage);
|
||||
|
||||
offset += buf->offset;
|
||||
|
||||
ret = nouveau_bo_map_range(buf->bo, offset, xfr->base.box.width, flags);
|
||||
if (ret)
|
||||
return NULL;
|
||||
map = bo->map;
|
||||
|
||||
/* Unmap right now. Since multiple buffers can share a single nouveau_bo,
|
||||
* not doing so might make future maps fail or trigger "reloc while mapped"
|
||||
* errors. For now, mappings to userspace are guaranteed to be persistent.
|
||||
*/
|
||||
nouveau_bo_unmap(bo);
|
||||
|
||||
if (buf->mm) {
|
||||
if (xfr->base.usage & PIPE_TRANSFER_DONTBLOCK) {
|
||||
if (nv50_buffer_busy(buf, xfr->base.usage & PIPE_TRANSFER_READ_WRITE))
|
||||
return NULL;
|
||||
} else
|
||||
if (!(xfr->base.usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
|
||||
nv50_buffer_sync(buf, xfr->base.usage & PIPE_TRANSFER_READ_WRITE);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void nv50_buffer_transfer_flush_region( struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer,
|
||||
const struct pipe_box *box)
|
||||
static void
|
||||
nv50_buffer_transfer_flush_region(struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer,
|
||||
const struct pipe_box *box)
|
||||
{
|
||||
struct nv50_resource *buffer = nv50_resource(transfer->resource);
|
||||
struct nv50_resource *res = nv50_resource(transfer->resource);
|
||||
struct nouveau_bo *bo = res->bo;
|
||||
unsigned offset = res->offset + transfer->box.x + box->x;
|
||||
|
||||
nouveau_screen_bo_map_flush_range(pipe->screen,
|
||||
buffer->bo,
|
||||
transfer->box.x + box->x,
|
||||
box->width);
|
||||
/* not using non-snoop system memory yet, no need for cflush */
|
||||
if (1)
|
||||
return;
|
||||
|
||||
/* XXX: maybe need to upload for VRAM buffers here */
|
||||
|
||||
nouveau_screen_bo_map_flush_range(pipe->screen, bo, offset, box->width);
|
||||
}
|
||||
|
||||
static void nv50_buffer_transfer_unmap( struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer )
|
||||
static void
|
||||
nv50_buffer_transfer_unmap(struct pipe_context *pipe,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct nv50_resource *buffer = nv50_resource(transfer->resource);
|
||||
|
||||
nouveau_screen_bo_unmap(pipe->screen, buffer->bo);
|
||||
/* we've called nouveau_bo_unmap right after map */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const struct u_resource_vtbl nv50_buffer_vtbl =
|
||||
{
|
||||
u_default_resource_get_handle, /* get_handle */
|
||||
nv50_buffer_destroy, /* resource_destroy */
|
||||
NULL, /* is_resource_referenced */
|
||||
u_default_get_transfer, /* get_transfer */
|
||||
u_default_transfer_destroy, /* transfer_destroy */
|
||||
nv50_buffer_transfer_map, /* transfer_map */
|
||||
nv50_buffer_transfer_flush_region, /* transfer_flush_region */
|
||||
nv50_buffer_transfer_unmap, /* transfer_unmap */
|
||||
u_default_transfer_inline_write /* transfer_inline_write */
|
||||
u_default_resource_get_handle, /* get_handle */
|
||||
nv50_buffer_destroy, /* resource_destroy */
|
||||
NULL, /* is_resource_referenced */
|
||||
nv50_buffer_transfer_get, /* get_transfer */
|
||||
nv50_buffer_transfer_destroy, /* transfer_destroy */
|
||||
nv50_buffer_transfer_map, /* transfer_map */
|
||||
nv50_buffer_transfer_flush_region, /* transfer_flush_region */
|
||||
nv50_buffer_transfer_unmap, /* transfer_unmap */
|
||||
u_default_transfer_inline_write /* transfer_inline_write */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct pipe_resource *
|
||||
nv50_buffer_create(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *template)
|
||||
const struct pipe_resource *templ)
|
||||
{
|
||||
struct nv50_resource *buffer;
|
||||
struct nv50_screen *screen = nv50_screen(pscreen);
|
||||
struct nv50_resource *buffer;
|
||||
boolean ret;
|
||||
|
||||
buffer = CALLOC_STRUCT(nv50_resource);
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
buffer = CALLOC_STRUCT(nv50_resource);
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
buffer->base = *template;
|
||||
buffer->vtbl = &nv50_buffer_vtbl;
|
||||
pipe_reference_init(&buffer->base.reference, 1);
|
||||
buffer->base.screen = pscreen;
|
||||
buffer->base = *templ;
|
||||
buffer->vtbl = &nv50_buffer_vtbl;
|
||||
pipe_reference_init(&buffer->base.reference, 1);
|
||||
buffer->base.screen = pscreen;
|
||||
|
||||
buffer->bo = nouveau_screen_bo_new(pscreen,
|
||||
16,
|
||||
buffer->base.usage,
|
||||
buffer->base.bind,
|
||||
buffer->base.width0);
|
||||
if (buffer->base.bind & PIPE_BIND_CONSTANT_BUFFER)
|
||||
ret = nv50_buffer_allocate(screen, buffer, 0);
|
||||
else
|
||||
ret = nv50_buffer_allocate(screen, buffer, NOUVEAU_BO_GART);
|
||||
|
||||
if (buffer->bo == NULL)
|
||||
goto fail;
|
||||
if (ret == FALSE)
|
||||
goto fail;
|
||||
|
||||
return &buffer->base;
|
||||
return &buffer->base;
|
||||
|
||||
fail:
|
||||
FREE(buffer);
|
||||
return NULL;
|
||||
FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct pipe_resource *
|
||||
nv50_user_buffer_create(struct pipe_screen *pscreen,
|
||||
void *ptr,
|
||||
unsigned bytes,
|
||||
unsigned bind)
|
||||
void *ptr,
|
||||
unsigned bytes,
|
||||
unsigned bind)
|
||||
{
|
||||
struct nv50_resource *buffer;
|
||||
struct nv50_resource *buffer;
|
||||
|
||||
buffer = CALLOC_STRUCT(nv50_resource);
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
buffer = CALLOC_STRUCT(nv50_resource);
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
pipe_reference_init(&buffer->base.reference, 1);
|
||||
buffer->vtbl = &nv50_buffer_vtbl;
|
||||
buffer->base.screen = pscreen;
|
||||
buffer->base.format = PIPE_FORMAT_R8_UNORM;
|
||||
buffer->base.usage = PIPE_USAGE_IMMUTABLE;
|
||||
buffer->base.bind = bind;
|
||||
buffer->base.width0 = bytes;
|
||||
buffer->base.height0 = 1;
|
||||
buffer->base.depth0 = 1;
|
||||
buffer->base.array_size = 1;
|
||||
pipe_reference_init(&buffer->base.reference, 1);
|
||||
buffer->vtbl = &nv50_buffer_vtbl;
|
||||
buffer->base.screen = pscreen;
|
||||
buffer->base.format = PIPE_FORMAT_R8_UNORM;
|
||||
buffer->base.usage = PIPE_USAGE_IMMUTABLE;
|
||||
buffer->base.bind = bind;
|
||||
buffer->base.width0 = bytes;
|
||||
buffer->base.height0 = 1;
|
||||
buffer->base.depth0 = 1;
|
||||
|
||||
buffer->bo = nouveau_screen_bo_user(pscreen, ptr, bytes);
|
||||
if (!buffer->bo)
|
||||
goto fail;
|
||||
|
||||
return &buffer->base;
|
||||
buffer->data = ptr;
|
||||
buffer->status = NV50_BUFFER_STATUS_USER_MEMORY;
|
||||
|
||||
fail:
|
||||
FREE(buffer);
|
||||
return NULL;
|
||||
return &buffer->base;
|
||||
}
|
||||
|
||||
/* Like download, but for GART buffers. Merge ? */
|
||||
static INLINE boolean
|
||||
nv50_buffer_data_fetch(struct nv50_resource *buf,
|
||||
struct nouveau_bo *bo, unsigned offset, unsigned size)
|
||||
{
|
||||
if (!buf->data) {
|
||||
buf->data = MALLOC(size);
|
||||
if (!buf->data)
|
||||
return FALSE;
|
||||
}
|
||||
if (nouveau_bo_map_range(bo, offset, size, NOUVEAU_BO_RD))
|
||||
return FALSE;
|
||||
memcpy(buf->data, bo->map, size);
|
||||
nouveau_bo_unmap(bo);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Migrate a linear buffer (vertex, index, constants) USER -> GART -> VRAM. */
|
||||
boolean
|
||||
nv50_buffer_migrate(struct nv50_context *nv50,
|
||||
struct nv50_resource *buf, const unsigned new_domain)
|
||||
{
|
||||
struct nv50_screen *screen = nv50_screen(buf->base.screen);
|
||||
struct nouveau_bo *bo;
|
||||
const unsigned old_domain = buf->domain;
|
||||
unsigned size = buf->base.width0;
|
||||
unsigned offset;
|
||||
int ret;
|
||||
|
||||
assert(new_domain != old_domain);
|
||||
|
||||
if (new_domain == NOUVEAU_BO_GART && old_domain == 0) {
|
||||
if (!nv50_buffer_allocate(screen, buf, new_domain))
|
||||
return FALSE;
|
||||
ret = nouveau_bo_map_range(buf->bo, buf->offset, size, NOUVEAU_BO_WR |
|
||||
NOUVEAU_BO_NOSYNC);
|
||||
if (ret)
|
||||
return ret;
|
||||
memcpy(buf->bo->map, buf->data, size);
|
||||
nouveau_bo_unmap(buf->bo);
|
||||
FREE(buf->data);
|
||||
} else
|
||||
if (old_domain != 0 && new_domain != 0) {
|
||||
struct nv50_mm_allocation *mm = buf->mm;
|
||||
|
||||
if (new_domain == NOUVEAU_BO_VRAM) {
|
||||
/* keep a system memory copy of our data in case we hit a fallback */
|
||||
if (!nv50_buffer_data_fetch(buf, buf->bo, buf->offset, size))
|
||||
return FALSE;
|
||||
debug_printf("migrating %u KiB to VRAM\n", size / 1024);
|
||||
}
|
||||
|
||||
offset = buf->offset;
|
||||
bo = buf->bo;
|
||||
buf->bo = NULL;
|
||||
buf->mm = NULL;
|
||||
nv50_buffer_allocate(screen, buf, new_domain);
|
||||
|
||||
nv50_m2mf_copy_linear(nv50, buf->bo, buf->offset, new_domain,
|
||||
bo, offset, old_domain, buf->base.width0);
|
||||
|
||||
nouveau_bo_ref(NULL, &bo);
|
||||
if (mm)
|
||||
release_allocation(&mm, screen->fence.current);
|
||||
} else
|
||||
if (new_domain == NOUVEAU_BO_VRAM && old_domain == 0) {
|
||||
if (!nv50_buffer_allocate(screen, buf, NOUVEAU_BO_VRAM))
|
||||
return FALSE;
|
||||
if (!nv50_buffer_upload(nv50, buf, 0, buf->base.width0))
|
||||
return FALSE;
|
||||
} else
|
||||
return FALSE;
|
||||
|
||||
assert(buf->domain == new_domain);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Migrate data from glVertexAttribPointer(non-VBO) user buffers to GART.
|
||||
* We'd like to only allocate @size bytes here, but then we'd have to rebase
|
||||
* the vertex indices ...
|
||||
*/
|
||||
boolean
|
||||
nv50_user_buffer_upload(struct nv50_resource *buf, unsigned base, unsigned size)
|
||||
{
|
||||
struct nv50_screen *screen = nv50_screen(buf->base.screen);
|
||||
int ret;
|
||||
|
||||
assert(buf->status & NV50_BUFFER_STATUS_USER_MEMORY);
|
||||
|
||||
buf->base.width0 = base + size;
|
||||
if (!nv50_buffer_reallocate(screen, buf, NOUVEAU_BO_GART))
|
||||
return FALSE;
|
||||
|
||||
ret = nouveau_bo_map_range(buf->bo, buf->offset + base, size,
|
||||
NOUVEAU_BO_WR | NOUVEAU_BO_NOSYNC);
|
||||
if (ret)
|
||||
return FALSE;
|
||||
memcpy(buf->bo->map, buf->data + base, size);
|
||||
nouveau_bo_unmap(buf->bo);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright 2008 Ben Skeggs
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "nv50_context.h"
|
||||
|
||||
void
|
||||
nv50_clear(struct pipe_context *pipe, unsigned buffers,
|
||||
const float *rgba, double depth, unsigned stencil)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct pipe_framebuffer_state *fb = &nv50->framebuffer;
|
||||
unsigned mode = 0, i;
|
||||
const unsigned dirty = nv50->dirty;
|
||||
|
||||
/* don't need NEW_BLEND, NV50TCL_COLOR_MASK doesn't affect CLEAR_BUFFERS */
|
||||
nv50->dirty &= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;
|
||||
if (!nv50_state_validate(nv50, 64))
|
||||
return;
|
||||
|
||||
if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_COLOR(0), 4);
|
||||
OUT_RING (chan, fui(rgba[0]));
|
||||
OUT_RING (chan, fui(rgba[1]));
|
||||
OUT_RING (chan, fui(rgba[2]));
|
||||
OUT_RING (chan, fui(rgba[3]));
|
||||
mode |= 0x3c;
|
||||
}
|
||||
|
||||
if (buffers & PIPE_CLEAR_DEPTH) {
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_DEPTH, 1);
|
||||
OUT_RING (chan, fui(depth));
|
||||
mode |= NV50TCL_CLEAR_BUFFERS_Z;
|
||||
}
|
||||
if (buffers & PIPE_CLEAR_STENCIL) {
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_STENCIL, 1);
|
||||
OUT_RING (chan, stencil & 0xff);
|
||||
mode |= NV50TCL_CLEAR_BUFFERS_S;
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
|
||||
OUT_RING (chan, mode);
|
||||
|
||||
for (i = 1; i < fb->nr_cbufs; i++) {
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
|
||||
OUT_RING (chan, (i << 6) | 0x3c);
|
||||
}
|
||||
nv50->dirty = dirty;
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008 Ben Skeggs
|
||||
* Copyright 2010 Christoph Bumiller
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
|
@ -27,80 +27,153 @@
|
|||
#include "nv50_screen.h"
|
||||
#include "nv50_resource.h"
|
||||
|
||||
#include "nouveau/nouveau_reloc.h"
|
||||
|
||||
static void
|
||||
nv50_flush(struct pipe_context *pipe, unsigned flags,
|
||||
struct pipe_fence_handle **fence)
|
||||
struct pipe_fence_handle **fence)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
|
||||
if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
|
||||
BEGIN_RING(chan, nv50->screen->tesla, 0x1338, 1);
|
||||
OUT_RING (chan, 0x20);
|
||||
}
|
||||
if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
|
||||
BEGIN_RING(chan, RING_3D_(NV50_GRAPH_WAIT_FOR_IDLE), 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1);
|
||||
OUT_RING (chan, 0x20);
|
||||
}
|
||||
|
||||
if (flags & PIPE_FLUSH_FRAME)
|
||||
FIRE_RING(chan);
|
||||
if (fence)
|
||||
nv50_fence_reference((struct nv50_fence **)fence,
|
||||
nv50->screen->fence.current);
|
||||
|
||||
if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME))
|
||||
FIRE_RING(chan);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_default_flush_notify(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nv50_context *nv50 = chan->user_private;
|
||||
|
||||
if (!nv50)
|
||||
return;
|
||||
|
||||
nv50_screen_fence_update(nv50->screen, TRUE);
|
||||
|
||||
nv50_screen_fence_next(nv50->screen);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_destroy(struct pipe_context *pipe)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
int i;
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
|
||||
for (i = 0; i < nv50->vtxbuf_nr; i++) {
|
||||
pipe_resource_reference(&nv50->vtxbuf[i].buffer, NULL);
|
||||
}
|
||||
draw_destroy(nv50->draw);
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (!nv50->state.hw[i])
|
||||
continue;
|
||||
so_ref(NULL, &nv50->state.hw[i]);
|
||||
}
|
||||
if (nv50->screen->cur_ctx == nv50) {
|
||||
nv50->screen->base.channel->user_private = NULL;
|
||||
nv50->screen->cur_ctx = NULL;
|
||||
}
|
||||
|
||||
draw_destroy(nv50->draw);
|
||||
|
||||
if (nv50->screen->cur_ctx == nv50)
|
||||
nv50->screen->cur_ctx = NULL;
|
||||
|
||||
FREE(nv50);
|
||||
FREE(nv50);
|
||||
}
|
||||
|
||||
|
||||
struct pipe_context *
|
||||
nv50_create(struct pipe_screen *pscreen, void *priv)
|
||||
{
|
||||
struct pipe_winsys *pipe_winsys = pscreen->winsys;
|
||||
struct nv50_screen *screen = nv50_screen(pscreen);
|
||||
struct nv50_context *nv50;
|
||||
struct pipe_winsys *pipe_winsys = pscreen->winsys;
|
||||
struct nv50_screen *screen = nv50_screen(pscreen);
|
||||
struct nv50_context *nv50;
|
||||
|
||||
nv50 = CALLOC_STRUCT(nv50_context);
|
||||
if (!nv50)
|
||||
return NULL;
|
||||
nv50->screen = screen;
|
||||
nv50 = CALLOC_STRUCT(nv50_context);
|
||||
if (!nv50)
|
||||
return NULL;
|
||||
nv50->screen = screen;
|
||||
|
||||
nv50->pipe.winsys = pipe_winsys;
|
||||
nv50->pipe.screen = pscreen;
|
||||
nv50->pipe.priv = priv;
|
||||
nv50->pipe.winsys = pipe_winsys;
|
||||
nv50->pipe.screen = pscreen;
|
||||
nv50->pipe.priv = priv;
|
||||
|
||||
nv50->pipe.destroy = nv50_destroy;
|
||||
nv50->pipe.destroy = nv50_destroy;
|
||||
|
||||
nv50->pipe.draw_vbo = nv50_draw_vbo;
|
||||
nv50->pipe.clear = nv50_clear;
|
||||
nv50->pipe.draw_vbo = nv50_draw_vbo;
|
||||
nv50->pipe.clear = nv50_clear;
|
||||
|
||||
nv50->pipe.flush = nv50_flush;
|
||||
nv50->pipe.flush = nv50_flush;
|
||||
|
||||
screen->base.channel->user_private = nv50;
|
||||
screen->base.channel->user_private = nv50;
|
||||
screen->base.channel->flush_notify = nv50_default_flush_notify;
|
||||
|
||||
nv50_init_surface_functions(nv50);
|
||||
nv50_init_state_functions(nv50);
|
||||
nv50_init_query_functions(nv50);
|
||||
nv50_init_resource_functions(&nv50->pipe);
|
||||
nv50_init_query_functions(nv50);
|
||||
nv50_init_surface_functions(nv50);
|
||||
nv50_init_state_functions(nv50);
|
||||
nv50_init_resource_functions(&nv50->pipe);
|
||||
|
||||
nv50->draw = draw_create(&nv50->pipe);
|
||||
assert(nv50->draw);
|
||||
draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
|
||||
nv50->draw = draw_create(&nv50->pipe);
|
||||
assert(nv50->draw);
|
||||
draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
|
||||
|
||||
return &nv50->pipe;
|
||||
return &nv50->pipe;
|
||||
}
|
||||
|
||||
struct resident {
|
||||
struct nv50_resource *res;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
void
|
||||
nv50_bufctx_add_resident(struct nv50_context *nv50, int ctx,
|
||||
struct nv50_resource *resource, uint32_t flags)
|
||||
{
|
||||
struct resident rsd = { resource, flags };
|
||||
|
||||
if (!resource->bo)
|
||||
return;
|
||||
|
||||
/* We don't need to reference the resource here, it will be referenced
|
||||
* in the context/state, and bufctx will be reset when state changes.
|
||||
*/
|
||||
util_dynarray_append(&nv50->residents[ctx], struct resident, rsd);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_bufctx_del_resident(struct nv50_context *nv50, int ctx,
|
||||
struct nv50_resource *resource)
|
||||
{
|
||||
struct resident *rsd, *top;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < nv50->residents[ctx].size / sizeof(struct resident); ++i) {
|
||||
rsd = util_dynarray_element(&nv50->residents[ctx], struct resident, i);
|
||||
|
||||
if (rsd->res == resource) {
|
||||
top = util_dynarray_pop_ptr(&nv50->residents[ctx], struct resident);
|
||||
if (rsd != top)
|
||||
*rsd = *top;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv50_bufctx_emit_relocs(struct nv50_context *nv50)
|
||||
{
|
||||
struct resident *rsd;
|
||||
struct util_dynarray *array;
|
||||
unsigned ctx, i, n;
|
||||
|
||||
for (ctx = 0; ctx < NV50_BUFCTX_COUNT; ++ctx) {
|
||||
array = &nv50->residents[ctx];
|
||||
|
||||
n = array->size / sizeof(struct resident);
|
||||
MARK_RING(nv50->screen->base.channel, n, n);
|
||||
for (i = 0; i < n; ++i) {
|
||||
rsd = util_dynarray_element(array, struct resident, i);
|
||||
|
||||
nv50_resource_validate(rsd->res, rsd->flags);
|
||||
}
|
||||
}
|
||||
|
||||
nv50_screen_make_buffers_resident(nv50->screen);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,265 +5,227 @@
|
|||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_dynarray.h"
|
||||
|
||||
#include "draw/draw_vertex.h"
|
||||
|
||||
#include "nouveau/nouveau_winsys.h"
|
||||
#include "nouveau/nouveau_gldefs.h"
|
||||
#include "nouveau/nouveau_stateobj.h"
|
||||
#include "nv50_reg.h"
|
||||
|
||||
#include "nv50_winsys.h"
|
||||
#include "nv50_stateobj.h"
|
||||
#include "nv50_screen.h"
|
||||
#include "nv50_program.h"
|
||||
#include "nv50_resource.h"
|
||||
|
||||
#include "nouveau/nv_object.xml.h"
|
||||
#include "nouveau/nv_m2mf.xml.h"
|
||||
#include "nv50_3ddefs.xml.h"
|
||||
#include "nv50_3d.xml.h"
|
||||
#include "nv50_2d.xml.h"
|
||||
|
||||
#define NOUVEAU_ERR(fmt, args...) \
|
||||
fprintf(stderr, "%s:%d - "fmt, __FUNCTION__, __LINE__, ##args);
|
||||
#define NOUVEAU_MSG(fmt, args...) \
|
||||
fprintf(stderr, "nouveau: "fmt, ##args);
|
||||
fprintf(stderr, "%s:%d - "fmt, __FUNCTION__, __LINE__, ##args);
|
||||
|
||||
#define nouveau_bo_tile_layout(nvbo) \
|
||||
((nvbo)->tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK)
|
||||
#ifdef NOUVEAU_DEBUG
|
||||
# define NOUVEAU_DBG(args...) printf(args);
|
||||
#else
|
||||
# define NOUVEAU_DBG(args...)
|
||||
#endif
|
||||
|
||||
/* Constant buffer assignment */
|
||||
#define NV50_CB_PMISC 0
|
||||
#define NV50_CB_PVP 1
|
||||
#define NV50_CB_PFP 2
|
||||
#define NV50_CB_PGP 3
|
||||
#define NV50_CB_AUX 4
|
||||
#define NV50_NEW_BLEND (1 << 0)
|
||||
#define NV50_NEW_RASTERIZER (1 << 1)
|
||||
#define NV50_NEW_ZSA (1 << 2)
|
||||
#define NV50_NEW_VERTPROG (1 << 3)
|
||||
#define NV50_NEW_GMTYPROG (1 << 6)
|
||||
#define NV50_NEW_FRAGPROG (1 << 7)
|
||||
#define NV50_NEW_BLEND_COLOUR (1 << 8)
|
||||
#define NV50_NEW_STENCIL_REF (1 << 9)
|
||||
#define NV50_NEW_CLIP (1 << 10)
|
||||
#define NV50_NEW_SAMPLE_MASK (1 << 11)
|
||||
#define NV50_NEW_FRAMEBUFFER (1 << 12)
|
||||
#define NV50_NEW_STIPPLE (1 << 13)
|
||||
#define NV50_NEW_SCISSOR (1 << 14)
|
||||
#define NV50_NEW_VIEWPORT (1 << 15)
|
||||
#define NV50_NEW_ARRAYS (1 << 16)
|
||||
#define NV50_NEW_VERTEX (1 << 17)
|
||||
#define NV50_NEW_CONSTBUF (1 << 18)
|
||||
#define NV50_NEW_TEXTURES (1 << 19)
|
||||
#define NV50_NEW_SAMPLERS (1 << 20)
|
||||
|
||||
#define NV50_NEW_BLEND (1 << 0)
|
||||
#define NV50_NEW_ZSA (1 << 1)
|
||||
#define NV50_NEW_BLEND_COLOUR (1 << 2)
|
||||
#define NV50_NEW_STIPPLE (1 << 3)
|
||||
#define NV50_NEW_SCISSOR (1 << 4)
|
||||
#define NV50_NEW_VIEWPORT (1 << 5)
|
||||
#define NV50_NEW_RASTERIZER (1 << 6)
|
||||
#define NV50_NEW_FRAMEBUFFER (1 << 7)
|
||||
#define NV50_NEW_VERTPROG (1 << 8)
|
||||
#define NV50_NEW_VERTPROG_CB (1 << 9)
|
||||
#define NV50_NEW_FRAGPROG (1 << 10)
|
||||
#define NV50_NEW_FRAGPROG_CB (1 << 11)
|
||||
#define NV50_NEW_GEOMPROG (1 << 12)
|
||||
#define NV50_NEW_GEOMPROG_CB (1 << 13)
|
||||
#define NV50_NEW_ARRAYS (1 << 14)
|
||||
#define NV50_NEW_SAMPLER (1 << 15)
|
||||
#define NV50_NEW_TEXTURE (1 << 16)
|
||||
#define NV50_NEW_STENCIL_REF (1 << 17)
|
||||
#define NV50_NEW_CLIP (1 << 18)
|
||||
#define NV50_BUFCTX_CONSTANT 0
|
||||
#define NV50_BUFCTX_FRAME 1
|
||||
#define NV50_BUFCTX_VERTEX 2
|
||||
#define NV50_BUFCTX_TEXTURES 3
|
||||
#define NV50_BUFCTX_COUNT 4
|
||||
|
||||
struct nv50_blend_stateobj {
|
||||
struct pipe_blend_state pipe;
|
||||
struct nouveau_stateobj *so;
|
||||
};
|
||||
|
||||
struct nv50_zsa_stateobj {
|
||||
struct pipe_depth_stencil_alpha_state pipe;
|
||||
struct nouveau_stateobj *so;
|
||||
};
|
||||
|
||||
struct nv50_rasterizer_stateobj {
|
||||
struct pipe_rasterizer_state pipe;
|
||||
struct nouveau_stateobj *so;
|
||||
};
|
||||
|
||||
struct nv50_sampler_stateobj {
|
||||
boolean normalized;
|
||||
unsigned tsc[8];
|
||||
};
|
||||
|
||||
struct nv50_sampler_view {
|
||||
struct pipe_sampler_view pipe;
|
||||
uint32_t tic[8];
|
||||
};
|
||||
|
||||
struct nv50_vtxelt_stateobj {
|
||||
struct pipe_vertex_element pipe[16];
|
||||
unsigned num_elements;
|
||||
uint32_t hw[16];
|
||||
};
|
||||
|
||||
static INLINE struct nv50_sampler_view *
|
||||
nv50_sampler_view(struct pipe_sampler_view *view)
|
||||
{
|
||||
return (struct nv50_sampler_view *)view;
|
||||
}
|
||||
|
||||
static INLINE unsigned
|
||||
get_tile_height(uint32_t tile_mode)
|
||||
{
|
||||
return 1 << ((tile_mode & 0xf) + 2);
|
||||
}
|
||||
|
||||
static INLINE unsigned
|
||||
get_tile_depth(uint32_t tile_mode)
|
||||
{
|
||||
return 1 << (tile_mode >> 4);
|
||||
}
|
||||
|
||||
|
||||
struct nv50_surface {
|
||||
struct pipe_surface base;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
static INLINE struct nv50_surface *
|
||||
nv50_surface(struct pipe_surface *pt)
|
||||
{
|
||||
return (struct nv50_surface *)pt;
|
||||
}
|
||||
|
||||
struct nv50_state {
|
||||
struct nouveau_stateobj *hw[64];
|
||||
uint64_t hw_dirty;
|
||||
|
||||
unsigned sampler_view_nr[3];
|
||||
struct nouveau_stateobj *vtxbuf;
|
||||
struct nouveau_stateobj *vtxattr;
|
||||
unsigned vtxelt_nr;
|
||||
};
|
||||
/* fixed constant buffer binding points - low indices for user's constbufs */
|
||||
#define NV50_CB_PVP 124
|
||||
#define NV50_CB_PGP 126
|
||||
#define NV50_CB_PFP 125
|
||||
#define NV50_CB_AUX 127
|
||||
|
||||
struct nv50_context {
|
||||
struct pipe_context pipe;
|
||||
struct pipe_context pipe;
|
||||
|
||||
struct nv50_screen *screen;
|
||||
struct nv50_screen *screen;
|
||||
|
||||
struct draw_context *draw;
|
||||
struct util_dynarray residents[NV50_BUFCTX_COUNT];
|
||||
|
||||
struct nv50_state state;
|
||||
uint32_t dirty;
|
||||
|
||||
unsigned dirty;
|
||||
struct nv50_blend_stateobj *blend;
|
||||
struct nv50_zsa_stateobj *zsa;
|
||||
struct nv50_rasterizer_stateobj *rasterizer;
|
||||
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_framebuffer_state framebuffer;
|
||||
struct pipe_clip_state clip;
|
||||
struct nv50_program *vertprog;
|
||||
struct nv50_program *fragprog;
|
||||
struct nv50_program *geomprog;
|
||||
struct pipe_resource *constbuf[PIPE_SHADER_TYPES];
|
||||
struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
|
||||
unsigned vtxbuf_nr;
|
||||
struct pipe_index_buffer idxbuf;
|
||||
struct nv50_vtxelt_stateobj *vtxelt;
|
||||
struct nv50_sampler_stateobj *sampler[3][PIPE_MAX_SAMPLERS];
|
||||
unsigned sampler_nr[3];
|
||||
struct pipe_sampler_view *sampler_views[3][PIPE_MAX_SAMPLERS];
|
||||
unsigned sampler_view_nr[3];
|
||||
struct {
|
||||
uint32_t instance_elts; /* bitmask of per-instance elements */
|
||||
uint32_t instance_base;
|
||||
int32_t index_bias;
|
||||
boolean prim_restart;
|
||||
uint8_t num_vtxbufs;
|
||||
uint8_t num_vtxelts;
|
||||
uint8_t num_textures[3];
|
||||
uint8_t num_samplers[3];
|
||||
uint16_t scissor;
|
||||
} state;
|
||||
|
||||
unsigned vbo_fifo;
|
||||
unsigned req_lmem;
|
||||
struct nv50_blend_stateobj *blend;
|
||||
struct nv50_rasterizer_stateobj *rast;
|
||||
struct nv50_zsa_stateobj *zsa;
|
||||
struct nv50_vertex_stateobj *vertex;
|
||||
|
||||
struct nv50_program *vertprog;
|
||||
struct nv50_program *gmtyprog;
|
||||
struct nv50_program *fragprog;
|
||||
|
||||
struct pipe_resource *constbuf[3][16];
|
||||
uint16_t constbuf_dirty[3];
|
||||
|
||||
struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
|
||||
unsigned num_vtxbufs;
|
||||
struct pipe_index_buffer idxbuf;
|
||||
uint32_t vbo_fifo; /* bitmask of vertex elements to be pushed to FIFO */
|
||||
uint32_t vbo_user; /* bitmask of vertex buffers pointing to user memory */
|
||||
unsigned vbo_min_index; /* from pipe_draw_info, for vertex upload */
|
||||
unsigned vbo_max_index;
|
||||
|
||||
struct pipe_sampler_view *textures[3][PIPE_MAX_SAMPLERS];
|
||||
unsigned num_textures[3];
|
||||
struct nv50_tsc_entry *samplers[3][PIPE_MAX_SAMPLERS];
|
||||
unsigned num_samplers[3];
|
||||
|
||||
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;
|
||||
|
||||
boolean vbo_dirty;
|
||||
boolean vbo_push_hint;
|
||||
|
||||
struct draw_context *draw;
|
||||
};
|
||||
|
||||
static INLINE struct nv50_context *
|
||||
nv50_context(struct pipe_context *pipe)
|
||||
{
|
||||
return (struct nv50_context *)pipe;
|
||||
return (struct nv50_context *)pipe;
|
||||
}
|
||||
|
||||
extern void nv50_init_surface_functions(struct nv50_context *nv50);
|
||||
extern void nv50_init_state_functions(struct nv50_context *nv50);
|
||||
extern void nv50_init_query_functions(struct nv50_context *nv50);
|
||||
extern void nv50_init_transfer_functions(struct nv50_context *nv50);
|
||||
|
||||
extern void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen);
|
||||
|
||||
extern int
|
||||
nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
|
||||
int dx, int dy, struct pipe_surface *src, int sx, int sy,
|
||||
int w, int h);
|
||||
|
||||
/* nv50_draw.c */
|
||||
extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *nv50);
|
||||
|
||||
/* nv50_vbo.c */
|
||||
extern void nv50_draw_vbo(struct pipe_context *pipe,
|
||||
const struct pipe_draw_info *info);
|
||||
extern void nv50_vtxelt_construct(struct nv50_vtxelt_stateobj *cso);
|
||||
extern struct nouveau_stateobj *nv50_vbo_validate(struct nv50_context *nv50);
|
||||
|
||||
/* nv50_push.c */
|
||||
extern void
|
||||
nv50_push_elements_instanced(struct pipe_context *, struct pipe_resource *,
|
||||
unsigned idxsize, int idxbias,
|
||||
unsigned mode, unsigned start,
|
||||
unsigned count, unsigned i_start,
|
||||
unsigned i_count);
|
||||
|
||||
/* nv50_clear.c */
|
||||
extern void nv50_clear(struct pipe_context *pipe, unsigned buffers,
|
||||
const float *rgba, double depth, unsigned stencil);
|
||||
|
||||
/* nv50_program.c */
|
||||
extern struct nouveau_stateobj *
|
||||
nv50_vertprog_validate(struct nv50_context *nv50);
|
||||
extern struct nouveau_stateobj *
|
||||
nv50_fragprog_validate(struct nv50_context *nv50);
|
||||
extern struct nouveau_stateobj *
|
||||
nv50_geomprog_validate(struct nv50_context *nv50);
|
||||
extern struct nouveau_stateobj *
|
||||
nv50_fp_linkage_validate(struct nv50_context *nv50);
|
||||
extern struct nouveau_stateobj *
|
||||
nv50_gp_linkage_validate(struct nv50_context *nv50);
|
||||
extern void nv50_program_destroy(struct nv50_context *nv50,
|
||||
struct nv50_program *p);
|
||||
|
||||
/* nv50_state_validate.c */
|
||||
extern boolean nv50_state_validate(struct nv50_context *nv50, unsigned dwords);
|
||||
|
||||
extern void nv50_so_init_sifc(struct nv50_context *nv50,
|
||||
struct nouveau_stateobj *so,
|
||||
struct nouveau_bo *bo, unsigned reloc,
|
||||
unsigned offset, unsigned size);
|
||||
|
||||
/* nv50_tex.c */
|
||||
extern boolean nv50_tex_construct(struct nv50_sampler_view *view);
|
||||
extern void nv50_tex_relocs(struct nv50_context *);
|
||||
extern struct nouveau_stateobj *nv50_tex_validate(struct nv50_context *);
|
||||
struct nv50_surface {
|
||||
struct pipe_surface base;
|
||||
uint32_t offset;
|
||||
uint32_t width;
|
||||
uint16_t height;
|
||||
uint16_t depth;
|
||||
};
|
||||
|
||||
static INLINE struct nv50_surface *
|
||||
nv50_surface(struct pipe_surface *ps)
|
||||
{
|
||||
return (struct nv50_surface *)ps;
|
||||
}
|
||||
|
||||
/* nv50_context.c */
|
||||
struct pipe_context *
|
||||
nv50_create(struct pipe_screen *pscreen, void *priv);
|
||||
struct pipe_context *nv50_create(struct pipe_screen *, void *);
|
||||
|
||||
static INLINE unsigned
|
||||
nv50_prim(unsigned mode)
|
||||
void nv50_default_flush_notify(struct nouveau_channel *);
|
||||
|
||||
void nv50_bufctx_emit_relocs(struct nv50_context *);
|
||||
void nv50_bufctx_add_resident(struct nv50_context *, int ctx,
|
||||
struct nv50_resource *, uint32_t flags);
|
||||
void nv50_bufctx_del_resident(struct nv50_context *, int ctx,
|
||||
struct nv50_resource *);
|
||||
static INLINE void
|
||||
nv50_bufctx_reset(struct nv50_context *nv50, int ctx)
|
||||
{
|
||||
switch (mode) {
|
||||
case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS;
|
||||
case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES;
|
||||
case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP;
|
||||
case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP;
|
||||
case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES;
|
||||
case PIPE_PRIM_TRIANGLE_STRIP:
|
||||
return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP;
|
||||
case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN;
|
||||
case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS;
|
||||
case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP;
|
||||
case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON;
|
||||
case PIPE_PRIM_LINES_ADJACENCY:
|
||||
return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY;
|
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
|
||||
return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY;
|
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY:
|
||||
return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY;
|
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
NOUVEAU_ERR("invalid primitive type %d\n", mode);
|
||||
return NV50TCL_VERTEX_BEGIN_POINTS;
|
||||
util_dynarray_resize(&nv50->residents[ctx], 0);
|
||||
}
|
||||
|
||||
/* nv50_draw.c */
|
||||
extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *);
|
||||
|
||||
/* nv50_program.c */
|
||||
boolean nv50_program_translate(struct nv50_program *);
|
||||
void nv50_program_destroy(struct nv50_context *, struct nv50_program *);
|
||||
|
||||
/* nv50_query.c */
|
||||
void nv50_init_query_functions(struct nv50_context *);
|
||||
|
||||
/* nv50_shader_state.c */
|
||||
void nv50_vertprog_validate(struct nv50_context *);
|
||||
void nv50_gmtyprog_validate(struct nv50_context *);
|
||||
void nv50_fragprog_validate(struct nv50_context *);
|
||||
void nv50_fp_linkage_validate(struct nv50_context *);
|
||||
void nv50_gp_linkage_validate(struct nv50_context *);
|
||||
void nv50_constbufs_validate(struct nv50_context *);
|
||||
|
||||
/* nv50_state.c */
|
||||
extern void nv50_init_state_functions(struct nv50_context *);
|
||||
|
||||
/* nv50_state_validate.c */
|
||||
extern boolean nv50_state_validate(struct nv50_context *);
|
||||
|
||||
/* nv50_surface.c */
|
||||
extern void nv50_clear(struct pipe_context *, unsigned buffers,
|
||||
const float *rgba, double depth, unsigned stencil);
|
||||
extern void nv50_init_surface_functions(struct nv50_context *);
|
||||
|
||||
/* nv50_tex.c */
|
||||
void nv50_validate_textures(struct nv50_context *);
|
||||
void nv50_validate_samplers(struct nv50_context *);
|
||||
|
||||
struct pipe_sampler_view *
|
||||
nv50_create_sampler_view(struct pipe_context *,
|
||||
struct pipe_resource *,
|
||||
const struct pipe_sampler_view *);
|
||||
|
||||
/* nv50_transfer.c */
|
||||
void
|
||||
nv50_sifc_linear_u8(struct nv50_context *nv50,
|
||||
struct nouveau_bo *dst, unsigned domain, int offset,
|
||||
unsigned size, void *data);
|
||||
void
|
||||
nv50_m2mf_copy_linear(struct nv50_context *nv50,
|
||||
struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
|
||||
struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
|
||||
unsigned size);
|
||||
|
||||
/* nv50_vbo.c */
|
||||
void nv50_draw_vbo(struct pipe_context *, const struct pipe_draw_info *);
|
||||
|
||||
void *
|
||||
nv50_vertex_state_create(struct pipe_context *pipe,
|
||||
unsigned num_elements,
|
||||
const struct pipe_vertex_element *elements);
|
||||
void
|
||||
nv50_vertex_state_delete(struct pipe_context *pipe, void *hwcso);
|
||||
|
||||
void nv50_vertex_arrays_validate(struct nv50_context *nv50);
|
||||
|
||||
/* nv50_push.c */
|
||||
void nv50_push_vbo(struct nv50_context *, const struct pipe_draw_info *);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
142
src/gallium/drivers/nv50/nv50_defs.xml.h
Normal file
142
src/gallium/drivers/nv50/nv50_defs.xml.h
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#ifndef NV50_DEFS_XML
|
||||
#define NV50_DEFS_XML
|
||||
|
||||
/* Autogenerated file, DO NOT EDIT manually!
|
||||
|
||||
This file was generated by the rules-ng-ng headergen tool in this git repository:
|
||||
http://0x04.net/cgit/index.cgi/rules-ng-ng
|
||||
git clone git://0x04.net/rules-ng-ng
|
||||
|
||||
The rules-ng-ng source files this header was generated from are:
|
||||
- nv50_defs.xml ( 4482 bytes, from 2010-10-03 13:18:37)
|
||||
- copyright.xml ( 6498 bytes, from 2010-10-03 13:18:37)
|
||||
|
||||
Copyright (C) 2006-2010 by the following authors:
|
||||
- Artur Huillet <arthur.huillet@free.fr> (ahuillet)
|
||||
- Ben Skeggs (darktama, darktama_)
|
||||
- B. R. <koala_br@users.sourceforge.net> (koala_br)
|
||||
- Carlos Martin <carlosmn@users.sf.net> (carlosmn)
|
||||
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr)
|
||||
- Dawid Gajownik <gajownik@users.sf.net> (gajownik)
|
||||
- Dmitry Baryshkov
|
||||
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag)
|
||||
- EdB <edb_@users.sf.net> (edb_)
|
||||
- Erik Waling <erikwailing@users.sf.net> (erikwaling)
|
||||
- Francisco Jerez <currojerez@riseup.net> (curro, curro_, currojerez)
|
||||
- imirkin <imirkin@users.sf.net> (imirkin)
|
||||
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome)
|
||||
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy)
|
||||
- Laurent Carlier <lordheavym@gmail.com> (lordheavy)
|
||||
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1)
|
||||
- Maarten Maathuis <madman2003@gmail.com> (stillunknown)
|
||||
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin)
|
||||
- Mark Carey <mark.carey@gmail.com> (careym)
|
||||
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c)
|
||||
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman)
|
||||
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata)
|
||||
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen)
|
||||
- Peter Popov <ironpeter@users.sf.net> (ironpeter)
|
||||
- Richard Hughes <hughsient@users.sf.net> (hughsient)
|
||||
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar)
|
||||
- Serge Martin
|
||||
- Simon Raffeiner
|
||||
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier)
|
||||
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu)
|
||||
- sturmflut <sturmflut@users.sf.net> (sturmflut)
|
||||
- Sylvain Munaut <tnt@246tNt.com>
|
||||
- Victor Stinner <victor.stinner@haypocalc.com> (haypo)
|
||||
- Wladmir van der Laan <laanwj@gmail.com> (miathan6)
|
||||
- Younes Manton <younes.m@gmail.com> (ymanton)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the
|
||||
next paragraph) shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#define NV50_SURFACE_FORMAT_R32G32B32A32_FLOAT 0x000000c0
|
||||
#define NV50_SURFACE_FORMAT_R32G32B32A32_SINT 0x000000c1
|
||||
#define NV50_SURFACE_FORMAT_R32G32B32A32_UINT 0x000000c2
|
||||
#define NV50_SURFACE_FORMAT_R32G32B32X32_FLOAT 0x000000c3
|
||||
#define NV50_SURFACE_FORMAT_R16G16B16A16_UNORM 0x000000c6
|
||||
#define NV50_SURFACE_FORMAT_R16G16B16A16_SNORM 0x000000c7
|
||||
#define NV50_SURFACE_FORMAT_R16G16B16A16_SINT 0x000000c8
|
||||
#define NV50_SURFACE_FORMAT_R16G16B16A16_UINT 0x000000c9
|
||||
#define NV50_SURFACE_FORMAT_R16G16B16A16_FLOAT 0x000000ca
|
||||
#define NV50_SURFACE_FORMAT_R32G32_FLOAT 0x000000cb
|
||||
#define NV50_SURFACE_FORMAT_R32G32_SINT 0x000000cc
|
||||
#define NV50_SURFACE_FORMAT_R32G32_UINT 0x000000cd
|
||||
#define NV50_SURFACE_FORMAT_R16G16B16X16_FLOAT 0x000000ce
|
||||
#define NV50_SURFACE_FORMAT_A8R8G8B8_UNORM 0x000000cf
|
||||
#define NV50_SURFACE_FORMAT_A8R8G8B8_SRGB 0x000000d0
|
||||
#define NV50_SURFACE_FORMAT_A2B10G10R10_UNORM 0x000000d1
|
||||
#define NV50_SURFACE_FORMAT_A2B10G10R10_UINT 0x000000d2
|
||||
#define NV50_SURFACE_FORMAT_A8B8G8R8_UNORM 0x000000d5
|
||||
#define NV50_SURFACE_FORMAT_A8B8G8R8_SRGB 0x000000d6
|
||||
#define NV50_SURFACE_FORMAT_A8B8G8R8_SNORM 0x000000d7
|
||||
#define NV50_SURFACE_FORMAT_A8B8G8R8_SINT 0x000000d8
|
||||
#define NV50_SURFACE_FORMAT_A8B8G8R8_UINT 0x000000d9
|
||||
#define NV50_SURFACE_FORMAT_R16G16_UNORM 0x000000da
|
||||
#define NV50_SURFACE_FORMAT_R16G16_SNORM 0x000000db
|
||||
#define NV50_SURFACE_FORMAT_R16G16_SINT 0x000000dc
|
||||
#define NV50_SURFACE_FORMAT_R16G16_UINT 0x000000dd
|
||||
#define NV50_SURFACE_FORMAT_R16G16_FLOAT 0x000000de
|
||||
#define NV50_SURFACE_FORMAT_A2R10G10B10_UNORM 0x000000df
|
||||
#define NV50_SURFACE_FORMAT_B10G11R11_FLOAT 0x000000e0
|
||||
#define NV50_SURFACE_FORMAT_R32_FLOAT 0x000000e5
|
||||
#define NV50_SURFACE_FORMAT_X8R8G8B8_UNORM 0x000000e6
|
||||
#define NV50_SURFACE_FORMAT_X8R8G8B8_SRGB 0x000000e7
|
||||
#define NV50_SURFACE_FORMAT_R5G6B5_UNORM 0x000000e8
|
||||
#define NV50_SURFACE_FORMAT_A1R5G5B5_UNORM 0x000000e9
|
||||
#define NV50_SURFACE_FORMAT_R8G8_UNORM 0x000000ea
|
||||
#define NV50_SURFACE_FORMAT_R8G8_SNORM 0x000000eb
|
||||
#define NV50_SURFACE_FORMAT_R8G8_SINT 0x000000ec
|
||||
#define NV50_SURFACE_FORMAT_R8G8_UINT 0x000000ed
|
||||
#define NV50_SURFACE_FORMAT_R16_UNORM 0x000000ee
|
||||
#define NV50_SURFACE_FORMAT_R16_SNORM 0x000000ef
|
||||
#define NV50_SURFACE_FORMAT_R16_SINT 0x000000f0
|
||||
#define NV50_SURFACE_FORMAT_R16_UINT 0x000000f1
|
||||
#define NV50_SURFACE_FORMAT_R16_FLOAT 0x000000f2
|
||||
#define NV50_SURFACE_FORMAT_R8_UNORM 0x000000f3
|
||||
#define NV50_SURFACE_FORMAT_R8_SNORM 0x000000f4
|
||||
#define NV50_SURFACE_FORMAT_R8_SINT 0x000000f5
|
||||
#define NV50_SURFACE_FORMAT_R8_UINT 0x000000f6
|
||||
#define NV50_SURFACE_FORMAT_A8_UNORM 0x000000f7
|
||||
#define NV50_SURFACE_FORMAT_X1R5G5B5_UNORM 0x000000f8
|
||||
#define NV50_SURFACE_FORMAT_X8B8G8R8_UNORM 0x000000f9
|
||||
#define NV50_SURFACE_FORMAT_X8B8G8R8_SRGB 0x000000fa
|
||||
#define NV50_ZETA_FORMAT_Z32_FLOAT 0x0000000a
|
||||
#define NV50_ZETA_FORMAT_Z16_UNORM 0x00000013
|
||||
#define NV50_ZETA_FORMAT_Z24S8_UNORM 0x00000014
|
||||
#define NV50_ZETA_FORMAT_X8Z24_UNORM 0x00000015
|
||||
#define NV50_ZETA_FORMAT_S8Z24_UNORM 0x00000016
|
||||
#define NV50_ZETA_FORMAT_UNK18 0x00000018
|
||||
#define NV50_ZETA_FORMAT_Z32_FLOAT_X24S8_UNORM 0x00000019
|
||||
#define NV50_ZETA_FORMAT_UNK1D 0x0000001d
|
||||
#define NV50_ZETA_FORMAT_UNK1E 0x0000001e
|
||||
#define NV50_ZETA_FORMAT_UNK1F 0x0000001f
|
||||
#define NV50_QUERY__SIZE 0x00000010
|
||||
#define NV50_QUERY_COUNTER 0x00000000
|
||||
|
||||
#define NV50_QUERY_RES 0x00000004
|
||||
|
||||
#define NV50_QUERY_TIME 0x00000008
|
||||
|
||||
|
||||
#endif /* NV50_DEFS_XML */
|
||||
|
|
@ -25,32 +25,32 @@
|
|||
#include "nv50_context.h"
|
||||
|
||||
struct nv50_render_stage {
|
||||
struct draw_stage stage;
|
||||
struct nv50_context *nv50;
|
||||
struct draw_stage stage;
|
||||
struct nv50_context *nv50;
|
||||
};
|
||||
|
||||
static INLINE struct nv50_render_stage *
|
||||
nv50_render_stage(struct draw_stage *stage)
|
||||
{
|
||||
return (struct nv50_render_stage *)stage;
|
||||
return (struct nv50_render_stage *)stage;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_render_point(struct draw_stage *stage, struct prim_header *prim)
|
||||
{
|
||||
NOUVEAU_ERR("\n");
|
||||
NOUVEAU_ERR("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_render_line(struct draw_stage *stage, struct prim_header *prim)
|
||||
{
|
||||
NOUVEAU_ERR("\n");
|
||||
NOUVEAU_ERR("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_render_tri(struct draw_stage *stage, struct prim_header *prim)
|
||||
{
|
||||
NOUVEAU_ERR("\n");
|
||||
NOUVEAU_ERR("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -61,29 +61,28 @@ nv50_render_flush(struct draw_stage *stage, unsigned flags)
|
|||
static void
|
||||
nv50_render_reset_stipple_counter(struct draw_stage *stage)
|
||||
{
|
||||
NOUVEAU_ERR("\n");
|
||||
NOUVEAU_ERR("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_render_destroy(struct draw_stage *stage)
|
||||
{
|
||||
FREE(stage);
|
||||
FREE(stage);
|
||||
}
|
||||
|
||||
struct draw_stage *
|
||||
nv50_draw_render_stage(struct nv50_context *nv50)
|
||||
{
|
||||
struct nv50_render_stage *rs = CALLOC_STRUCT(nv50_render_stage);
|
||||
struct nv50_render_stage *rs = CALLOC_STRUCT(nv50_render_stage);
|
||||
|
||||
rs->nv50 = nv50;
|
||||
rs->stage.draw = nv50->draw;
|
||||
rs->stage.destroy = nv50_render_destroy;
|
||||
rs->stage.point = nv50_render_point;
|
||||
rs->stage.line = nv50_render_line;
|
||||
rs->stage.tri = nv50_render_tri;
|
||||
rs->stage.flush = nv50_render_flush;
|
||||
rs->stage.reset_stipple_counter = nv50_render_reset_stipple_counter;
|
||||
rs->nv50 = nv50;
|
||||
rs->stage.draw = nv50->draw;
|
||||
rs->stage.destroy = nv50_render_destroy;
|
||||
rs->stage.point = nv50_render_point;
|
||||
rs->stage.line = nv50_render_line;
|
||||
rs->stage.tri = nv50_render_tri;
|
||||
rs->stage.flush = nv50_render_flush;
|
||||
rs->stage.reset_stipple_counter = nv50_render_reset_stipple_counter;
|
||||
|
||||
return &rs->stage;
|
||||
return &rs->stage;
|
||||
}
|
||||
|
||||
|
|
|
|||
216
src/gallium/drivers/nv50/nv50_fence.c
Normal file
216
src/gallium/drivers/nv50/nv50_fence.c
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright 2010 Christoph Bumiller
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "nv50_fence.h"
|
||||
#include "nv50_context.h"
|
||||
#include "nv50_screen.h"
|
||||
|
||||
#ifdef PIPE_OS_UNIX
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
boolean
|
||||
nv50_screen_fence_new(struct nv50_screen *screen, struct nv50_fence **fence,
|
||||
boolean emit)
|
||||
{
|
||||
*fence = CALLOC_STRUCT(nv50_fence);
|
||||
if (!*fence)
|
||||
return FALSE;
|
||||
|
||||
(*fence)->screen = screen;
|
||||
(*fence)->ref = 1;
|
||||
|
||||
if (emit)
|
||||
nv50_fence_emit(*fence);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_fence_emit(struct nv50_fence *fence)
|
||||
{
|
||||
struct nv50_screen *screen = fence->screen;
|
||||
struct nouveau_channel *chan = screen->base.channel;
|
||||
|
||||
fence->sequence = ++screen->fence.sequence;
|
||||
|
||||
assert(fence->state == NV50_FENCE_STATE_AVAILABLE);
|
||||
|
||||
MARK_RING (chan, 5, 2);
|
||||
BEGIN_RING(chan, RING_3D(QUERY_ADDRESS_HIGH), 4);
|
||||
OUT_RELOCh(chan, screen->fence.bo, 0, NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, screen->fence.bo, 0, NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, fence->sequence);
|
||||
OUT_RING (chan,
|
||||
NV50_3D_QUERY_GET_MODE_WRITE_UNK0 |
|
||||
NV50_3D_QUERY_GET_UNK4 |
|
||||
NV50_3D_QUERY_GET_UNIT_CROP |
|
||||
NV50_3D_QUERY_GET_TYPE_QUERY |
|
||||
NV50_3D_QUERY_GET_QUERY_SELECT_ZERO |
|
||||
NV50_3D_QUERY_GET_SHORT);
|
||||
|
||||
|
||||
++fence->ref;
|
||||
|
||||
if (screen->fence.tail)
|
||||
screen->fence.tail->next = fence;
|
||||
else
|
||||
screen->fence.head = fence;
|
||||
|
||||
screen->fence.tail = fence;
|
||||
|
||||
fence->state = NV50_FENCE_STATE_EMITTED;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_fence_trigger_release_buffers(struct nv50_fence *fence);
|
||||
|
||||
void
|
||||
nv50_fence_del(struct nv50_fence *fence)
|
||||
{
|
||||
struct nv50_fence *it;
|
||||
struct nv50_screen *screen = fence->screen;
|
||||
|
||||
if (fence->state == NV50_FENCE_STATE_EMITTED ||
|
||||
fence->state == NV50_FENCE_STATE_FLUSHED) {
|
||||
if (fence == screen->fence.head) {
|
||||
screen->fence.head = fence->next;
|
||||
if (!screen->fence.head)
|
||||
screen->fence.tail = NULL;
|
||||
} else {
|
||||
for (it = screen->fence.head; it && it->next != fence; it = it->next);
|
||||
it->next = fence->next;
|
||||
if (screen->fence.tail == fence)
|
||||
screen->fence.tail = it;
|
||||
}
|
||||
}
|
||||
|
||||
if (fence->buffers) {
|
||||
debug_printf("WARNING: deleting fence with buffers "
|
||||
"still hooked to it !\n");
|
||||
nv50_fence_trigger_release_buffers(fence);
|
||||
}
|
||||
|
||||
FREE(fence);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_fence_trigger_release_buffers(struct nv50_fence *fence)
|
||||
{
|
||||
struct nv50_mm_allocation *alloc = fence->buffers;
|
||||
|
||||
while (alloc) {
|
||||
struct nv50_mm_allocation *next = alloc->next;
|
||||
nv50_mm_free(alloc);
|
||||
alloc = next;
|
||||
};
|
||||
fence->buffers = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_screen_fence_update(struct nv50_screen *screen, boolean flushed)
|
||||
{
|
||||
struct nv50_fence *fence;
|
||||
struct nv50_fence *next = NULL;
|
||||
uint32_t sequence = screen->fence.map[0];
|
||||
|
||||
if (screen->fence.sequence_ack == sequence)
|
||||
return;
|
||||
screen->fence.sequence_ack = sequence;
|
||||
|
||||
for (fence = screen->fence.head; fence; fence = next) {
|
||||
next = fence->next;
|
||||
sequence = fence->sequence;
|
||||
|
||||
fence->state = NV50_FENCE_STATE_SIGNALLED;
|
||||
|
||||
if (fence->buffers)
|
||||
nv50_fence_trigger_release_buffers(fence);
|
||||
|
||||
nv50_fence_reference(&fence, NULL);
|
||||
|
||||
if (sequence == screen->fence.sequence_ack)
|
||||
break;
|
||||
}
|
||||
screen->fence.head = next;
|
||||
if (!next)
|
||||
screen->fence.tail = NULL;
|
||||
|
||||
if (flushed) {
|
||||
for (fence = next; fence; fence = fence->next)
|
||||
fence->state = NV50_FENCE_STATE_FLUSHED;
|
||||
}
|
||||
}
|
||||
|
||||
#define NV50_FENCE_MAX_SPINS (1 << 31)
|
||||
|
||||
boolean
|
||||
nv50_fence_signalled(struct nv50_fence *fence)
|
||||
{
|
||||
struct nv50_screen *screen = fence->screen;
|
||||
|
||||
if (fence->state >= NV50_FENCE_STATE_EMITTED)
|
||||
nv50_screen_fence_update(screen, FALSE);
|
||||
|
||||
return fence->state == NV50_FENCE_STATE_SIGNALLED;
|
||||
}
|
||||
|
||||
boolean
|
||||
nv50_fence_wait(struct nv50_fence *fence)
|
||||
{
|
||||
struct nv50_screen *screen = fence->screen;
|
||||
uint32_t spins = 0;
|
||||
|
||||
if (fence->state < NV50_FENCE_STATE_EMITTED) {
|
||||
nv50_fence_emit(fence);
|
||||
|
||||
if (fence == screen->fence.current)
|
||||
nv50_screen_fence_new(screen, &screen->fence.current, FALSE);
|
||||
}
|
||||
if (fence->state < NV50_FENCE_STATE_FLUSHED)
|
||||
FIRE_RING(screen->base.channel);
|
||||
|
||||
do {
|
||||
nv50_screen_fence_update(screen, FALSE);
|
||||
|
||||
if (fence->state == NV50_FENCE_STATE_SIGNALLED)
|
||||
return TRUE;
|
||||
spins++;
|
||||
#ifdef PIPE_OS_UNIX
|
||||
if (!(spins % 8)) /* donate a few cycles */
|
||||
sched_yield();
|
||||
#endif
|
||||
} while (spins < NV50_FENCE_MAX_SPINS);
|
||||
|
||||
debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n",
|
||||
fence->sequence,
|
||||
screen->fence.sequence_ack, screen->fence.sequence);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_screen_fence_next(struct nv50_screen *screen)
|
||||
{
|
||||
nv50_fence_emit(screen->fence.current);
|
||||
nv50_screen_fence_new(screen, &screen->fence.current, FALSE);
|
||||
}
|
||||
49
src/gallium/drivers/nv50/nv50_fence.h
Normal file
49
src/gallium/drivers/nv50/nv50_fence.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
#ifndef __NV50_FENCE_H__
|
||||
#define __NV50_FENCE_H__
|
||||
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_double_list.h"
|
||||
|
||||
#define NV50_FENCE_STATE_AVAILABLE 0
|
||||
#define NV50_FENCE_STATE_EMITTED 1
|
||||
#define NV50_FENCE_STATE_FLUSHED 2
|
||||
#define NV50_FENCE_STATE_SIGNALLED 3
|
||||
|
||||
struct nv50_mm_allocation;
|
||||
|
||||
struct nv50_fence {
|
||||
struct nv50_fence *next;
|
||||
struct nv50_screen *screen;
|
||||
int state;
|
||||
int ref;
|
||||
uint32_t sequence;
|
||||
struct nv50_mm_allocation *buffers;
|
||||
};
|
||||
|
||||
void nv50_fence_emit(struct nv50_fence *);
|
||||
void nv50_fence_del(struct nv50_fence *);
|
||||
|
||||
boolean nv50_fence_wait(struct nv50_fence *);
|
||||
boolean nv50_fence_signalled(struct nv50_fence *);
|
||||
|
||||
static INLINE void
|
||||
nv50_fence_reference(struct nv50_fence **ref, struct nv50_fence *fence)
|
||||
{
|
||||
if (*ref) {
|
||||
if (--(*ref)->ref == 0)
|
||||
nv50_fence_del(*ref);
|
||||
}
|
||||
if (fence)
|
||||
++fence->ref;
|
||||
|
||||
*ref = fence;
|
||||
}
|
||||
|
||||
static INLINE struct nv50_fence *
|
||||
nv50_fence(struct pipe_fence_handle *fence)
|
||||
{
|
||||
return (struct nv50_fence *)fence;
|
||||
}
|
||||
|
||||
#endif // __NV50_FENCE_H__
|
||||
|
|
@ -21,26 +21,34 @@
|
|||
*/
|
||||
|
||||
#include "nv50_screen.h"
|
||||
#include "nv50_texture.h"
|
||||
#include "nv50_reg.h"
|
||||
#include "nv50_texture.xml.h"
|
||||
#include "nv50_defs.xml.h"
|
||||
#include "nv50_3d.xml.h"
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#define A_(cr, cg, cb, ca, t0, t1, t2, t3, sz, r) \
|
||||
NV50TIC_0_0_MAPR_##cr | NV50TIC_0_0_TYPER_##t0 | \
|
||||
NV50TIC_0_0_MAPG_##cg | NV50TIC_0_0_TYPEG_##t1 | \
|
||||
NV50TIC_0_0_MAPB_##cb | NV50TIC_0_0_TYPEB_##t2 | \
|
||||
NV50TIC_0_0_MAPA_##ca | NV50TIC_0_0_TYPEA_##t3 | \
|
||||
NV50TIC_0_0_FMT_##sz, \
|
||||
NV50TCL_VERTEX_ARRAY_ATTRIB_FORMAT_##sz | \
|
||||
NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_##t0 | \
|
||||
(NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_##t0 << 3) | (r << 31)
|
||||
#define A_(cr, cg, cb, ca, t0, t1, t2, t3, sz, r) \
|
||||
(NV50_TIC_MAP_##cr << NV50_TIC_0_MAPR__SHIFT) | \
|
||||
(NV50_TIC_TYPE_##t0 << NV50_TIC_0_TYPE0__SHIFT) | \
|
||||
(NV50_TIC_MAP_##cg << NV50_TIC_0_MAPG__SHIFT) | \
|
||||
(NV50_TIC_TYPE_##t1 << NV50_TIC_0_TYPE1__SHIFT) | \
|
||||
(NV50_TIC_MAP_##cb << NV50_TIC_0_MAPB__SHIFT) | \
|
||||
(NV50_TIC_TYPE_##t2 << NV50_TIC_0_TYPE2__SHIFT) | \
|
||||
(NV50_TIC_MAP_##ca << NV50_TIC_0_MAPA__SHIFT) | \
|
||||
(NV50_TIC_TYPE_##t3 << NV50_TIC_0_TYPE3__SHIFT) | \
|
||||
NV50_TIC_0_FMT_##sz, \
|
||||
NV50_3D_VERTEX_ARRAY_ATTRIB_FORMAT_##sz | \
|
||||
NV50_3D_VERTEX_ARRAY_ATTRIB_TYPE_##t0 | (r << 31)
|
||||
|
||||
#define B_(cr, cg, cb, ca, t0, t1, t2, t3, sz, r) \
|
||||
NV50TIC_0_0_MAPR_##cr | NV50TIC_0_0_TYPER_##t0 | \
|
||||
NV50TIC_0_0_MAPG_##cg | NV50TIC_0_0_TYPEG_##t1 | \
|
||||
NV50TIC_0_0_MAPB_##cb | NV50TIC_0_0_TYPEB_##t2 | \
|
||||
NV50TIC_0_0_MAPA_##ca | NV50TIC_0_0_TYPEA_##t3 | \
|
||||
NV50TIC_0_0_FMT_##sz, 0
|
||||
#define B_(cr, cg, cb, ca, t0, t1, t2, t3, sz, r) \
|
||||
(NV50_TIC_MAP_##cr << NV50_TIC_0_MAPR__SHIFT) | \
|
||||
(NV50_TIC_TYPE_##t0 << NV50_TIC_0_TYPE0__SHIFT) | \
|
||||
(NV50_TIC_MAP_##cg << NV50_TIC_0_MAPG__SHIFT) | \
|
||||
(NV50_TIC_TYPE_##t1 << NV50_TIC_0_TYPE1__SHIFT) | \
|
||||
(NV50_TIC_MAP_##cb << NV50_TIC_0_MAPB__SHIFT) | \
|
||||
(NV50_TIC_TYPE_##t2 << NV50_TIC_0_TYPE2__SHIFT) | \
|
||||
(NV50_TIC_MAP_##ca << NV50_TIC_0_MAPA__SHIFT) | \
|
||||
(NV50_TIC_TYPE_##t3 << NV50_TIC_0_TYPE3__SHIFT) | \
|
||||
NV50_TIC_0_FMT_##sz, 0
|
||||
|
||||
#define VERTEX_BUFFER PIPE_BIND_VERTEX_BUFFER
|
||||
#define SAMPLER_VIEW PIPE_BIND_SAMPLER_VIEW
|
||||
|
|
@ -49,98 +57,96 @@
|
|||
#define SCANOUT PIPE_BIND_SCANOUT
|
||||
|
||||
/* for vertex buffers: */
|
||||
#define NV50TIC_0_0_FMT_8_8_8 NV50TIC_0_0_FMT_8_8_8_8
|
||||
#define NV50TIC_0_0_FMT_16_16_16 NV50TIC_0_0_FMT_16_16_16_16
|
||||
#define NV50TIC_0_0_FMT_32_32_32 NV50TIC_0_0_FMT_32_32_32_32
|
||||
|
||||
/* NOTE: using NV50_2D_DST_FORMAT for substitute formats used with 2D engine */
|
||||
#define NV50_TIC_0_FMT_8_8_8 NV50_TIC_0_FMT_8_8_8_8
|
||||
#define NV50_TIC_0_FMT_16_16_16 NV50_TIC_0_FMT_16_16_16_16
|
||||
#define NV50_TIC_0_FMT_32_32_32 NV50_TIC_0_FMT_32_32_32_32
|
||||
|
||||
const struct nv50_format nv50_format_table[PIPE_FORMAT_COUNT] =
|
||||
{
|
||||
/* COMMON FORMATS */
|
||||
|
||||
[PIPE_FORMAT_B8G8R8A8_UNORM] = { NV50TCL_RT_FORMAT_A8R8G8B8_UNORM,
|
||||
[PIPE_FORMAT_B8G8R8A8_UNORM] = { NV50_SURFACE_FORMAT_A8R8G8B8_UNORM,
|
||||
A_(C2, C1, C0, C3, UNORM, UNORM, UNORM, UNORM, 8_8_8_8, 1),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET | SCANOUT },
|
||||
|
||||
[PIPE_FORMAT_B8G8R8X8_UNORM] = { NV50TCL_RT_FORMAT_X8R8G8B8_UNORM,
|
||||
[PIPE_FORMAT_B8G8R8X8_UNORM] = { NV50_SURFACE_FORMAT_X8R8G8B8_UNORM,
|
||||
A_(C2, C1, C0, ONE, UNORM, UNORM, UNORM, UNORM, 8_8_8_8, 1),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET | SCANOUT },
|
||||
|
||||
[PIPE_FORMAT_B8G8R8A8_SRGB] = { NV50TCL_RT_FORMAT_A8R8G8B8_SRGB,
|
||||
[PIPE_FORMAT_B8G8R8A8_SRGB] = { NV50_SURFACE_FORMAT_A8R8G8B8_SRGB,
|
||||
A_(C2, C1, C0, C3, UNORM, UNORM, UNORM, UNORM, 8_8_8_8, 1),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_B8G8R8X8_SRGB] = { NV50TCL_RT_FORMAT_X8R8G8B8_SRGB,
|
||||
[PIPE_FORMAT_B8G8R8X8_SRGB] = { NV50_SURFACE_FORMAT_X8R8G8B8_SRGB,
|
||||
A_(C2, C1, C0, ONE, UNORM, UNORM, UNORM, UNORM, 8_8_8_8, 1),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_B5G6R5_UNORM] = { NV50TCL_RT_FORMAT_R5G6B5_UNORM,
|
||||
[PIPE_FORMAT_B5G6R5_UNORM] = { NV50_SURFACE_FORMAT_R5G6B5_UNORM,
|
||||
B_(C2, C1, C0, ONE, UNORM, UNORM, UNORM, UNORM, 5_6_5, 1),
|
||||
SAMPLER_VIEW | RENDER_TARGET | SCANOUT },
|
||||
|
||||
[PIPE_FORMAT_B5G5R5A1_UNORM] = { NV50TCL_RT_FORMAT_A1R5G5B5_UNORM,
|
||||
[PIPE_FORMAT_B5G5R5A1_UNORM] = { NV50_SURFACE_FORMAT_A1R5G5B5_UNORM,
|
||||
B_(C2, C1, C0, C3, UNORM, UNORM, UNORM, UNORM, 1_5_5_5, 1),
|
||||
SAMPLER_VIEW | RENDER_TARGET | SCANOUT },
|
||||
|
||||
[PIPE_FORMAT_B4G4R4A4_UNORM] = { NV50_2D_DST_FORMAT_R16_UNORM,
|
||||
[PIPE_FORMAT_B4G4R4A4_UNORM] = { NV50_SURFACE_FORMAT_R16_UNORM,
|
||||
B_(C2, C1, C0, C3, UNORM, UNORM, UNORM, UNORM, 4_4_4_4, 1),
|
||||
SAMPLER_VIEW },
|
||||
|
||||
[PIPE_FORMAT_R10G10B10A2_UNORM] = { NV50TCL_RT_FORMAT_A2B10G10R10_UNORM,
|
||||
[PIPE_FORMAT_R10G10B10A2_UNORM] = { NV50_SURFACE_FORMAT_A2B10G10R10_UNORM,
|
||||
A_(C0, C1, C2, C3, UNORM, UNORM, UNORM, UNORM, 2_10_10_10, 0),
|
||||
SAMPLER_VIEW | RENDER_TARGET | VERTEX_BUFFER | SCANOUT },
|
||||
|
||||
[PIPE_FORMAT_B10G10R10A2_UNORM] = { NV50TCL_RT_FORMAT_A2R10G10B10_UNORM,
|
||||
[PIPE_FORMAT_B10G10R10A2_UNORM] = { NV50_SURFACE_FORMAT_A2R10G10B10_UNORM,
|
||||
A_(C2, C1, C0, C3, UNORM, UNORM, UNORM, UNORM, 2_10_10_10, 1),
|
||||
SAMPLER_VIEW | RENDER_TARGET | VERTEX_BUFFER },
|
||||
|
||||
/* DEPTH/STENCIL FORMATS */
|
||||
|
||||
[PIPE_FORMAT_Z16_UNORM] = { NV50TCL_ZETA_FORMAT_Z16_UNORM,
|
||||
B_(C0, C0, C0, ONE, UNORM, UINT, UINT, UINT, 16_DEPTH, 0),
|
||||
[PIPE_FORMAT_Z16_UNORM] = { NV50_ZETA_FORMAT_Z16_UNORM,
|
||||
B_(C0, C0, C0, ONE, UNORM, UINT, UINT, UINT, 16_ZETA, 0),
|
||||
SAMPLER_VIEW | DEPTH_STENCIL },
|
||||
|
||||
[PIPE_FORMAT_Z24_UNORM_S8_USCALED] = { NV50TCL_ZETA_FORMAT_S8Z24_UNORM,
|
||||
[PIPE_FORMAT_Z24_UNORM_S8_USCALED] = { NV50_ZETA_FORMAT_S8Z24_UNORM,
|
||||
B_(C0, C0, C0, ONE, UNORM, UINT, UINT, UINT, 8_24, 0),
|
||||
SAMPLER_VIEW | DEPTH_STENCIL },
|
||||
|
||||
[PIPE_FORMAT_Z24X8_UNORM] = { NV50TCL_ZETA_FORMAT_X8Z24_UNORM,
|
||||
[PIPE_FORMAT_Z24X8_UNORM] = { NV50_ZETA_FORMAT_X8Z24_UNORM,
|
||||
B_(C0, C0, C0, ONE, UNORM, UINT, UINT, UINT, 8_24, 0),
|
||||
SAMPLER_VIEW | DEPTH_STENCIL },
|
||||
|
||||
[PIPE_FORMAT_S8_USCALED_Z24_UNORM] = { NV50TCL_ZETA_FORMAT_S8Z24_UNORM,
|
||||
[PIPE_FORMAT_S8_USCALED_Z24_UNORM] = { NV50_ZETA_FORMAT_Z24S8_UNORM,
|
||||
B_(C1, C1, C1, ONE, UINT, UNORM, UINT, UINT, 24_8, 0),
|
||||
SAMPLER_VIEW | DEPTH_STENCIL },
|
||||
|
||||
[PIPE_FORMAT_Z32_FLOAT] = { NV50TCL_ZETA_FORMAT_Z32_FLOAT,
|
||||
B_(C0, C0, C0, ONE, FLOAT, UINT, UINT, UINT, 32_DEPTH, 0),
|
||||
[PIPE_FORMAT_Z32_FLOAT] = { NV50_ZETA_FORMAT_Z32_FLOAT,
|
||||
B_(C0, C0, C0, ONE, FLOAT, UINT, UINT, UINT, 32_ZETA, 0),
|
||||
SAMPLER_VIEW | DEPTH_STENCIL },
|
||||
|
||||
[PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED] = {
|
||||
NV50TCL_ZETA_FORMAT_Z32_FLOAT_X24S8_UNORM,
|
||||
NV50_ZETA_FORMAT_Z32_FLOAT_X24S8_UNORM,
|
||||
B_(C0, C0, C0, ONE, FLOAT, UINT, UINT, UINT, 32_8, 0),
|
||||
SAMPLER_VIEW | DEPTH_STENCIL },
|
||||
|
||||
/* LUMINANCE, ALPHA, INTENSITY */
|
||||
|
||||
[PIPE_FORMAT_L8_UNORM] = { NV50_2D_DST_FORMAT_R8_UNORM,
|
||||
[PIPE_FORMAT_L8_UNORM] = { NV50_SURFACE_FORMAT_R8_UNORM,
|
||||
A_(C0, C0, C0, ONE, UNORM, UNORM, UNORM, UNORM, 8, 0),
|
||||
SAMPLER_VIEW },
|
||||
|
||||
[PIPE_FORMAT_L8_SRGB] = { NV50_2D_DST_FORMAT_R8_UNORM,
|
||||
[PIPE_FORMAT_L8_SRGB] = { NV50_SURFACE_FORMAT_R8_UNORM,
|
||||
A_(C0, C0, C0, ONE, UNORM, UNORM, UNORM, UNORM, 8, 0),
|
||||
SAMPLER_VIEW },
|
||||
|
||||
[PIPE_FORMAT_I8_UNORM] = { NV50_2D_DST_FORMAT_R8_UNORM,
|
||||
[PIPE_FORMAT_I8_UNORM] = { NV50_SURFACE_FORMAT_R8_UNORM,
|
||||
A_(C0, C0, C0, C0, UNORM, UNORM, UNORM, UNORM, 8, 0),
|
||||
SAMPLER_VIEW },
|
||||
|
||||
[PIPE_FORMAT_A8_UNORM] = { NV50TCL_RT_FORMAT_A8_UNORM,
|
||||
[PIPE_FORMAT_A8_UNORM] = { NV50_SURFACE_FORMAT_A8_UNORM,
|
||||
A_(ZERO, ZERO, ZERO, C0, UNORM, UNORM, UNORM, UNORM, 8, 0),
|
||||
SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_L8A8_UNORM] = { NV50_2D_DST_FORMAT_R16_UNORM,
|
||||
[PIPE_FORMAT_L8A8_UNORM] = { NV50_SURFACE_FORMAT_R16_UNORM,
|
||||
A_(C0, C0, C0, C1, UNORM, UNORM, UNORM, UNORM, 8_8, 0),
|
||||
SAMPLER_VIEW },
|
||||
|
||||
|
|
@ -184,48 +190,48 @@ const struct nv50_format nv50_format_table[PIPE_FORMAT_COUNT] =
|
|||
|
||||
/* FLOAT 16 */
|
||||
|
||||
[PIPE_FORMAT_R16G16B16A16_FLOAT] = { NV50TCL_RT_FORMAT_R16G16B16A16_FLOAT,
|
||||
[PIPE_FORMAT_R16G16B16A16_FLOAT] = { NV50_SURFACE_FORMAT_R16G16B16A16_FLOAT,
|
||||
A_(C0, C1, C2, C3, FLOAT, FLOAT, FLOAT, FLOAT, 16_16_16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R16G16B16_FLOAT] = { NV50TCL_RT_FORMAT_R16G16B16X16_FLOAT,
|
||||
[PIPE_FORMAT_R16G16B16_FLOAT] = { NV50_SURFACE_FORMAT_R16G16B16X16_FLOAT,
|
||||
A_(C0, C1, C2, ONE, FLOAT, FLOAT, FLOAT, FLOAT, 16_16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R16G16_FLOAT] = { NV50TCL_RT_FORMAT_R16G16_FLOAT,
|
||||
[PIPE_FORMAT_R16G16_FLOAT] = { NV50_SURFACE_FORMAT_R16G16_FLOAT,
|
||||
A_(C0, C1, ZERO, ONE, FLOAT, FLOAT, FLOAT, FLOAT, 16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R16_FLOAT] = { NV50TCL_RT_FORMAT_R16_FLOAT,
|
||||
[PIPE_FORMAT_R16_FLOAT] = { NV50_SURFACE_FORMAT_R16_FLOAT,
|
||||
A_(C0, ZERO, ZERO, ONE, FLOAT, FLOAT, FLOAT, FLOAT, 16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
/* FLOAT 32 */
|
||||
|
||||
[PIPE_FORMAT_R32G32B32A32_FLOAT] = { NV50TCL_RT_FORMAT_R32G32B32A32_FLOAT,
|
||||
[PIPE_FORMAT_R32G32B32A32_FLOAT] = { NV50_SURFACE_FORMAT_R32G32B32A32_FLOAT,
|
||||
A_(C0, C1, C2, C3, FLOAT, FLOAT, FLOAT, FLOAT, 32_32_32_32, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R32G32B32_FLOAT] = { NV50TCL_RT_FORMAT_R32G32B32X32_FLOAT,
|
||||
[PIPE_FORMAT_R32G32B32_FLOAT] = { NV50_SURFACE_FORMAT_R32G32B32X32_FLOAT,
|
||||
A_(C0, C1, C2, ONE, FLOAT, FLOAT, FLOAT, FLOAT, 32_32_32, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R32G32_FLOAT] = { NV50TCL_RT_FORMAT_R32G32_FLOAT,
|
||||
[PIPE_FORMAT_R32G32_FLOAT] = { NV50_SURFACE_FORMAT_R32G32_FLOAT,
|
||||
A_(C0, C1, ZERO, ONE, FLOAT, FLOAT, FLOAT, FLOAT, 32_32, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R32_FLOAT] = { NV50TCL_RT_FORMAT_R32_FLOAT,
|
||||
[PIPE_FORMAT_R32_FLOAT] = { NV50_SURFACE_FORMAT_R32_FLOAT,
|
||||
A_(C0, ZERO, ZERO, ONE, FLOAT, FLOAT, FLOAT, FLOAT, 32, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
/* ODD FORMATS */
|
||||
|
||||
[PIPE_FORMAT_R11G11B10_FLOAT] = { NV50TCL_RT_FORMAT_B10G11R11_FLOAT,
|
||||
[PIPE_FORMAT_R11G11B10_FLOAT] = { NV50_SURFACE_FORMAT_B10G11R11_FLOAT,
|
||||
B_(C0, C1, C2, ONE, FLOAT, FLOAT, FLOAT, FLOAT, 10_11_11, 0),
|
||||
SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R9G9B9E5_FLOAT] = { 0,
|
||||
B_(C0, C1, C2, ONE, FLOAT, FLOAT, FLOAT, FLOAT, 5_9_9_9, 0),
|
||||
B_(C0, C1, C2, ONE, FLOAT, FLOAT, FLOAT, FLOAT, E5_9_9_9, 0),
|
||||
SAMPLER_VIEW },
|
||||
|
||||
/* SNORM 32 */
|
||||
|
|
@ -266,7 +272,7 @@ const struct nv50_format nv50_format_table[PIPE_FORMAT_COUNT] =
|
|||
|
||||
/* SNORM 16 */
|
||||
|
||||
[PIPE_FORMAT_R16G16B16A16_SNORM] = { NV50TCL_RT_FORMAT_R16G16B16A16_SNORM,
|
||||
[PIPE_FORMAT_R16G16B16A16_SNORM] = { NV50_SURFACE_FORMAT_R16G16B16A16_SNORM,
|
||||
A_(C0, C1, C2, C3, SNORM, SNORM, SNORM, SNORM, 16_16_16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
|
|
@ -274,17 +280,17 @@ const struct nv50_format nv50_format_table[PIPE_FORMAT_COUNT] =
|
|||
A_(C0, C1, C2, ONE, SNORM, SNORM, SNORM, SNORM, 16_16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW },
|
||||
|
||||
[PIPE_FORMAT_R16G16_SNORM] = { NV50TCL_RT_FORMAT_R16G16_SNORM,
|
||||
[PIPE_FORMAT_R16G16_SNORM] = { NV50_SURFACE_FORMAT_R16G16_SNORM,
|
||||
A_(C0, C1, C2, C3, SNORM, SNORM, SNORM, SNORM, 16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R16_SNORM] = { NV50TCL_RT_FORMAT_R16_SNORM,
|
||||
[PIPE_FORMAT_R16_SNORM] = { NV50_SURFACE_FORMAT_R16_SNORM,
|
||||
A_(C0, ZERO, ZERO, ONE, SNORM, SNORM, SNORM, SNORM, 16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
/* UNORM 16 */
|
||||
|
||||
[PIPE_FORMAT_R16G16B16A16_UNORM] = { NV50TCL_RT_FORMAT_R16G16B16A16_UNORM,
|
||||
[PIPE_FORMAT_R16G16B16A16_UNORM] = { NV50_SURFACE_FORMAT_R16G16B16A16_UNORM,
|
||||
A_(C0, C1, C2, C3, UNORM, UNORM, UNORM, UNORM, 16_16_16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
|
|
@ -292,17 +298,17 @@ const struct nv50_format nv50_format_table[PIPE_FORMAT_COUNT] =
|
|||
A_(C0, C1, C2, ONE, UNORM, UNORM, UNORM, UNORM, 16_16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW },
|
||||
|
||||
[PIPE_FORMAT_R16G16_UNORM] = { NV50TCL_RT_FORMAT_R16G16_UNORM,
|
||||
[PIPE_FORMAT_R16G16_UNORM] = { NV50_SURFACE_FORMAT_R16G16_UNORM,
|
||||
A_(C0, C1, C2, C3, UNORM, UNORM, UNORM, UNORM, 16_16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R16_UNORM] = { NV50TCL_RT_FORMAT_R16_UNORM,
|
||||
[PIPE_FORMAT_R16_UNORM] = { NV50_SURFACE_FORMAT_R16_UNORM,
|
||||
A_(C0, ZERO, ZERO, ONE, UNORM, UNORM, UNORM, UNORM, 16, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
/* SNORM 8 */
|
||||
|
||||
[PIPE_FORMAT_R8G8B8A8_SNORM] = { NV50TCL_RT_FORMAT_A8B8G8R8_SNORM,
|
||||
[PIPE_FORMAT_R8G8B8A8_SNORM] = { NV50_SURFACE_FORMAT_A8B8G8R8_SNORM,
|
||||
A_(C0, C1, C2, C3, SNORM, SNORM, SNORM, SNORM, 8_8_8_8, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
|
|
@ -310,37 +316,37 @@ const struct nv50_format nv50_format_table[PIPE_FORMAT_COUNT] =
|
|||
A_(C0, C1, C2, ONE, SNORM, SNORM, SNORM, SNORM, 8_8_8, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW },
|
||||
|
||||
[PIPE_FORMAT_R8G8_SNORM] = { NV50TCL_RT_FORMAT_R8G8_SNORM,
|
||||
[PIPE_FORMAT_R8G8_SNORM] = { NV50_SURFACE_FORMAT_R8G8_SNORM,
|
||||
A_(C0, C1, ZERO, ONE, SNORM, SNORM, SNORM, SNORM, 8_8, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R8_SNORM] = { NV50TCL_RT_FORMAT_R8_SNORM,
|
||||
[PIPE_FORMAT_R8_SNORM] = { NV50_SURFACE_FORMAT_R8_SNORM,
|
||||
A_(C0, ZERO, ZERO, ONE, SNORM, SNORM, SNORM, SNORM, 8, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
/* UNORM 8 */
|
||||
|
||||
[PIPE_FORMAT_R8G8B8A8_UNORM] = { NV50TCL_RT_FORMAT_A8B8G8R8_UNORM,
|
||||
[PIPE_FORMAT_R8G8B8A8_UNORM] = { NV50_SURFACE_FORMAT_A8B8G8R8_UNORM,
|
||||
A_(C0, C1, C2, C3, UNORM, UNORM, UNORM, UNORM, 8_8_8_8, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R8G8B8A8_SRGB] = { NV50TCL_RT_FORMAT_A8B8G8R8_SRGB,
|
||||
[PIPE_FORMAT_R8G8B8A8_SRGB] = { NV50_SURFACE_FORMAT_A8B8G8R8_SRGB,
|
||||
A_(C0, C1, C2, C3, UNORM, UNORM, UNORM, UNORM, 8_8_8_8, 0),
|
||||
SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R8G8B8_UNORM] = { NV50TCL_RT_FORMAT_X8B8G8R8_UNORM,
|
||||
[PIPE_FORMAT_R8G8B8_UNORM] = { NV50_SURFACE_FORMAT_X8B8G8R8_UNORM,
|
||||
A_(C0, C1, C2, ONE, UNORM, UNORM, UNORM, UNORM, 8_8_8, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R8G8B8_SRGB] = { NV50TCL_RT_FORMAT_X8B8G8R8_SRGB,
|
||||
[PIPE_FORMAT_R8G8B8_SRGB] = { NV50_SURFACE_FORMAT_X8B8G8R8_SRGB,
|
||||
A_(C0, C1, C2, ONE, UNORM, UNORM, UNORM, UNORM, 8_8_8, 0),
|
||||
SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R8G8_UNORM] = { NV50TCL_RT_FORMAT_R8G8_UNORM,
|
||||
[PIPE_FORMAT_R8G8_UNORM] = { NV50_SURFACE_FORMAT_R8G8_UNORM,
|
||||
A_(C0, C1, ZERO, ONE, UNORM, UNORM, UNORM, UNORM, 8_8, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
[PIPE_FORMAT_R8_UNORM] = { NV50TCL_RT_FORMAT_R8_UNORM,
|
||||
[PIPE_FORMAT_R8_UNORM] = { NV50_SURFACE_FORMAT_R8_UNORM,
|
||||
A_(C0, ZERO, ZERO, ONE, UNORM, UNORM, UNORM, UNORM, 8, 0),
|
||||
VERTEX_BUFFER | SAMPLER_VIEW | RENDER_TARGET },
|
||||
|
||||
|
|
|
|||
|
|
@ -29,300 +29,288 @@
|
|||
#include "nv50_resource.h"
|
||||
#include "nv50_transfer.h"
|
||||
|
||||
/* The restrictions in tile mode selection probably aren't necessary. */
|
||||
static INLINE uint32_t
|
||||
get_tile_mode(unsigned ny, unsigned d)
|
||||
get_tile_dims(unsigned nx, unsigned ny, unsigned nz)
|
||||
{
|
||||
uint32_t tile_mode = 0x00;
|
||||
uint32_t tile_mode = 0x00;
|
||||
|
||||
if (ny > 32) tile_mode = 0x04; /* height 64 tiles */
|
||||
else
|
||||
if (ny > 16) tile_mode = 0x03; /* height 32 tiles */
|
||||
else
|
||||
if (ny > 8) tile_mode = 0x02; /* height 16 tiles */
|
||||
else
|
||||
if (ny > 4) tile_mode = 0x01; /* height 8 tiles */
|
||||
if (ny > 32) tile_mode = 0x04; /* height 128 tiles */
|
||||
else
|
||||
if (ny > 16) tile_mode = 0x03; /* height 64 tiles */
|
||||
else
|
||||
if (ny > 8) tile_mode = 0x02; /* height 32 tiles */
|
||||
else
|
||||
if (ny > 4) tile_mode = 0x01; /* height 16 tiles */
|
||||
|
||||
if (d == 1)
|
||||
return tile_mode;
|
||||
else
|
||||
if (tile_mode > 0x02)
|
||||
tile_mode = 0x02;
|
||||
if (nz == 1)
|
||||
return tile_mode;
|
||||
else
|
||||
if (tile_mode > 0x02)
|
||||
tile_mode = 0x02;
|
||||
|
||||
if (d > 16 && tile_mode < 0x02)
|
||||
return tile_mode | 0x50; /* depth 32 tiles */
|
||||
if (d > 8) return tile_mode | 0x40; /* depth 16 tiles */
|
||||
if (d > 4) return tile_mode | 0x30; /* depth 8 tiles */
|
||||
if (d > 2) return tile_mode | 0x20; /* depth 4 tiles */
|
||||
if (nz > 16 && tile_mode < 0x02)
|
||||
return tile_mode | 0x50; /* depth 32 tiles */
|
||||
if (nz > 8) return tile_mode | 0x40; /* depth 16 tiles */
|
||||
if (nz > 4) return tile_mode | 0x30; /* depth 8 tiles */
|
||||
if (nz > 2) return tile_mode | 0x20; /* depth 4 tiles */
|
||||
|
||||
return tile_mode | 0x10;
|
||||
return tile_mode | 0x10;
|
||||
}
|
||||
|
||||
static INLINE unsigned
|
||||
get_zslice_offset(unsigned tile_mode, unsigned z, unsigned pitch, unsigned nb_h)
|
||||
calc_zslice_offset(uint32_t tile_mode, unsigned z, unsigned pitch, unsigned nbh)
|
||||
{
|
||||
unsigned tile_h = get_tile_height(tile_mode);
|
||||
unsigned tile_d = get_tile_depth(tile_mode);
|
||||
unsigned tile_h = NV50_TILE_HEIGHT(tile_mode);
|
||||
unsigned tile_d_shift = NV50_TILE_DIM_SHIFT(tile_mode, 2);
|
||||
unsigned tile_d = 1 << tile_d_shift;
|
||||
|
||||
/* pitch_2d == to next slice within this volume-tile */
|
||||
/* pitch_3d == size (in bytes) of a volume-tile */
|
||||
unsigned pitch_2d = tile_h * 64;
|
||||
unsigned pitch_3d = tile_d * align(nb_h, tile_h) * pitch;
|
||||
/* stride_2d == to next slice within this volume tile */
|
||||
/* stride_3d == size (in bytes) of a volume tile */
|
||||
unsigned stride_2d = tile_h * NV50_TILE_PITCH(tile_mode);
|
||||
unsigned stride_3d = tile_d * align(nbh, tile_h) * pitch;
|
||||
|
||||
return (z % tile_d) * pitch_2d + (z / tile_d) * pitch_3d;
|
||||
return (z & (tile_d - 1)) * stride_2d + (z >> tile_d_shift) * stride_3d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
nv50_miptree_destroy(struct pipe_screen *pscreen,
|
||||
struct pipe_resource *pt)
|
||||
nv50_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
|
||||
{
|
||||
struct nv50_miptree *mt = nv50_miptree(pt);
|
||||
unsigned l;
|
||||
struct nv50_miptree *mt = nv50_miptree(pt);
|
||||
|
||||
for (l = 0; l <= pt->last_level; ++l)
|
||||
FREE(mt->level[l].image_offset);
|
||||
nouveau_screen_bo_release(pscreen, mt->base.bo);
|
||||
|
||||
nouveau_screen_bo_release(pscreen, mt->base.bo);
|
||||
FREE(mt);
|
||||
FREE(mt);
|
||||
}
|
||||
|
||||
static boolean
|
||||
nv50_miptree_get_handle(struct pipe_screen *pscreen,
|
||||
struct pipe_resource *pt,
|
||||
struct winsys_handle *whandle)
|
||||
struct pipe_resource *pt,
|
||||
struct winsys_handle *whandle)
|
||||
{
|
||||
struct nv50_miptree *mt = nv50_miptree(pt);
|
||||
unsigned stride;
|
||||
struct nv50_miptree *mt = nv50_miptree(pt);
|
||||
unsigned stride;
|
||||
|
||||
if (!mt || !mt->base.bo)
|
||||
return FALSE;
|
||||
|
||||
if (!mt || !mt->base.bo)
|
||||
return FALSE;
|
||||
stride = util_format_get_stride(mt->base.base.format,
|
||||
mt->base.base.width0);
|
||||
|
||||
stride = util_format_get_stride(mt->base.base.format,
|
||||
mt->base.base.width0);
|
||||
|
||||
return nouveau_screen_bo_get_handle(pscreen,
|
||||
mt->base.bo,
|
||||
stride,
|
||||
whandle);
|
||||
return nouveau_screen_bo_get_handle(pscreen,
|
||||
mt->base.bo,
|
||||
stride,
|
||||
whandle);
|
||||
}
|
||||
|
||||
|
||||
const struct u_resource_vtbl nv50_miptree_vtbl =
|
||||
{
|
||||
nv50_miptree_get_handle, /* get_handle */
|
||||
nv50_miptree_destroy, /* resource_destroy */
|
||||
NULL, /* is_resource_referenced */
|
||||
nv50_miptree_transfer_new, /* get_transfer */
|
||||
nv50_miptree_transfer_del, /* transfer_destroy */
|
||||
nv50_miptree_get_handle, /* get_handle */
|
||||
nv50_miptree_destroy, /* resource_destroy */
|
||||
NULL, /* is_resource_referenced */
|
||||
nv50_miptree_transfer_new, /* get_transfer */
|
||||
nv50_miptree_transfer_del, /* transfer_destroy */
|
||||
nv50_miptree_transfer_map, /* transfer_map */
|
||||
u_default_transfer_flush_region, /* transfer_flush_region */
|
||||
nv50_miptree_transfer_unmap, /* transfer_unmap */
|
||||
u_default_transfer_inline_write /* transfer_inline_write */
|
||||
u_default_transfer_flush_region, /* transfer_flush_region */
|
||||
nv50_miptree_transfer_unmap, /* transfer_unmap */
|
||||
u_default_transfer_inline_write /* transfer_inline_write */
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct pipe_resource *
|
||||
nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *tmp)
|
||||
nv50_miptree_create(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *templ)
|
||||
{
|
||||
struct nouveau_device *dev = nouveau_screen(pscreen)->device;
|
||||
struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
|
||||
struct pipe_resource *pt = &mt->base.base;
|
||||
unsigned width = tmp->width0, height = tmp->height0;
|
||||
unsigned depth = tmp->depth0, image_alignment;
|
||||
uint32_t tile_flags;
|
||||
int ret, i, l;
|
||||
struct nouveau_device *dev = nouveau_screen(pscreen)->device;
|
||||
struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
|
||||
struct pipe_resource *pt = &mt->base.base;
|
||||
int ret;
|
||||
unsigned w, h, d, l, alloc_size;
|
||||
uint32_t tile_flags;
|
||||
|
||||
if (!mt)
|
||||
return NULL;
|
||||
if (!mt)
|
||||
return NULL;
|
||||
|
||||
*pt = *tmp;
|
||||
mt->base.vtbl = &nv50_miptree_vtbl;
|
||||
pipe_reference_init(&pt->reference, 1);
|
||||
pt->screen = pscreen;
|
||||
mt->base.vtbl = &nv50_miptree_vtbl;
|
||||
*pt = *templ;
|
||||
pipe_reference_init(&pt->reference, 1);
|
||||
pt->screen = pscreen;
|
||||
|
||||
switch (pt->format) {
|
||||
case PIPE_FORMAT_Z32_FLOAT:
|
||||
tile_flags = 0x4800;
|
||||
break;
|
||||
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
|
||||
tile_flags = 0x1800;
|
||||
break;
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
tile_flags = 0x6c00;
|
||||
break;
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
|
||||
tile_flags = 0x2800;
|
||||
break;
|
||||
case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
|
||||
tile_flags = 0xe000;
|
||||
break;
|
||||
case PIPE_FORMAT_R32G32B32A32_FLOAT:
|
||||
case PIPE_FORMAT_R32G32B32_FLOAT:
|
||||
tile_flags = 0x7400;
|
||||
break;
|
||||
default:
|
||||
if ((pt->bind & PIPE_BIND_SCANOUT) &&
|
||||
util_format_get_blocksizebits(pt->format) == 32)
|
||||
tile_flags = 0x7a00;
|
||||
else
|
||||
tile_flags = 0x7000;
|
||||
break;
|
||||
}
|
||||
mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
|
||||
|
||||
/* XXX: texture arrays */
|
||||
mt->image_nr = (pt->target == PIPE_TEXTURE_CUBE) ? 6 : 1;
|
||||
w = pt->width0;
|
||||
h = pt->height0;
|
||||
d = mt->layout_3d ? pt->depth0 : 1;
|
||||
|
||||
for (l = 0; l <= pt->last_level; l++) {
|
||||
struct nv50_miptree_level *lvl = &mt->level[l];
|
||||
unsigned nblocksy = util_format_get_nblocksy(pt->format, height);
|
||||
switch (pt->format) {
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
tile_flags = 0x6c00;
|
||||
break;
|
||||
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
|
||||
tile_flags = 0x1800;
|
||||
break;
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
|
||||
tile_flags = 0x2800;
|
||||
break;
|
||||
case PIPE_FORMAT_R32G32B32A32_FLOAT:
|
||||
case PIPE_FORMAT_R32G32B32_FLOAT:
|
||||
tile_flags = 0x7400;
|
||||
break;
|
||||
case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
|
||||
tile_flags = 0x6000;
|
||||
break;
|
||||
case PIPE_FORMAT_R16G16B16A16_UNORM:
|
||||
tile_flags = 0xe900; /* COMPRESSED */
|
||||
break;
|
||||
default:
|
||||
if ((pt->bind & PIPE_BIND_SCANOUT) &&
|
||||
util_format_get_blocksizebits(pt->format) == 32)
|
||||
tile_flags = 0x7a00;
|
||||
else
|
||||
tile_flags = 0x7000;
|
||||
break;
|
||||
}
|
||||
|
||||
lvl->image_offset = CALLOC(mt->image_nr, sizeof(int));
|
||||
lvl->pitch = align(util_format_get_stride(pt->format, width), 64);
|
||||
lvl->tile_mode = get_tile_mode(nblocksy, depth);
|
||||
/* For 3D textures, a mipmap is spanned by all the layers, for array
|
||||
* textures and cube maps, each layer contains its own mipmaps.
|
||||
*/
|
||||
for (l = 0; l <= pt->last_level; ++l) {
|
||||
struct nv50_miptree_level *lvl = &mt->level[l];
|
||||
unsigned nbx = util_format_get_nblocksx(pt->format, w);
|
||||
unsigned nby = util_format_get_nblocksy(pt->format, h);
|
||||
unsigned blocksize = util_format_get_blocksize(pt->format);
|
||||
|
||||
width = u_minify(width, 1);
|
||||
height = u_minify(height, 1);
|
||||
depth = u_minify(depth, 1);
|
||||
}
|
||||
lvl->offset = mt->total_size;
|
||||
lvl->tile_mode = get_tile_dims(nbx, nby, d);
|
||||
lvl->pitch = align(nbx * blocksize, NV50_TILE_PITCH(lvl->tile_mode));
|
||||
|
||||
image_alignment = get_tile_height(mt->level[0].tile_mode) * 64;
|
||||
image_alignment *= get_tile_depth(mt->level[0].tile_mode);
|
||||
mt->total_size += lvl->pitch *
|
||||
align(nby, NV50_TILE_HEIGHT(lvl->tile_mode)) *
|
||||
align(d, NV50_TILE_DEPTH(lvl->tile_mode));
|
||||
|
||||
/* NOTE the distinction between arrays of mip-mapped 2D textures and
|
||||
* mip-mapped 3D textures. We can't use image_nr == depth for 3D mip.
|
||||
*/
|
||||
for (i = 0; i < mt->image_nr; i++) {
|
||||
for (l = 0; l <= pt->last_level; l++) {
|
||||
struct nv50_miptree_level *lvl = &mt->level[l];
|
||||
int size;
|
||||
unsigned tile_h = get_tile_height(lvl->tile_mode);
|
||||
unsigned tile_d = get_tile_depth(lvl->tile_mode);
|
||||
w = u_minify(w, 1);
|
||||
h = u_minify(h, 1);
|
||||
d = u_minify(d, 1);
|
||||
}
|
||||
|
||||
size = lvl->pitch;
|
||||
size *= align(util_format_get_nblocksy(pt->format, u_minify(pt->height0, l)), tile_h);
|
||||
size *= align(u_minify(pt->depth0, l), tile_d);
|
||||
if (pt->array_size > 1) {
|
||||
mt->layer_stride = align(mt->total_size,
|
||||
NV50_TILE_SIZE(mt->level[0].tile_mode));
|
||||
mt->total_size = mt->layer_stride * pt->array_size;
|
||||
}
|
||||
|
||||
lvl->image_offset[i] = mt->total_size;
|
||||
alloc_size = mt->total_size;
|
||||
|
||||
mt->total_size += size;
|
||||
}
|
||||
mt->total_size = align(mt->total_size, image_alignment);
|
||||
}
|
||||
ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, alloc_size,
|
||||
mt->level[0].tile_mode, tile_flags,
|
||||
&mt->base.bo);
|
||||
if (ret) {
|
||||
FREE(mt);
|
||||
return NULL;
|
||||
}
|
||||
mt->base.domain = NOUVEAU_BO_VRAM;
|
||||
|
||||
ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size,
|
||||
mt->level[0].tile_mode, tile_flags,
|
||||
&mt->base.bo);
|
||||
if (ret) {
|
||||
for (l = 0; l <= pt->last_level; ++l)
|
||||
FREE(mt->level[l].image_offset);
|
||||
FREE(mt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pt;
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
||||
struct pipe_resource *
|
||||
nv50_miptree_from_handle(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *template,
|
||||
struct winsys_handle *whandle)
|
||||
const struct pipe_resource *templ,
|
||||
struct winsys_handle *whandle)
|
||||
{
|
||||
struct nv50_miptree *mt;
|
||||
unsigned stride;
|
||||
struct nv50_miptree *mt;
|
||||
unsigned stride;
|
||||
|
||||
/* Only supports 2D, non-mipmapped textures for the moment */
|
||||
if ((template->target != PIPE_TEXTURE_2D &&
|
||||
template->target != PIPE_TEXTURE_RECT) ||
|
||||
template->last_level != 0 ||
|
||||
template->depth0 != 1)
|
||||
return NULL;
|
||||
/* only supports 2D, non-mipmapped textures for the moment */
|
||||
if ((templ->target != PIPE_TEXTURE_2D &&
|
||||
templ->target != PIPE_TEXTURE_RECT) ||
|
||||
templ->last_level != 0 ||
|
||||
templ->depth0 != 1 ||
|
||||
templ->array_size > 1)
|
||||
return NULL;
|
||||
|
||||
mt = CALLOC_STRUCT(nv50_miptree);
|
||||
if (!mt)
|
||||
return NULL;
|
||||
mt = CALLOC_STRUCT(nv50_miptree);
|
||||
if (!mt)
|
||||
return NULL;
|
||||
|
||||
mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
|
||||
if (mt->base.bo == NULL) {
|
||||
FREE(mt);
|
||||
return NULL;
|
||||
}
|
||||
mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
|
||||
if (mt->base.bo == NULL) {
|
||||
FREE(mt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mt->base.base = *templ;
|
||||
mt->base.vtbl = &nv50_miptree_vtbl;
|
||||
pipe_reference_init(&mt->base.base.reference, 1);
|
||||
mt->base.base.screen = pscreen;
|
||||
mt->level[0].pitch = stride;
|
||||
mt->level[0].offset = 0;
|
||||
mt->level[0].tile_mode = mt->base.bo->tile_mode;
|
||||
|
||||
mt->base.base = *template;
|
||||
mt->base.vtbl = &nv50_miptree_vtbl;
|
||||
pipe_reference_init(&mt->base.base.reference, 1);
|
||||
mt->base.base.screen = pscreen;
|
||||
mt->image_nr = 1;
|
||||
mt->level[0].pitch = stride;
|
||||
mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
|
||||
mt->level[0].tile_mode = mt->base.bo->tile_mode;
|
||||
|
||||
/* XXX: Need to adjust bo refcount??
|
||||
*/
|
||||
/* nouveau_bo_ref(bo, &mt->base.bo); */
|
||||
return &mt->base.base;
|
||||
/* no need to adjust bo reference count */
|
||||
return &mt->base.base;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Surface functions
|
||||
/* Surface functions.
|
||||
*/
|
||||
|
||||
struct pipe_surface *
|
||||
nv50_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt,
|
||||
const struct pipe_surface *surf_tmpl)
|
||||
nv50_miptree_surface_new(struct pipe_context *pipe,
|
||||
struct pipe_resource *pt,
|
||||
const struct pipe_surface *templ)
|
||||
{
|
||||
unsigned level = surf_tmpl->u.tex.level;
|
||||
struct nv50_miptree *mt = nv50_miptree(pt);
|
||||
struct nv50_miptree_level *lvl = &mt->level[level];
|
||||
struct nv50_surface *ns;
|
||||
unsigned img = 0, zslice = 0;
|
||||
struct nv50_miptree *mt = nv50_miptree(pt); /* guaranteed */
|
||||
struct nv50_surface *ns;
|
||||
struct pipe_surface *ps;
|
||||
struct nv50_miptree_level *lvl = &mt->level[templ->u.tex.level];
|
||||
|
||||
assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
|
||||
ns = CALLOC_STRUCT(nv50_surface);
|
||||
if (!ns)
|
||||
return NULL;
|
||||
ps = &ns->base;
|
||||
|
||||
/* XXX can't unify these here? */
|
||||
if (pt->target == PIPE_TEXTURE_CUBE)
|
||||
img = surf_tmpl->u.tex.first_layer;
|
||||
else if (pt->target == PIPE_TEXTURE_3D)
|
||||
zslice = surf_tmpl->u.tex.first_layer;
|
||||
pipe_reference_init(&ps->reference, 1);
|
||||
pipe_resource_reference(&ps->texture, pt);
|
||||
ps->context = pipe;
|
||||
ps->format = templ->format;
|
||||
ps->usage = templ->usage;
|
||||
ps->u.tex.level = templ->u.tex.level;
|
||||
ps->u.tex.first_layer = templ->u.tex.first_layer;
|
||||
ps->u.tex.last_layer = templ->u.tex.last_layer;
|
||||
|
||||
ns = CALLOC_STRUCT(nv50_surface);
|
||||
if (!ns)
|
||||
return NULL;
|
||||
pipe_resource_reference(&ns->base.texture, pt);
|
||||
ns->base.context = pipe;
|
||||
ns->base.format = pt->format;
|
||||
ns->base.width = u_minify(pt->width0, level);
|
||||
ns->base.height = u_minify(pt->height0, level);
|
||||
ns->base.usage = surf_tmpl->usage;
|
||||
pipe_reference_init(&ns->base.reference, 1);
|
||||
ns->base.u.tex.level = level;
|
||||
ns->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
|
||||
ns->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
|
||||
ns->offset = lvl->image_offset[img];
|
||||
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 = lvl->offset;
|
||||
|
||||
if (pt->target == PIPE_TEXTURE_3D) {
|
||||
unsigned nb_h = util_format_get_nblocksy(pt->format, ns->base.height);
|
||||
ns->offset += get_zslice_offset(lvl->tile_mode, zslice,
|
||||
lvl->pitch, nb_h);
|
||||
}
|
||||
/* comment says there are going to be removed, but they're used by the st */
|
||||
ps->width = ns->width;
|
||||
ps->height = ns->height;
|
||||
|
||||
return &ns->base;
|
||||
if (mt->layout_3d) {
|
||||
unsigned zslice = ps->u.tex.first_layer;
|
||||
|
||||
/* TODO: re-layout the texture to use only depth 1 tiles in this case: */
|
||||
if (ns->depth > 1 && (zslice & (NV50_TILE_DEPTH(lvl->tile_mode) - 1)))
|
||||
NOUVEAU_ERR("Creating unsupported 3D surface of slices [%u:%u].\n",
|
||||
zslice, ps->u.tex.last_layer);
|
||||
|
||||
ns->offset += calc_zslice_offset(lvl->tile_mode, zslice, lvl->pitch,
|
||||
util_format_get_nblocksy(pt->format,
|
||||
ns->height));
|
||||
} else {
|
||||
ns->offset += mt->layer_stride * ps->u.tex.first_layer;
|
||||
}
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_miptree_surface_del(struct pipe_context *pipe,
|
||||
struct pipe_surface *ps)
|
||||
nv50_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
|
||||
{
|
||||
struct nv50_surface *s = nv50_surface(ps);
|
||||
struct nv50_surface *s = nv50_surface(ps);
|
||||
|
||||
pipe_resource_reference(&s->base.texture, NULL);
|
||||
FREE(s);
|
||||
pipe_resource_reference(&ps->texture, NULL);
|
||||
|
||||
FREE(s);
|
||||
}
|
||||
|
|
|
|||
277
src/gallium/drivers/nv50/nv50_mm.c
Normal file
277
src/gallium/drivers/nv50/nv50_mm.c
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_double_list.h"
|
||||
|
||||
#include "nv50_screen.h"
|
||||
|
||||
#define MM_MIN_ORDER 7
|
||||
#define MM_MAX_ORDER 20
|
||||
|
||||
#define MM_NUM_BUCKETS (MM_MAX_ORDER - MM_MIN_ORDER + 1)
|
||||
|
||||
#define MM_MIN_SIZE (1 << MM_MIN_ORDER)
|
||||
#define MM_MAX_SIZE (1 << MM_MAX_ORDER)
|
||||
|
||||
struct mm_bucket {
|
||||
struct list_head free;
|
||||
struct list_head used;
|
||||
struct list_head full;
|
||||
int num_free;
|
||||
};
|
||||
|
||||
struct nv50_mman {
|
||||
struct nouveau_device *dev;
|
||||
struct mm_bucket bucket[MM_NUM_BUCKETS];
|
||||
uint32_t storage_type;
|
||||
uint32_t domain;
|
||||
uint64_t allocated;
|
||||
};
|
||||
|
||||
struct mm_slab {
|
||||
struct list_head head;
|
||||
struct nouveau_bo *bo;
|
||||
struct nv50_mman *cache;
|
||||
int order;
|
||||
int count;
|
||||
int free;
|
||||
uint32_t bits[0];
|
||||
};
|
||||
|
||||
static int
|
||||
mm_slab_alloc(struct mm_slab *slab)
|
||||
{
|
||||
int i, n, b;
|
||||
|
||||
if (slab->free == 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < (slab->count + 31) / 32; ++i) {
|
||||
b = ffs(slab->bits[i]) - 1;
|
||||
if (b >= 0) {
|
||||
n = i * 32 + b;
|
||||
assert(n < slab->count);
|
||||
slab->free--;
|
||||
slab->bits[i] &= ~(1 << b);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
mm_slab_free(struct mm_slab *slab, int i)
|
||||
{
|
||||
assert(i < slab->count);
|
||||
slab->bits[i / 32] |= 1 << (i % 32);
|
||||
slab->free++;
|
||||
assert(slab->free <= slab->count);
|
||||
}
|
||||
|
||||
static INLINE int
|
||||
mm_get_order(uint32_t size)
|
||||
{
|
||||
int s = __builtin_clz(size) ^ 31;
|
||||
|
||||
if (size > (1 << s))
|
||||
s += 1;
|
||||
return s;
|
||||
}
|
||||
|
||||
static struct mm_bucket *
|
||||
mm_bucket_by_order(struct nv50_mman *cache, int order)
|
||||
{
|
||||
if (order > MM_MAX_ORDER)
|
||||
return NULL;
|
||||
return &cache->bucket[MAX2(order, MM_MIN_ORDER) - MM_MIN_ORDER];
|
||||
}
|
||||
|
||||
static struct mm_bucket *
|
||||
mm_bucket_by_size(struct nv50_mman *cache, unsigned size)
|
||||
{
|
||||
return mm_bucket_by_order(cache, mm_get_order(size));
|
||||
}
|
||||
|
||||
/* size of bo allocation for slab with chunks of (1 << chunk_order) bytes */
|
||||
static INLINE uint32_t
|
||||
mm_default_slab_size(unsigned chunk_order)
|
||||
{
|
||||
static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] =
|
||||
{
|
||||
12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22
|
||||
};
|
||||
|
||||
assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER);
|
||||
|
||||
return 1 << slab_order[chunk_order - MM_MIN_ORDER];
|
||||
}
|
||||
|
||||
static int
|
||||
mm_slab_new(struct nv50_mman *cache, int chunk_order)
|
||||
{
|
||||
struct mm_slab *slab;
|
||||
int words, ret;
|
||||
const uint32_t size = mm_default_slab_size(chunk_order);
|
||||
|
||||
words = ((size >> chunk_order) + 31) / 32;
|
||||
assert(words);
|
||||
|
||||
slab = MALLOC(sizeof(struct mm_slab) + words * 4);
|
||||
if (!slab)
|
||||
return PIPE_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
memset(&slab->bits[0], ~0, words * 4);
|
||||
|
||||
slab->bo = NULL;
|
||||
ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size,
|
||||
0, cache->storage_type, &slab->bo);
|
||||
if (ret) {
|
||||
FREE(slab);
|
||||
return PIPE_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
LIST_INITHEAD(&slab->head);
|
||||
|
||||
slab->cache = cache;
|
||||
slab->order = chunk_order;
|
||||
slab->count = slab->free = size >> chunk_order;
|
||||
|
||||
LIST_ADD(&slab->head, &mm_bucket_by_order(cache, chunk_order)->free);
|
||||
|
||||
cache->allocated += size;
|
||||
|
||||
debug_printf("MM: new slab, total memory = %lu KiB\n",
|
||||
cache->allocated / 1024);
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
/* @return token to identify slab or NULL if we just allocated a new bo */
|
||||
struct nv50_mm_allocation *
|
||||
nv50_mm_allocate(struct nv50_mman *cache,
|
||||
uint32_t size, struct nouveau_bo **bo, uint32_t *offset)
|
||||
{
|
||||
struct mm_bucket *bucket;
|
||||
struct mm_slab *slab;
|
||||
struct nv50_mm_allocation *alloc;
|
||||
int ret;
|
||||
|
||||
bucket = mm_bucket_by_size(cache, size);
|
||||
if (!bucket) {
|
||||
ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size,
|
||||
0, cache->storage_type, bo);
|
||||
if (ret)
|
||||
debug_printf("bo_new(%x, %x): %i\n", size, cache->storage_type, ret);
|
||||
|
||||
*offset = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!LIST_IS_EMPTY(&bucket->used)) {
|
||||
slab = LIST_ENTRY(struct mm_slab, bucket->used.next, head);
|
||||
} else {
|
||||
if (LIST_IS_EMPTY(&bucket->free)) {
|
||||
mm_slab_new(cache, MAX2(mm_get_order(size), MM_MIN_ORDER));
|
||||
}
|
||||
slab = LIST_ENTRY(struct mm_slab, bucket->free.next, head);
|
||||
|
||||
LIST_DEL(&slab->head);
|
||||
LIST_ADD(&slab->head, &bucket->used);
|
||||
}
|
||||
|
||||
*offset = mm_slab_alloc(slab) << slab->order;
|
||||
|
||||
alloc = MALLOC_STRUCT(nv50_mm_allocation);
|
||||
if (!alloc)
|
||||
return NULL;
|
||||
|
||||
nouveau_bo_ref(slab->bo, bo);
|
||||
|
||||
if (slab->free == 0) {
|
||||
LIST_DEL(&slab->head);
|
||||
LIST_ADD(&slab->head, &bucket->full);
|
||||
}
|
||||
|
||||
alloc->next = NULL;
|
||||
alloc->offset = *offset;
|
||||
alloc->priv = (void *)slab;
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_mm_free(struct nv50_mm_allocation *alloc)
|
||||
{
|
||||
struct mm_slab *slab = (struct mm_slab *)alloc->priv;
|
||||
struct mm_bucket *bucket = mm_bucket_by_order(slab->cache, slab->order);
|
||||
|
||||
mm_slab_free(slab, alloc->offset >> slab->order);
|
||||
|
||||
if (slab->free == 1) {
|
||||
LIST_DEL(&slab->head);
|
||||
|
||||
if (slab->count > 1)
|
||||
LIST_ADDTAIL(&slab->head, &bucket->used);
|
||||
else
|
||||
LIST_ADDTAIL(&slab->head, &bucket->free);
|
||||
}
|
||||
|
||||
FREE(alloc);
|
||||
}
|
||||
|
||||
struct nv50_mman *
|
||||
nv50_mm_create(struct nouveau_device *dev, uint32_t domain,
|
||||
uint32_t storage_type)
|
||||
{
|
||||
struct nv50_mman *cache = MALLOC_STRUCT(nv50_mman);
|
||||
int i;
|
||||
|
||||
if (!cache)
|
||||
return NULL;
|
||||
|
||||
cache->dev = dev;
|
||||
cache->domain = domain;
|
||||
cache->storage_type = storage_type;
|
||||
cache->allocated = 0;
|
||||
|
||||
for (i = 0; i < MM_NUM_BUCKETS; ++i) {
|
||||
LIST_INITHEAD(&cache->bucket[i].free);
|
||||
LIST_INITHEAD(&cache->bucket[i].used);
|
||||
LIST_INITHEAD(&cache->bucket[i].full);
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
nv50_mm_free_slabs(struct list_head *head)
|
||||
{
|
||||
struct mm_slab *slab, *next;
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(slab, next, head, head) {
|
||||
LIST_DEL(&slab->head);
|
||||
nouveau_bo_ref(NULL, &slab->bo);
|
||||
FREE(slab);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv50_mm_destroy(struct nv50_mman *cache)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MM_NUM_BUCKETS; ++i) {
|
||||
if (!LIST_IS_EMPTY(&cache->bucket[i].used) ||
|
||||
!LIST_IS_EMPTY(&cache->bucket[i].full))
|
||||
debug_printf("WARNING: destroying GPU memory cache "
|
||||
"with some buffers still in use\n");
|
||||
|
||||
nv50_mm_free_slabs(&cache->bucket[i].free);
|
||||
nv50_mm_free_slabs(&cache->bucket[i].used);
|
||||
nv50_mm_free_slabs(&cache->bucket[i].full);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -307,7 +307,10 @@ nv_pc_pass_in_order(struct nv_basic_block *root, nv_pc_pass_func f, void *priv)
|
|||
bb[p++] = b->out[j];
|
||||
break;
|
||||
case CFG_EDGE_LOOP_LEAVE:
|
||||
bbb[pp++] = b->out[j];
|
||||
if (!b->out[j]->priv) {
|
||||
bbb[pp++] = b->out[j];
|
||||
b->out[j]->priv = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#ifndef __NV50_COMPILER_H__
|
||||
#define __NV50_COMPILER_H__
|
||||
|
||||
#define NV50PC_DEBUG
|
||||
|
||||
#ifdef NV50PC_DEBUG
|
||||
# define NV50_DBGMSG(args...) debug_printf(args)
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -145,8 +145,9 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b)
|
|||
int j;
|
||||
uint size, n32 = 0;
|
||||
|
||||
/* find first non-empty block emitted before b */
|
||||
for (j = pc->num_blocks - 1; j >= 0 && !pc->bb_list[j]->bin_size; --j);
|
||||
if (j >= 0) {
|
||||
for (; j >= 0; --j) {
|
||||
in = pc->bb_list[j];
|
||||
|
||||
/* check for no-op branches (BRA $PC+8) */
|
||||
|
|
@ -160,6 +161,9 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b)
|
|||
nv_nvi_delete(in->exit);
|
||||
}
|
||||
b->bin_pos = in->bin_pos + in->bin_size;
|
||||
|
||||
if (in->bin_size) /* no more no-op branches to b */
|
||||
break;
|
||||
}
|
||||
|
||||
pc->bb_list[pc->num_blocks++] = b;
|
||||
|
|
|
|||
|
|
@ -411,11 +411,11 @@ nv50_fragprog_prepare(struct nv50_translation_info *ti)
|
|||
|
||||
if (ti->scan.writes_z) {
|
||||
p->fp.flags[1] = 0x11;
|
||||
p->fp.flags[0] |= NV50TCL_FP_CONTROL_EXPORTS_Z;
|
||||
p->fp.flags[0] |= NV50_3D_FP_CONTROL_EXPORTS_Z;
|
||||
}
|
||||
|
||||
if (ti->scan.uses_kill)
|
||||
p->fp.flags[0] |= NV50TCL_FP_CONTROL_USES_KIL;
|
||||
p->fp.flags[0] |= NV50_3D_FP_CONTROL_USES_KIL;
|
||||
|
||||
/* FP inputs */
|
||||
|
||||
|
|
@ -490,13 +490,13 @@ nv50_fragprog_prepare(struct nv50_translation_info *ti)
|
|||
if (n < m)
|
||||
nvary -= p->in[n].hw;
|
||||
|
||||
p->fp.interp |= nvary << NV50TCL_FP_INTERPOLANT_CTRL_COUNT_NONFLAT_SHIFT;
|
||||
p->fp.interp |= nintp << NV50TCL_FP_INTERPOLANT_CTRL_COUNT_SHIFT;
|
||||
p->fp.interp |= nvary << NV50_3D_FP_INTERPOLANT_CTRL_COUNT_NONFLAT__SHIFT;
|
||||
p->fp.interp |= nintp << NV50_3D_FP_INTERPOLANT_CTRL_COUNT__SHIFT;
|
||||
|
||||
/* FP outputs */
|
||||
|
||||
if (p->out_nr > (1 + (ti->scan.writes_z ? 1 : 0)))
|
||||
p->fp.flags[0] |= NV50TCL_FP_CONTROL_MULTIPLE_RESULTS;
|
||||
p->fp.flags[0] |= NV50_3D_FP_CONTROL_MULTIPLE_RESULTS;
|
||||
|
||||
depr = p->out_nr;
|
||||
for (i = 0; i < p->out_nr; ++i) {
|
||||
|
|
@ -608,7 +608,7 @@ nv50_prog_scan(struct nv50_translation_info *ti)
|
|||
}
|
||||
|
||||
boolean
|
||||
nv50_program_tx(struct nv50_program *p)
|
||||
nv50_program_translate(struct nv50_program *p)
|
||||
{
|
||||
struct nv50_translation_info *ti;
|
||||
int ret;
|
||||
|
|
@ -646,9 +646,8 @@ out:
|
|||
void
|
||||
nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p)
|
||||
{
|
||||
nouveau_bo_ref(NULL, &p->bo);
|
||||
|
||||
so_ref(NULL, &p->so);
|
||||
if (p->res)
|
||||
nouveau_resource_free(&p->res);
|
||||
|
||||
if (p->code)
|
||||
FREE(p->code);
|
||||
|
|
|
|||
|
|
@ -47,12 +47,9 @@ struct nv50_program {
|
|||
boolean translated;
|
||||
boolean uses_lmem;
|
||||
|
||||
struct nouveau_bo *bo;
|
||||
struct nouveau_stateobj *so;
|
||||
|
||||
uint32_t *code;
|
||||
unsigned code_size;
|
||||
unsigned code_start; /* offset inside bo */
|
||||
unsigned code_base;
|
||||
uint32_t *immd;
|
||||
unsigned immd_size;
|
||||
unsigned parm_size; /* size limit of uniform buffer */
|
||||
|
|
@ -89,6 +86,8 @@ struct nv50_program {
|
|||
/* relocation records */
|
||||
void *fixups;
|
||||
unsigned num_fixups;
|
||||
|
||||
struct nouveau_resource *res;
|
||||
};
|
||||
|
||||
#define NV50_INTERP_LINEAR (1 << 0)
|
||||
|
|
|
|||
|
|
@ -1,362 +1,292 @@
|
|||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_split_prim.h"
|
||||
#include "translate/translate.h"
|
||||
|
||||
#include "nv50_context.h"
|
||||
#include "nv50_resource.h"
|
||||
|
||||
struct push_context {
|
||||
struct nv50_context *nv50;
|
||||
#include "nv50_3d.xml.h"
|
||||
|
||||
unsigned vtx_size;
|
||||
struct push_context {
|
||||
struct nouveau_channel *chan;
|
||||
|
||||
void *idxbuf;
|
||||
int32_t idxbias;
|
||||
unsigned idxsize;
|
||||
|
||||
float edgeflag;
|
||||
int edgeflag_attr;
|
||||
|
||||
struct {
|
||||
void *map;
|
||||
unsigned stride;
|
||||
unsigned divisor;
|
||||
unsigned step;
|
||||
void (*push)(struct nouveau_channel *, void *);
|
||||
} attr[16];
|
||||
unsigned attr_nr;
|
||||
uint32_t vertex_words;
|
||||
uint32_t packet_vertex_limit;
|
||||
|
||||
struct translate *translate;
|
||||
|
||||
boolean primitive_restart;
|
||||
uint32_t prim;
|
||||
uint32_t restart_index;
|
||||
uint32_t instance_id;
|
||||
};
|
||||
|
||||
static void
|
||||
emit_b32_1(struct nouveau_channel *chan, void *data)
|
||||
static INLINE unsigned
|
||||
prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
|
||||
{
|
||||
uint32_t *v = data;
|
||||
unsigned i;
|
||||
for (i = 0; i < push; ++i)
|
||||
if (elts[i] == index)
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
OUT_RING(chan, v[0]);
|
||||
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_b32_2(struct nouveau_channel *chan, void *data)
|
||||
emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
|
||||
{
|
||||
uint32_t *v = data;
|
||||
uint8_t *elts = (uint8_t *)ctx->idxbuf + start;
|
||||
|
||||
OUT_RING(chan, v[0]);
|
||||
OUT_RING(chan, v[1]);
|
||||
}
|
||||
while (count) {
|
||||
unsigned push = MIN2(count, ctx->packet_vertex_limit);
|
||||
unsigned size, nr;
|
||||
|
||||
static void
|
||||
emit_b32_3(struct nouveau_channel *chan, void *data)
|
||||
{
|
||||
uint32_t *v = data;
|
||||
nr = push;
|
||||
if (ctx->primitive_restart)
|
||||
nr = prim_restart_search_i08(elts, push, ctx->restart_index);
|
||||
|
||||
OUT_RING(chan, v[0]);
|
||||
OUT_RING(chan, v[1]);
|
||||
OUT_RING(chan, v[2]);
|
||||
}
|
||||
size = ctx->vertex_words * nr;
|
||||
|
||||
static void
|
||||
emit_b32_4(struct nouveau_channel *chan, void *data)
|
||||
{
|
||||
uint32_t *v = data;
|
||||
BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);
|
||||
|
||||
OUT_RING(chan, v[0]);
|
||||
OUT_RING(chan, v[1]);
|
||||
OUT_RING(chan, v[2]);
|
||||
OUT_RING(chan, v[3]);
|
||||
}
|
||||
ctx->translate->run_elts8(ctx->translate, elts, nr, ctx->instance_id,
|
||||
ctx->chan->cur);
|
||||
|
||||
static void
|
||||
emit_b16_1(struct nouveau_channel *chan, void *data)
|
||||
{
|
||||
uint16_t *v = data;
|
||||
ctx->chan->cur += size;
|
||||
count -= nr;
|
||||
elts += nr;
|
||||
|
||||
OUT_RING(chan, v[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_b16_3(struct nouveau_channel *chan, void *data)
|
||||
{
|
||||
uint16_t *v = data;
|
||||
|
||||
OUT_RING(chan, (v[1] << 16) | v[0]);
|
||||
OUT_RING(chan, v[2]);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_b08_1(struct nouveau_channel *chan, void *data)
|
||||
{
|
||||
uint8_t *v = data;
|
||||
|
||||
OUT_RING(chan, v[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_b08_3(struct nouveau_channel *chan, void *data)
|
||||
{
|
||||
uint8_t *v = data;
|
||||
|
||||
OUT_RING(chan, (v[2] << 16) | (v[1] << 8) | v[0]);
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
emit_vertex(struct push_context *ctx, unsigned n)
|
||||
{
|
||||
struct nouveau_grobj *tesla = ctx->nv50->screen->tesla;
|
||||
struct nouveau_channel *chan = tesla->channel;
|
||||
int i;
|
||||
|
||||
if (ctx->edgeflag_attr < 16) {
|
||||
float *edgeflag = (float *)
|
||||
((uint8_t *)ctx->attr[ctx->edgeflag_attr].map +
|
||||
ctx->attr[ctx->edgeflag_attr].stride * n);
|
||||
|
||||
if (*edgeflag != ctx->edgeflag) {
|
||||
BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
|
||||
OUT_RING (chan, *edgeflag ? 1 : 0);
|
||||
ctx->edgeflag = *edgeflag;
|
||||
if (nr != push) {
|
||||
count--;
|
||||
elts++;
|
||||
BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2);
|
||||
OUT_RING (ctx->chan, 0);
|
||||
OUT_RING (ctx->chan, NVA0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
|
||||
(ctx->prim & ~NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, ctx->vtx_size);
|
||||
for (i = 0; i < ctx->attr_nr; i++)
|
||||
ctx->attr[i].push(chan,
|
||||
(uint8_t *)ctx->attr[i].map + ctx->attr[i].stride * n);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_edgeflag(void *priv, boolean enabled)
|
||||
emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
|
||||
{
|
||||
struct push_context *ctx = priv;
|
||||
struct nouveau_grobj *tesla = ctx->nv50->screen->tesla;
|
||||
struct nouveau_channel *chan = tesla->channel;
|
||||
uint16_t *elts = (uint16_t *)ctx->idxbuf + start;
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
|
||||
OUT_RING (chan, enabled ? 1 : 0);
|
||||
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_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);
|
||||
|
||||
ctx->translate->run_elts16(ctx->translate, elts, nr, ctx->instance_id,
|
||||
ctx->chan->cur);
|
||||
|
||||
ctx->chan->cur += size;
|
||||
count -= nr;
|
||||
elts += nr;
|
||||
|
||||
if (nr != push) {
|
||||
count--;
|
||||
elts++;
|
||||
BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2);
|
||||
OUT_RING (ctx->chan, 0);
|
||||
OUT_RING (ctx->chan, NVA0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
|
||||
(ctx->prim & ~NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_elt08(void *priv, unsigned start, unsigned count)
|
||||
emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
|
||||
{
|
||||
struct push_context *ctx = priv;
|
||||
uint8_t *idxbuf = ctx->idxbuf;
|
||||
uint32_t *elts = (uint32_t *)ctx->idxbuf + start;
|
||||
|
||||
while (count--)
|
||||
emit_vertex(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_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);
|
||||
|
||||
ctx->translate->run_elts(ctx->translate, elts, nr, ctx->instance_id,
|
||||
ctx->chan->cur);
|
||||
|
||||
ctx->chan->cur += size;
|
||||
count -= nr;
|
||||
elts += nr;
|
||||
|
||||
if (nr != push) {
|
||||
count--;
|
||||
elts++;
|
||||
BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2);
|
||||
OUT_RING (ctx->chan, 0);
|
||||
OUT_RING (ctx->chan, NVA0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
|
||||
(ctx->prim & ~NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_elt08_biased(void *priv, unsigned start, unsigned count)
|
||||
emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
|
||||
{
|
||||
struct push_context *ctx = priv;
|
||||
uint8_t *idxbuf = ctx->idxbuf;
|
||||
while (count) {
|
||||
unsigned push = MIN2(count, ctx->packet_vertex_limit);
|
||||
unsigned size = ctx->vertex_words * push;
|
||||
|
||||
while (count--)
|
||||
emit_vertex(ctx, idxbuf[start++] + ctx->idxbias);
|
||||
BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);
|
||||
|
||||
ctx->translate->run(ctx->translate, start, push, ctx->instance_id,
|
||||
ctx->chan->cur);
|
||||
ctx->chan->cur += size;
|
||||
count -= push;
|
||||
start += push;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_elt16(void *priv, unsigned start, unsigned count)
|
||||
|
||||
#define NV50_PRIM_GL_CASE(n) \
|
||||
case PIPE_PRIM_##n: return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
|
||||
|
||||
static INLINE unsigned
|
||||
nv50_prim_gl(unsigned prim)
|
||||
{
|
||||
struct push_context *ctx = priv;
|
||||
uint16_t *idxbuf = ctx->idxbuf;
|
||||
|
||||
while (count--)
|
||||
emit_vertex(ctx, idxbuf[start++]);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_elt16_biased(void *priv, unsigned start, unsigned count)
|
||||
{
|
||||
struct push_context *ctx = priv;
|
||||
uint16_t *idxbuf = ctx->idxbuf;
|
||||
|
||||
while (count--)
|
||||
emit_vertex(ctx, idxbuf[start++] + ctx->idxbias);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_elt32(void *priv, unsigned start, unsigned count)
|
||||
{
|
||||
struct push_context *ctx = priv;
|
||||
uint32_t *idxbuf = ctx->idxbuf;
|
||||
|
||||
while (count--)
|
||||
emit_vertex(ctx, idxbuf[start++]);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_elt32_biased(void *priv, unsigned start, unsigned count)
|
||||
{
|
||||
struct push_context *ctx = priv;
|
||||
uint32_t *idxbuf = ctx->idxbuf;
|
||||
|
||||
while (count--)
|
||||
emit_vertex(ctx, idxbuf[start++] + ctx->idxbias);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_verts(void *priv, unsigned start, unsigned count)
|
||||
{
|
||||
while (count--)
|
||||
emit_vertex(priv, start++);
|
||||
switch (prim) {
|
||||
NV50_PRIM_GL_CASE(POINTS);
|
||||
NV50_PRIM_GL_CASE(LINES);
|
||||
NV50_PRIM_GL_CASE(LINE_LOOP);
|
||||
NV50_PRIM_GL_CASE(LINE_STRIP);
|
||||
NV50_PRIM_GL_CASE(TRIANGLES);
|
||||
NV50_PRIM_GL_CASE(TRIANGLE_STRIP);
|
||||
NV50_PRIM_GL_CASE(TRIANGLE_FAN);
|
||||
NV50_PRIM_GL_CASE(QUADS);
|
||||
NV50_PRIM_GL_CASE(QUAD_STRIP);
|
||||
NV50_PRIM_GL_CASE(POLYGON);
|
||||
NV50_PRIM_GL_CASE(LINES_ADJACENCY);
|
||||
NV50_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);
|
||||
NV50_PRIM_GL_CASE(TRIANGLES_ADJACENCY);
|
||||
NV50_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);
|
||||
/*
|
||||
NV50_PRIM_GL_CASE(PATCHES); */
|
||||
default:
|
||||
return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv50_push_elements_instanced(struct pipe_context *pipe,
|
||||
struct pipe_resource *idxbuf,
|
||||
unsigned idxsize, int idxbias,
|
||||
unsigned mode, unsigned start, unsigned count,
|
||||
unsigned i_start, unsigned i_count)
|
||||
nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_channel *chan = tesla->channel;
|
||||
struct push_context ctx;
|
||||
const unsigned p_overhead = 4 + /* begin/end */
|
||||
4; /* potential edgeflag enable/disable */
|
||||
const unsigned v_overhead = 1 + /* VERTEX_DATA packet header */
|
||||
2; /* potential edgeflag modification */
|
||||
struct util_split_prim s;
|
||||
unsigned vtx_size;
|
||||
boolean nzi = FALSE;
|
||||
int i;
|
||||
unsigned i, index_size;
|
||||
unsigned inst = info->instance_count;
|
||||
boolean apply_bias = info->indexed && info->index_bias;
|
||||
|
||||
ctx.nv50 = nv50;
|
||||
ctx.attr_nr = 0;
|
||||
ctx.idxbuf = NULL;
|
||||
ctx.vtx_size = 0;
|
||||
ctx.edgeflag = 0.5f;
|
||||
ctx.edgeflag_attr = nv50->vertprog->vp.edgeflag;
|
||||
ctx.chan = nv50->screen->base.channel;
|
||||
ctx.translate = nv50->vertex->translate;
|
||||
ctx.packet_vertex_limit = nv50->vertex->packet_vertex_limit;
|
||||
ctx.vertex_words = nv50->vertex->vertex_size;
|
||||
|
||||
/* map vertex buffers, determine vertex size */
|
||||
for (i = 0; i < nv50->vtxelt->num_elements; i++) {
|
||||
struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i];
|
||||
struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index];
|
||||
struct nouveau_bo *bo = nv50_resource(vb->buffer)->bo;
|
||||
unsigned size, nr_components, n;
|
||||
for (i = 0; i < nv50->num_vtxbufs; ++i) {
|
||||
uint8_t *data;
|
||||
struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i];
|
||||
struct nv50_resource *res = nv50_resource(vb->buffer);
|
||||
|
||||
if (!(nv50->vbo_fifo & (1 << i)))
|
||||
continue;
|
||||
n = ctx.attr_nr++;
|
||||
data = nv50_resource_map_offset(nv50, res,
|
||||
vb->buffer_offset, NOUVEAU_BO_RD);
|
||||
|
||||
if (nouveau_bo_map(bo, NOUVEAU_BO_RD)) {
|
||||
assert(bo->map);
|
||||
if (apply_bias && likely(!(nv50->vertex->instance_bufs & (1 << i))))
|
||||
data += info->index_bias * vb->stride;
|
||||
|
||||
ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
|
||||
}
|
||||
|
||||
if (info->indexed) {
|
||||
ctx.idxbuf = nv50_resource_map_offset(nv50,
|
||||
nv50_resource(nv50->idxbuf.buffer),
|
||||
nv50->idxbuf.offset, NOUVEAU_BO_RD);
|
||||
if (!ctx.idxbuf)
|
||||
return;
|
||||
}
|
||||
ctx.attr[n].map = (uint8_t *)bo->map + vb->buffer_offset + ve->src_offset;
|
||||
nouveau_bo_unmap(bo);
|
||||
index_size = nv50->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;
|
||||
}
|
||||
|
||||
ctx.attr[n].stride = vb->stride;
|
||||
ctx.attr[n].divisor = ve->instance_divisor;
|
||||
if (ctx.attr[n].divisor) {
|
||||
ctx.attr[n].step = i_start % ve->instance_divisor;
|
||||
ctx.attr[n].map = (uint8_t *)ctx.attr[n].map + i_start * vb->stride;
|
||||
}
|
||||
ctx.instance_id = info->start_instance;
|
||||
ctx.prim = nv50_prim_gl(info->mode);
|
||||
|
||||
size = util_format_get_component_bits(ve->src_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 0);
|
||||
nr_components = util_format_get_nr_components(ve->src_format);
|
||||
switch (size) {
|
||||
case 8:
|
||||
switch (nr_components) {
|
||||
case 1: ctx.attr[n].push = emit_b08_1; break;
|
||||
case 2: ctx.attr[n].push = emit_b16_1; break;
|
||||
case 3: ctx.attr[n].push = emit_b08_3; break;
|
||||
case 4: ctx.attr[n].push = emit_b32_1; break;
|
||||
}
|
||||
ctx.vtx_size++;
|
||||
while (inst--) {
|
||||
BEGIN_RING(ctx.chan, RING_3D(VERTEX_BEGIN_GL), 1);
|
||||
OUT_RING (ctx.chan, ctx.prim);
|
||||
switch (index_size) {
|
||||
case 0:
|
||||
emit_vertices_seq(&ctx, info->start, info->count);
|
||||
break;
|
||||
case 16:
|
||||
switch (nr_components) {
|
||||
case 1: ctx.attr[n].push = emit_b16_1; break;
|
||||
case 2: ctx.attr[n].push = emit_b32_1; break;
|
||||
case 3: ctx.attr[n].push = emit_b16_3; break;
|
||||
case 4: ctx.attr[n].push = emit_b32_2; break;
|
||||
}
|
||||
ctx.vtx_size += (nr_components + 1) >> 1;
|
||||
case 1:
|
||||
emit_vertices_i08(&ctx, info->start, info->count);
|
||||
break;
|
||||
case 32:
|
||||
switch (nr_components) {
|
||||
case 1: ctx.attr[n].push = emit_b32_1; break;
|
||||
case 2: ctx.attr[n].push = emit_b32_2; break;
|
||||
case 3: ctx.attr[n].push = emit_b32_3; break;
|
||||
case 4: ctx.attr[n].push = emit_b32_4; break;
|
||||
}
|
||||
ctx.vtx_size += nr_components;
|
||||
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);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vtx_size = ctx.vtx_size + v_overhead;
|
||||
BEGIN_RING(ctx.chan, RING_3D(VERTEX_END_GL), 1);
|
||||
OUT_RING (ctx.chan, 0);
|
||||
|
||||
/* map index buffer, if present */
|
||||
if (idxbuf) {
|
||||
struct nouveau_bo *bo = nv50_resource(idxbuf)->bo;
|
||||
|
||||
if (nouveau_bo_map(bo, NOUVEAU_BO_RD)) {
|
||||
assert(bo->map);
|
||||
return;
|
||||
}
|
||||
ctx.idxbuf = bo->map;
|
||||
ctx.idxbias = idxbias;
|
||||
ctx.idxsize = idxsize;
|
||||
nouveau_bo_unmap(bo);
|
||||
ctx.instance_id++;
|
||||
ctx.prim |= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
|
||||
}
|
||||
|
||||
s.priv = &ctx;
|
||||
s.edge = emit_edgeflag;
|
||||
if (idxbuf) {
|
||||
if (idxsize == 1)
|
||||
s.emit = idxbias ? emit_elt08_biased : emit_elt08;
|
||||
else
|
||||
if (idxsize == 2)
|
||||
s.emit = idxbias ? emit_elt16_biased : emit_elt16;
|
||||
else
|
||||
s.emit = idxbias ? emit_elt32_biased : emit_elt32;
|
||||
} else
|
||||
s.emit = emit_verts;
|
||||
if (info->indexed)
|
||||
nv50_resource_unmap(nv50_resource(nv50->idxbuf.buffer));
|
||||
|
||||
/* per-instance loop */
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2);
|
||||
OUT_RING (chan, NV50_CB_AUX | (24 << 8));
|
||||
OUT_RING (chan, i_start);
|
||||
while (i_count--) {
|
||||
unsigned max_verts;
|
||||
boolean done;
|
||||
|
||||
for (i = 0; i < ctx.attr_nr; i++) {
|
||||
if (!ctx.attr[i].divisor ||
|
||||
ctx.attr[i].divisor != ++ctx.attr[i].step)
|
||||
continue;
|
||||
ctx.attr[i].step = 0;
|
||||
ctx.attr[i].map = (uint8_t *)ctx.attr[i].map + ctx.attr[i].stride;
|
||||
}
|
||||
|
||||
util_split_prim_init(&s, mode, start, count);
|
||||
do {
|
||||
if (AVAIL_RING(chan) < p_overhead + (6 * vtx_size)) {
|
||||
FIRE_RING(chan);
|
||||
if (!nv50_state_validate(nv50, p_overhead + (6 * vtx_size))) {
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
max_verts = AVAIL_RING(chan);
|
||||
max_verts -= p_overhead;
|
||||
max_verts /= vtx_size;
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
|
||||
OUT_RING (chan, nv50_prim(s.mode) | (nzi ? (1 << 28) : 0));
|
||||
done = util_split_prim_next(&s, max_verts);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
|
||||
OUT_RING (chan, 0);
|
||||
} while (!done);
|
||||
|
||||
nzi = TRUE;
|
||||
}
|
||||
for (i = 0; i < nv50->num_vtxbufs; ++i)
|
||||
nv50_resource_unmap(nv50_resource(nv50->vtxbuf[i].buffer));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008 Ben Skeggs
|
||||
* Copyright 2011 Nouveau Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
|
@ -18,150 +18,318 @@
|
|||
* 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: Christoph Bumiller
|
||||
*/
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
#include "nv50_context.h"
|
||||
#include "nouveau/nv_object.xml.h"
|
||||
|
||||
/* XXX: Nested queries, and simultaneous queries on multiple gallium contexts
|
||||
* (since we use only a single GPU channel per screen) will not work properly.
|
||||
*
|
||||
* The first is not that big of an issue because OpenGL does not allow nested
|
||||
* queries anyway.
|
||||
*/
|
||||
|
||||
struct nv50_query {
|
||||
struct nouveau_bo *bo;
|
||||
unsigned type;
|
||||
boolean ready;
|
||||
uint64_t result;
|
||||
uint32_t *data;
|
||||
uint32_t type;
|
||||
uint32_t sequence;
|
||||
struct nouveau_bo *bo;
|
||||
uint32_t base;
|
||||
uint32_t offset; /* base + i * 16 */
|
||||
boolean ready;
|
||||
boolean is64bit;
|
||||
struct nv50_mm_allocation *mm;
|
||||
};
|
||||
|
||||
#define NV50_QUERY_ALLOC_SPACE 128
|
||||
|
||||
static INLINE struct nv50_query *
|
||||
nv50_query(struct pipe_query *pipe)
|
||||
{
|
||||
return (struct nv50_query *)pipe;
|
||||
return (struct nv50_query *)pipe;
|
||||
}
|
||||
|
||||
static struct pipe_query *
|
||||
nv50_query_create(struct pipe_context *pipe, unsigned type)
|
||||
static boolean
|
||||
nv50_query_allocate(struct nv50_context *nv50, struct nv50_query *q, int size)
|
||||
{
|
||||
struct nouveau_device *dev = nouveau_screen(pipe->screen)->device;
|
||||
struct nv50_query *q = CALLOC_STRUCT(nv50_query);
|
||||
int ret;
|
||||
struct nv50_screen *screen = nv50->screen;
|
||||
int ret;
|
||||
|
||||
assert (type == PIPE_QUERY_OCCLUSION_COUNTER);
|
||||
q->type = type;
|
||||
if (q->bo) {
|
||||
nouveau_bo_ref(NULL, &q->bo);
|
||||
if (q->mm) {
|
||||
if (q->ready)
|
||||
nv50_mm_free(q->mm);
|
||||
else
|
||||
nv50_fence_sched_release(screen->fence.current, q->mm);
|
||||
}
|
||||
}
|
||||
if (size) {
|
||||
q->mm = nv50_mm_allocate(screen->mm_GART, size, &q->bo, &q->base);
|
||||
if (!q->bo)
|
||||
return FALSE;
|
||||
q->offset = q->base;
|
||||
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 256,
|
||||
16, &q->bo);
|
||||
if (ret) {
|
||||
FREE(q);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (struct pipe_query *)q;
|
||||
ret = nouveau_bo_map_range(q->bo, q->base, size, NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_NOSYNC);
|
||||
if (ret) {
|
||||
nv50_query_allocate(nv50, q, 0);
|
||||
return FALSE;
|
||||
}
|
||||
q->data = q->bo->map;
|
||||
nouveau_bo_unmap(q->bo);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
|
||||
{
|
||||
struct nv50_query *q = nv50_query(pq);
|
||||
nv50_query_allocate(nv50_context(pipe), nv50_query(pq), 0);
|
||||
FREE(nv50_query(pq));
|
||||
}
|
||||
|
||||
if (q) {
|
||||
nouveau_bo_ref(NULL, &q->bo);
|
||||
FREE(q);
|
||||
}
|
||||
static struct pipe_query *
|
||||
nv50_query_create(struct pipe_context *pipe, unsigned type)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nv50_query *q;
|
||||
|
||||
q = CALLOC_STRUCT(nv50_query);
|
||||
if (!q)
|
||||
return NULL;
|
||||
|
||||
if (!nv50_query_allocate(nv50, q, NV50_QUERY_ALLOC_SPACE)) {
|
||||
FREE(q);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
q->is64bit = (type == PIPE_QUERY_PRIMITIVES_GENERATED ||
|
||||
type == PIPE_QUERY_PRIMITIVES_EMITTED ||
|
||||
type == PIPE_QUERY_SO_STATISTICS);
|
||||
q->type = type;
|
||||
|
||||
if (q->type == PIPE_QUERY_OCCLUSION_COUNTER) {
|
||||
q->offset -= 16;
|
||||
q->data -= 16 / sizeof(*q->data); /* we advance before query_begin ! */
|
||||
}
|
||||
|
||||
return (struct pipe_query *)q;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_query_get(struct nouveau_channel *chan, struct nv50_query *q,
|
||||
unsigned offset, uint32_t get)
|
||||
{
|
||||
offset += q->offset;
|
||||
|
||||
MARK_RING (chan, 5, 2);
|
||||
BEGIN_RING(chan, RING_3D(QUERY_ADDRESS_HIGH), 4);
|
||||
OUT_RELOCh(chan, q->bo, offset, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, q->bo, offset, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, q->sequence);
|
||||
OUT_RING (chan, get);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nv50_query *q = nv50_query(pq);
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_query *q = nv50_query(pq);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_RESET, 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_ENABLE, 1);
|
||||
OUT_RING (chan, 1);
|
||||
/* For occlusion queries we have to change the storage, because a previous
|
||||
* query might set the initial render conition to FALSE even *after* we re-
|
||||
* initialized it to TRUE.
|
||||
*/
|
||||
if (q->type == PIPE_QUERY_OCCLUSION_COUNTER) {
|
||||
q->offset += 16;
|
||||
q->data += 16 / sizeof(*q->data);
|
||||
if (q->offset - q->base == NV50_QUERY_ALLOC_SPACE)
|
||||
nv50_query_allocate(nv50, q, NV50_QUERY_ALLOC_SPACE);
|
||||
|
||||
q->ready = FALSE;
|
||||
/* XXX: can we do this with the GPU, and sync with respect to a previous
|
||||
* query ?
|
||||
*/
|
||||
q->data[1] = 1; /* initial render condition = TRUE */
|
||||
}
|
||||
if (!q->is64bit)
|
||||
q->data[0] = q->sequence++; /* the previously used one */
|
||||
|
||||
switch (q->type) {
|
||||
case PIPE_QUERY_OCCLUSION_COUNTER:
|
||||
BEGIN_RING(chan, RING_3D(COUNTER_RESET), 1);
|
||||
OUT_RING (chan, NV50_3D_COUNTER_RESET_SAMPLECNT);
|
||||
BEGIN_RING(chan, RING_3D(SAMPLECNT_ENABLE), 1);
|
||||
OUT_RING (chan, 1);
|
||||
break;
|
||||
case PIPE_QUERY_PRIMITIVES_GENERATED: /* store before & after instead ? */
|
||||
BEGIN_RING(chan, RING_3D(COUNTER_RESET), 1);
|
||||
OUT_RING (chan, NV50_3D_COUNTER_RESET_GENERATED_PRIMITIVES);
|
||||
break;
|
||||
case PIPE_QUERY_PRIMITIVES_EMITTED:
|
||||
BEGIN_RING(chan, RING_3D(COUNTER_RESET), 1);
|
||||
OUT_RING (chan, NV50_3D_COUNTER_RESET_TRANSFORM_FEEDBACK);
|
||||
break;
|
||||
case PIPE_QUERY_SO_STATISTICS:
|
||||
BEGIN_RING_NI(chan, RING_3D(COUNTER_RESET), 2);
|
||||
OUT_RING (chan, NV50_3D_COUNTER_RESET_TRANSFORM_FEEDBACK);
|
||||
OUT_RING (chan, NV50_3D_COUNTER_RESET_GENERATED_PRIMITIVES);
|
||||
break;
|
||||
case PIPE_QUERY_TIMESTAMP_DISJOINT:
|
||||
case PIPE_QUERY_TIME_ELAPSED:
|
||||
nv50_query_get(chan, q, 0x10, 0x00005002);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
q->ready = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nv50_query *q = nv50_query(pq);
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_query *q = nv50_query(pq);
|
||||
|
||||
MARK_RING (chan, 5, 2); /* flush on lack of space or relocs */
|
||||
BEGIN_RING(chan, tesla, NV50TCL_QUERY_ADDRESS_HIGH, 4);
|
||||
OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, 0x00000000);
|
||||
OUT_RING (chan, 0x0100f002);
|
||||
switch (q->type) {
|
||||
case PIPE_QUERY_OCCLUSION_COUNTER:
|
||||
nv50_query_get(chan, q, 0, 0x0100f002);
|
||||
BEGIN_RING(chan, RING_3D(SAMPLECNT_ENABLE), 1);
|
||||
OUT_RING (chan, 0);
|
||||
break;
|
||||
case PIPE_QUERY_PRIMITIVES_GENERATED:
|
||||
nv50_query_get(chan, q, 0, 0x06805002);
|
||||
break;
|
||||
case PIPE_QUERY_PRIMITIVES_EMITTED:
|
||||
nv50_query_get(chan, q, 0, 0x05805002);
|
||||
break;
|
||||
case PIPE_QUERY_SO_STATISTICS:
|
||||
nv50_query_get(chan, q, 0x00, 0x05805002);
|
||||
nv50_query_get(chan, q, 0x10, 0x06805002);
|
||||
break;
|
||||
case PIPE_QUERY_TIMESTAMP_DISJOINT:
|
||||
case PIPE_QUERY_TIME_ELAPSED:
|
||||
nv50_query_get(chan, q, 0, 0x00005002);
|
||||
break;
|
||||
case PIPE_QUERY_GPU_FINISHED:
|
||||
nv50_query_get(chan, q, 0, 0x1000f010);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_ENABLE, 1);
|
||||
OUT_RING (chan, 0);
|
||||
static INLINE boolean
|
||||
nv50_query_ready(struct nv50_query *q)
|
||||
{
|
||||
return q->ready || (!q->is64bit && (q->data[0] == q->sequence));
|
||||
}
|
||||
|
||||
static INLINE boolean
|
||||
nv50_query_wait(struct nv50_query *q)
|
||||
{
|
||||
int ret = nouveau_bo_map(q->bo, NOUVEAU_BO_RD);
|
||||
if (ret)
|
||||
return FALSE;
|
||||
nouveau_bo_unmap(q->bo);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static boolean
|
||||
nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq,
|
||||
boolean wait, void *vresult)
|
||||
boolean wait, void *result)
|
||||
{
|
||||
uint64_t *result = (uint64_t*)vresult;
|
||||
struct nv50_query *q = nv50_query(pq);
|
||||
int ret;
|
||||
struct nv50_query *q = nv50_query(pq);
|
||||
uint64_t *res64 = result;
|
||||
boolean *res8 = result;
|
||||
uint64_t *data64 = (uint64_t *)q->data;
|
||||
|
||||
if (!q->ready) {
|
||||
ret = nouveau_bo_map(q->bo, NOUVEAU_BO_RD |
|
||||
(wait ? 0 : NOUVEAU_BO_NOWAIT));
|
||||
if (ret)
|
||||
return false;
|
||||
q->result = ((uint32_t *)q->bo->map)[1];
|
||||
q->ready = TRUE;
|
||||
nouveau_bo_unmap(q->bo);
|
||||
}
|
||||
if (q->type == PIPE_QUERY_GPU_FINISHED) {
|
||||
res8[0] = nv50_query_ready(q);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*result = q->result;
|
||||
return q->ready;
|
||||
if (!q->ready) /* update ? */
|
||||
q->ready = nv50_query_ready(q);
|
||||
if (!q->ready) {
|
||||
struct nouveau_channel *chan = nv50_context(pipe)->screen->base.channel;
|
||||
if (!wait) {
|
||||
if (nouveau_bo_pending(q->bo) & NOUVEAU_BO_WR) /* for daft apps */
|
||||
FIRE_RING(chan);
|
||||
return FALSE;
|
||||
}
|
||||
if (!nv50_query_wait(q))
|
||||
return FALSE;
|
||||
}
|
||||
q->ready = TRUE;
|
||||
|
||||
switch (q->type) {
|
||||
case PIPE_QUERY_OCCLUSION_COUNTER: /* u32 sequence, u32 count, u64 time */
|
||||
res64[0] = q->data[1];
|
||||
break;
|
||||
case PIPE_QUERY_PRIMITIVES_GENERATED: /* u64 count, u64 time */
|
||||
case PIPE_QUERY_PRIMITIVES_EMITTED: /* u64 count, u64 time */
|
||||
res64[0] = data64[0];
|
||||
break;
|
||||
case PIPE_QUERY_SO_STATISTICS:
|
||||
res64[0] = data64[0];
|
||||
res64[1] = data64[1];
|
||||
break;
|
||||
case PIPE_QUERY_TIMESTAMP_DISJOINT: /* u32 sequence, u32 0, u64 time */
|
||||
res64[0] = 1000000000;
|
||||
res8[8] = (data64[0] == data64[2]) ? FALSE : TRUE;
|
||||
break;
|
||||
case PIPE_QUERY_TIME_ELAPSED:
|
||||
res64[0] = data64[1] - data64[3];
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_render_condition(struct pipe_context *pipe,
|
||||
struct pipe_query *pq, uint mode)
|
||||
struct pipe_query *pq, uint mode)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nv50_query *q;
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_query *q;
|
||||
|
||||
if (!pq) {
|
||||
BEGIN_RING(chan, tesla, NV50TCL_COND_MODE, 1);
|
||||
OUT_RING (chan, NV50TCL_COND_MODE_ALWAYS);
|
||||
return;
|
||||
}
|
||||
q = nv50_query(pq);
|
||||
if (!pq) {
|
||||
BEGIN_RING(chan, RING_3D(COND_MODE), 1);
|
||||
OUT_RING (chan, NV50_3D_COND_MODE_ALWAYS);
|
||||
return;
|
||||
}
|
||||
q = nv50_query(pq);
|
||||
|
||||
if (mode == PIPE_RENDER_COND_WAIT ||
|
||||
mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
|
||||
/* XXX: big fence, FIFO semaphore might be better */
|
||||
BEGIN_RING(chan, tesla, 0x0110, 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
if (mode == PIPE_RENDER_COND_WAIT ||
|
||||
mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
|
||||
BEGIN_RING(chan, RING_3D_(NV50_GRAPH_WAIT_FOR_IDLE), 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_COND_ADDRESS_HIGH, 3);
|
||||
OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
|
||||
OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
|
||||
OUT_RING (chan, NV50TCL_COND_MODE_RES);
|
||||
MARK_RING (chan, 4, 2);
|
||||
BEGIN_RING(chan, RING_3D(COND_ADDRESS_HIGH), 3);
|
||||
OUT_RELOCh(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
|
||||
OUT_RELOCl(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
|
||||
OUT_RING (chan, NV50_3D_COND_MODE_RES_NON_ZERO);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_init_query_functions(struct nv50_context *nv50)
|
||||
{
|
||||
nv50->pipe.create_query = nv50_query_create;
|
||||
nv50->pipe.destroy_query = nv50_query_destroy;
|
||||
nv50->pipe.begin_query = nv50_query_begin;
|
||||
nv50->pipe.end_query = nv50_query_end;
|
||||
nv50->pipe.get_query_result = nv50_query_result;
|
||||
nv50->pipe.render_condition = nv50_render_condition;
|
||||
nv50->pipe.create_query = nv50_query_create;
|
||||
nv50->pipe.destroy_query = nv50_query_destroy;
|
||||
nv50->pipe.begin_query = nv50_query_begin;
|
||||
nv50->pipe.end_query = nv50_query_end;
|
||||
nv50->pipe.get_query_result = nv50_query_result;
|
||||
nv50->pipe.render_condition = nv50_render_condition;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -3,65 +3,66 @@
|
|||
#include "nv50_resource.h"
|
||||
#include "nouveau/nouveau_screen.h"
|
||||
|
||||
|
||||
/* This doesn't look quite right - this query is supposed to ask
|
||||
* whether the particular context has references to the resource in
|
||||
* any unflushed rendering command buffer, and hence requires a
|
||||
* pipe->flush() for serializing some modification to that resource.
|
||||
*
|
||||
* This seems to be answering the question of whether the resource is
|
||||
* currently on hardware.
|
||||
*/
|
||||
static unsigned int
|
||||
static unsigned
|
||||
nv50_resource_is_referenced(struct pipe_context *pipe,
|
||||
struct pipe_resource *resource,
|
||||
unsigned level, int layer)
|
||||
struct pipe_resource *resource,
|
||||
unsigned face, int layer)
|
||||
{
|
||||
return nouveau_reference_flags(nv50_resource(resource)->bo);
|
||||
struct nv50_resource *res = nv50_resource(resource);
|
||||
unsigned flags = 0;
|
||||
unsigned bo_flags = nouveau_bo_pending(res->bo);
|
||||
|
||||
if (bo_flags & NOUVEAU_BO_RD)
|
||||
flags = PIPE_REFERENCED_FOR_READ;
|
||||
if (bo_flags & NOUVEAU_BO_WR)
|
||||
flags |= PIPE_REFERENCED_FOR_WRITE;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
nv50_resource_create(struct pipe_screen *screen,
|
||||
const struct pipe_resource *template)
|
||||
const struct pipe_resource *templ)
|
||||
{
|
||||
if (template->target == PIPE_BUFFER)
|
||||
return nv50_buffer_create(screen, template);
|
||||
else
|
||||
return nv50_miptree_create(screen, template);
|
||||
switch (templ->target) {
|
||||
case PIPE_BUFFER:
|
||||
return nv50_buffer_create(screen, templ);
|
||||
default:
|
||||
return nv50_miptree_create(screen, templ);
|
||||
}
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
nv50_resource_from_handle(struct pipe_screen * screen,
|
||||
const struct pipe_resource *template,
|
||||
struct winsys_handle *whandle)
|
||||
const struct pipe_resource *templ,
|
||||
struct winsys_handle *whandle)
|
||||
{
|
||||
if (template->target == PIPE_BUFFER)
|
||||
return NULL;
|
||||
else
|
||||
return nv50_miptree_from_handle(screen, template, whandle);
|
||||
if (templ->target == PIPE_BUFFER)
|
||||
return NULL;
|
||||
else
|
||||
return nv50_miptree_from_handle(screen, templ, whandle);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_init_resource_functions(struct pipe_context *pcontext)
|
||||
{
|
||||
pcontext->get_transfer = u_get_transfer_vtbl;
|
||||
pcontext->transfer_map = u_transfer_map_vtbl;
|
||||
pcontext->transfer_flush_region = u_transfer_flush_region_vtbl;
|
||||
pcontext->transfer_unmap = u_transfer_unmap_vtbl;
|
||||
pcontext->transfer_destroy = u_transfer_destroy_vtbl;
|
||||
pcontext->transfer_inline_write = u_transfer_inline_write_vtbl;
|
||||
pcontext->is_resource_referenced = nv50_resource_is_referenced;
|
||||
|
||||
pcontext->create_surface = nv50_miptree_surface_new;
|
||||
pcontext->surface_destroy = nv50_miptree_surface_del;
|
||||
pcontext->get_transfer = u_get_transfer_vtbl;
|
||||
pcontext->transfer_map = u_transfer_map_vtbl;
|
||||
pcontext->transfer_flush_region = u_transfer_flush_region_vtbl;
|
||||
pcontext->transfer_unmap = u_transfer_unmap_vtbl;
|
||||
pcontext->transfer_destroy = u_transfer_destroy_vtbl;
|
||||
pcontext->transfer_inline_write = u_transfer_inline_write_vtbl;
|
||||
pcontext->is_resource_referenced = nv50_resource_is_referenced;
|
||||
pcontext->create_surface = nv50_miptree_surface_new;
|
||||
pcontext->surface_destroy = nv50_miptree_surface_del;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_screen_init_resource_functions(struct pipe_screen *pscreen)
|
||||
{
|
||||
pscreen->resource_create = nv50_resource_create;
|
||||
pscreen->resource_from_handle = nv50_resource_from_handle;
|
||||
pscreen->resource_get_handle = u_resource_get_handle_vtbl;
|
||||
pscreen->resource_destroy = u_resource_destroy_vtbl;
|
||||
pscreen->user_buffer_create = nv50_user_buffer_create;
|
||||
pscreen->resource_create = nv50_resource_create;
|
||||
pscreen->resource_from_handle = nv50_resource_from_handle;
|
||||
pscreen->resource_get_handle = u_resource_get_handle_vtbl;
|
||||
pscreen->resource_destroy = u_resource_destroy_vtbl;
|
||||
pscreen->user_buffer_create = nv50_user_buffer_create;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,61 +1,164 @@
|
|||
|
||||
#ifndef NV50_RESOURCE_H
|
||||
#define NV50_RESOURCE_H
|
||||
#ifndef __NV50_RESOURCE_H__
|
||||
#define __NV50_RESOURCE_H__
|
||||
|
||||
#include "util/u_transfer.h"
|
||||
|
||||
#include "util/u_double_list.h"
|
||||
#define NOUVEAU_NVC0
|
||||
#include "nouveau/nouveau_winsys.h"
|
||||
#undef NOUVEAU_NVC0
|
||||
|
||||
#include "nv50_fence.h"
|
||||
|
||||
struct pipe_resource;
|
||||
struct nouveau_bo;
|
||||
struct nv50_context;
|
||||
|
||||
#define NV50_BUFFER_SCORE_MIN -25000
|
||||
#define NV50_BUFFER_SCORE_MAX 25000
|
||||
#define NV50_BUFFER_SCORE_VRAM_THRESHOLD 20000
|
||||
|
||||
/* This gets further specialized into either buffer or texture
|
||||
* structures. In the future we'll want to remove much of that
|
||||
* distinction, but for now try to keep as close to the existing code
|
||||
* as possible and use the vtbl struct to choose between the two
|
||||
* underlying implementations.
|
||||
/* DIRTY: buffer was (or will be after the next flush) written to by GPU and
|
||||
* resource->data has not been updated to reflect modified VRAM contents
|
||||
*
|
||||
* USER_MEMORY: resource->data is a pointer to client memory and may change
|
||||
* between GL calls
|
||||
*/
|
||||
#define NV50_BUFFER_STATUS_DIRTY (1 << 0)
|
||||
#define NV50_BUFFER_STATUS_USER_MEMORY (1 << 7)
|
||||
|
||||
/* Resources, if mapped into the GPU's address space, are guaranteed to
|
||||
* have constant virtual addresses.
|
||||
* The address of a resource will lie within the nouveau_bo referenced,
|
||||
* and this bo should be added to the memory manager's validation list.
|
||||
*/
|
||||
struct nv50_resource {
|
||||
struct pipe_resource base;
|
||||
const struct u_resource_vtbl *vtbl;
|
||||
struct nouveau_bo *bo;
|
||||
struct pipe_resource base;
|
||||
const struct u_resource_vtbl *vtbl;
|
||||
|
||||
uint8_t *data;
|
||||
struct nouveau_bo *bo;
|
||||
uint32_t offset;
|
||||
|
||||
uint8_t status;
|
||||
uint8_t domain;
|
||||
|
||||
int16_t score; /* low if mapped very often, if high can move to VRAM */
|
||||
|
||||
struct nv50_fence *fence;
|
||||
struct nv50_fence *fence_wr;
|
||||
|
||||
struct nv50_mm_allocation *mm;
|
||||
};
|
||||
|
||||
void
|
||||
nv50_buffer_release_gpu_storage(struct nv50_resource *);
|
||||
|
||||
boolean
|
||||
nv50_buffer_download(struct nv50_context *, struct nv50_resource *,
|
||||
unsigned start, unsigned size);
|
||||
|
||||
boolean
|
||||
nv50_buffer_migrate(struct nv50_context *,
|
||||
struct nv50_resource *, unsigned domain);
|
||||
|
||||
static INLINE void
|
||||
nv50_buffer_adjust_score(struct nv50_context *nv50, struct nv50_resource *res,
|
||||
int16_t score)
|
||||
{
|
||||
if (score < 0) {
|
||||
if (res->score > NV50_BUFFER_SCORE_MIN)
|
||||
res->score += score;
|
||||
} else
|
||||
if (score > 0){
|
||||
if (res->score < NV50_BUFFER_SCORE_MAX)
|
||||
res->score += score;
|
||||
if (res->domain == NOUVEAU_BO_GART &&
|
||||
res->score > NV50_BUFFER_SCORE_VRAM_THRESHOLD)
|
||||
nv50_buffer_migrate(nv50, res, NOUVEAU_BO_VRAM);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: wait for fence (atm only using this for vertex push) */
|
||||
static INLINE void *
|
||||
nv50_resource_map_offset(struct nv50_context *nv50,
|
||||
struct nv50_resource *res, uint32_t offset,
|
||||
uint32_t flags)
|
||||
{
|
||||
void *map;
|
||||
|
||||
nv50_buffer_adjust_score(nv50, res, -250);
|
||||
|
||||
if ((res->domain == NOUVEAU_BO_VRAM) &&
|
||||
(res->status & NV50_BUFFER_STATUS_DIRTY))
|
||||
nv50_buffer_download(nv50, res, 0, res->base.width0);
|
||||
|
||||
if ((res->domain != NOUVEAU_BO_GART) ||
|
||||
(res->status & NV50_BUFFER_STATUS_USER_MEMORY))
|
||||
return res->data + offset;
|
||||
|
||||
if (res->mm)
|
||||
flags |= NOUVEAU_BO_NOSYNC;
|
||||
|
||||
if (nouveau_bo_map_range(res->bo, res->offset + offset,
|
||||
res->base.width0, flags))
|
||||
return NULL;
|
||||
|
||||
map = res->bo->map;
|
||||
nouveau_bo_unmap(res->bo);
|
||||
return map;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
nv50_resource_unmap(struct nv50_resource *res)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
#define NV50_TILE_DIM_SHIFT(m, d) (((m) >> (d * 4)) & 0xf)
|
||||
|
||||
#define NV50_TILE_PITCH(m) (64 << 0)
|
||||
#define NV50_TILE_HEIGHT(m) ( 4 << NV50_TILE_DIM_SHIFT(m, 0))
|
||||
#define NV50_TILE_DEPTH(m) ( 1 << NV50_TILE_DIM_SHIFT(m, 1))
|
||||
|
||||
#define NV50_TILE_SIZE_2D(m) ((64 * 8) << \
|
||||
NV50_TILE_DIM_SHIFT(m, 0))
|
||||
|
||||
#define NV50_TILE_SIZE(m) (NV50_TILE_SIZE_2D(m) << NV50_TILE_DIM_SHIFT(m, 1))
|
||||
|
||||
struct nv50_miptree_level {
|
||||
int *image_offset;
|
||||
unsigned pitch;
|
||||
unsigned tile_mode;
|
||||
uint32_t offset;
|
||||
uint32_t pitch;
|
||||
uint32_t tile_mode;
|
||||
};
|
||||
|
||||
#define NV50_MAX_TEXTURE_LEVELS 16
|
||||
|
||||
struct nv50_miptree {
|
||||
struct nv50_resource base;
|
||||
|
||||
struct nv50_miptree_level level[NV50_MAX_TEXTURE_LEVELS];
|
||||
int image_nr;
|
||||
int total_size;
|
||||
struct nv50_resource base;
|
||||
struct nv50_miptree_level level[NV50_MAX_TEXTURE_LEVELS];
|
||||
uint32_t total_size;
|
||||
uint32_t layer_stride;
|
||||
boolean layout_3d; /* TRUE if layer count varies with mip level */
|
||||
};
|
||||
|
||||
static INLINE struct nv50_miptree *
|
||||
nv50_miptree(struct pipe_resource *pt)
|
||||
{
|
||||
return (struct nv50_miptree *)pt;
|
||||
return (struct nv50_miptree *)pt;
|
||||
}
|
||||
|
||||
|
||||
static INLINE
|
||||
struct nv50_resource *nv50_resource(struct pipe_resource *resource)
|
||||
static INLINE struct nv50_resource *
|
||||
nv50_resource(struct pipe_resource *resource)
|
||||
{
|
||||
return (struct nv50_resource *)resource;
|
||||
return (struct nv50_resource *)resource;
|
||||
}
|
||||
|
||||
/* is resource mapped into the GPU's address space (i.e. VRAM or GART) ? */
|
||||
static INLINE boolean
|
||||
nv50_resource_mapped_by_gpu(struct pipe_resource *resource)
|
||||
{
|
||||
return nv50_resource(resource)->bo->handle;
|
||||
return nv50_resource(resource)->domain != 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -64,34 +167,37 @@ nv50_init_resource_functions(struct pipe_context *pcontext);
|
|||
void
|
||||
nv50_screen_init_resource_functions(struct pipe_screen *pscreen);
|
||||
|
||||
/* Internal functions
|
||||
/* Internal functions:
|
||||
*/
|
||||
struct pipe_resource *
|
||||
nv50_miptree_create(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *tmp);
|
||||
const struct pipe_resource *tmp);
|
||||
|
||||
struct pipe_resource *
|
||||
nv50_miptree_from_handle(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *template,
|
||||
struct winsys_handle *whandle);
|
||||
const struct pipe_resource *template,
|
||||
struct winsys_handle *whandle);
|
||||
|
||||
struct pipe_resource *
|
||||
nv50_buffer_create(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *template);
|
||||
const struct pipe_resource *templ);
|
||||
|
||||
struct pipe_resource *
|
||||
nv50_user_buffer_create(struct pipe_screen *screen,
|
||||
void *ptr,
|
||||
unsigned bytes,
|
||||
unsigned usage);
|
||||
void *ptr,
|
||||
unsigned bytes,
|
||||
unsigned usage);
|
||||
|
||||
|
||||
struct pipe_surface *
|
||||
nv50_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt,
|
||||
const struct pipe_surface *surf_tmpl);
|
||||
nv50_miptree_surface_new(struct pipe_context *,
|
||||
struct pipe_resource *,
|
||||
const struct pipe_surface *templ);
|
||||
|
||||
void
|
||||
nv50_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps);
|
||||
nv50_miptree_surface_del(struct pipe_context *, struct pipe_surface *);
|
||||
|
||||
boolean
|
||||
nv50_user_buffer_upload(struct nv50_resource *, unsigned base, unsigned size);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,53 +1,193 @@
|
|||
#ifndef __NV50_SCREEN_H__
|
||||
#define __NV50_SCREEN_H__
|
||||
|
||||
#define NOUVEAU_NVC0
|
||||
#include "nouveau/nouveau_screen.h"
|
||||
#undef NOUVEAU_NVC0
|
||||
#include "nv50_winsys.h"
|
||||
#include "nv50_stateobj.h"
|
||||
|
||||
#define NV50_TIC_MAX_ENTRIES 2048
|
||||
#define NV50_TSC_MAX_ENTRIES 2048
|
||||
|
||||
struct nv50_mman;
|
||||
struct nv50_context;
|
||||
struct nv50_fence;
|
||||
|
||||
#define NV50_SCRATCH_SIZE (2 << 20)
|
||||
#define NV50_SCRATCH_NR_BUFFERS 2
|
||||
|
||||
struct nv50_screen {
|
||||
struct nouveau_screen base;
|
||||
struct nouveau_screen base;
|
||||
struct nouveau_winsys *nvws;
|
||||
|
||||
struct nouveau_winsys *nvws;
|
||||
struct nv50_context *cur_ctx;
|
||||
|
||||
struct nv50_context *cur_ctx;
|
||||
struct nouveau_bo *code;
|
||||
struct nouveau_bo *uniforms;
|
||||
struct nouveau_bo *txc; /* TIC (offset 0) and TSC (65536) */
|
||||
struct nouveau_bo *stack_bo;
|
||||
struct nouveau_bo *tls_bo;
|
||||
|
||||
struct nouveau_grobj *tesla;
|
||||
struct nouveau_grobj *eng2d;
|
||||
struct nouveau_grobj *m2mf;
|
||||
struct nouveau_notifier *sync;
|
||||
uint64_t tls_size;
|
||||
|
||||
struct nouveau_bo *constbuf_misc[1];
|
||||
struct nouveau_bo *constbuf_parm[PIPE_SHADER_TYPES];
|
||||
struct nouveau_resource *vp_code_heap;
|
||||
struct nouveau_resource *gp_code_heap;
|
||||
struct nouveau_resource *fp_code_heap;
|
||||
|
||||
struct nouveau_resource *immd_heap;
|
||||
struct {
|
||||
void **entries;
|
||||
int next;
|
||||
uint32_t lock[NV50_TIC_MAX_ENTRIES / 32];
|
||||
} tic;
|
||||
|
||||
struct {
|
||||
void **entries;
|
||||
int next;
|
||||
uint32_t lock[NV50_TSC_MAX_ENTRIES / 32];
|
||||
} tsc;
|
||||
|
||||
struct nouveau_bo *tic;
|
||||
struct nouveau_bo *tsc;
|
||||
struct {
|
||||
uint32_t *map;
|
||||
struct nv50_fence *head;
|
||||
struct nv50_fence *tail;
|
||||
struct nv50_fence *current;
|
||||
uint32_t sequence;
|
||||
uint32_t sequence_ack;
|
||||
struct nouveau_bo *bo;
|
||||
} fence;
|
||||
|
||||
struct nouveau_bo *stack_bo; /* control flow stack */
|
||||
struct nouveau_bo *local_bo; /* l[] memory */
|
||||
struct nouveau_notifier *sync;
|
||||
|
||||
boolean force_push;
|
||||
struct nv50_mman *mm_GART;
|
||||
struct nv50_mman *mm_VRAM;
|
||||
struct nv50_mman *mm_VRAM_fe0;
|
||||
|
||||
struct nouveau_grobj *tesla;
|
||||
struct nouveau_grobj *eng2d;
|
||||
struct nouveau_grobj *m2mf;
|
||||
};
|
||||
|
||||
static INLINE struct nv50_screen *
|
||||
nv50_screen(struct pipe_screen *screen)
|
||||
{
|
||||
return (struct nv50_screen *)screen;
|
||||
return (struct nv50_screen *)screen;
|
||||
}
|
||||
|
||||
extern void nv50_screen_relocs(struct nv50_screen *);
|
||||
/* Since a resource can be migrated, we need to decouple allocations from
|
||||
* them. This struct is linked with fences for delayed freeing of allocs.
|
||||
*/
|
||||
struct nv50_mm_allocation {
|
||||
struct nv50_mm_allocation *next;
|
||||
void *priv;
|
||||
uint32_t offset;
|
||||
};
|
||||
|
||||
extern void nv50_screen_reloc_constbuf(struct nv50_screen *, unsigned cbi);
|
||||
static INLINE void
|
||||
nv50_fence_sched_release(struct nv50_fence *nf, struct nv50_mm_allocation *mm)
|
||||
{
|
||||
mm->next = nf->buffers;
|
||||
nf->buffers = mm;
|
||||
}
|
||||
|
||||
extern struct nv50_mman *
|
||||
nv50_mm_create(struct nouveau_device *, uint32_t domain, uint32_t storage_type);
|
||||
|
||||
extern void
|
||||
nv50_mm_destroy(struct nv50_mman *);
|
||||
|
||||
extern struct nv50_mm_allocation *
|
||||
nv50_mm_allocate(struct nv50_mman *,
|
||||
uint32_t size, struct nouveau_bo **, uint32_t *offset);
|
||||
extern void
|
||||
nv50_mm_free(struct nv50_mm_allocation *);
|
||||
|
||||
void nv50_screen_make_buffers_resident(struct nv50_screen *);
|
||||
|
||||
int nv50_screen_tic_alloc(struct nv50_screen *, void *);
|
||||
int nv50_screen_tsc_alloc(struct nv50_screen *, void *);
|
||||
|
||||
static INLINE void
|
||||
nv50_resource_fence(struct nv50_resource *res, uint32_t flags)
|
||||
{
|
||||
struct nv50_screen *screen = nv50_screen(res->base.screen);
|
||||
|
||||
if (res->mm) {
|
||||
nv50_fence_reference(&res->fence, screen->fence.current);
|
||||
|
||||
if (flags & NOUVEAU_BO_WR)
|
||||
nv50_fence_reference(&res->fence_wr, screen->fence.current);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
nv50_resource_validate(struct nv50_resource *res, uint32_t flags)
|
||||
{
|
||||
struct nv50_screen *screen = nv50_screen(res->base.screen);
|
||||
|
||||
if (likely(res->bo)) {
|
||||
nouveau_bo_validate(screen->base.channel, res->bo, flags);
|
||||
|
||||
nv50_resource_fence(res, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean
|
||||
nv50_screen_fence_new(struct nv50_screen *, struct nv50_fence **, boolean emit);
|
||||
|
||||
void
|
||||
nv50_screen_fence_next(struct nv50_screen *);
|
||||
void
|
||||
nv50_screen_fence_update(struct nv50_screen *, boolean flushed);
|
||||
|
||||
static INLINE boolean
|
||||
nv50_screen_fence_emit(struct nv50_screen *screen)
|
||||
{
|
||||
nv50_fence_emit(screen->fence.current);
|
||||
|
||||
return nv50_screen_fence_new(screen, &screen->fence.current, FALSE);
|
||||
}
|
||||
|
||||
struct nv50_format {
|
||||
uint32_t rt;
|
||||
uint32_t tic;
|
||||
uint32_t vtx;
|
||||
uint32_t usage;
|
||||
uint32_t rt;
|
||||
uint32_t tic;
|
||||
uint32_t vtx;
|
||||
uint32_t usage;
|
||||
};
|
||||
|
||||
extern const struct nv50_format nv50_format_table[];
|
||||
|
||||
static INLINE void
|
||||
nv50_screen_tic_unlock(struct nv50_screen *screen, struct nv50_tic_entry *tic)
|
||||
{
|
||||
if (tic->id >= 0)
|
||||
screen->tic.lock[tic->id / 32] &= ~(1 << (tic->id % 32));
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
nv50_screen_tsc_unlock(struct nv50_screen *screen, struct nv50_tsc_entry *tsc)
|
||||
{
|
||||
if (tsc->id >= 0)
|
||||
screen->tsc.lock[tsc->id / 32] &= ~(1 << (tsc->id % 32));
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
nv50_screen_tic_free(struct nv50_screen *screen, struct nv50_tic_entry *tic)
|
||||
{
|
||||
if (tic->id >= 0) {
|
||||
screen->tic.entries[tic->id] = NULL;
|
||||
screen->tic.lock[tic->id / 32] &= ~(1 << (tic->id % 32));
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
nv50_screen_tsc_free(struct nv50_screen *screen, struct nv50_tsc_entry *tsc)
|
||||
{
|
||||
if (tsc->id >= 0) {
|
||||
screen->tsc.entries[tsc->id] = NULL;
|
||||
screen->tsc.lock[tsc->id / 32] &= ~(1 << (tsc->id % 32));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,422 +28,234 @@
|
|||
|
||||
#include "nv50_context.h"
|
||||
|
||||
static void
|
||||
nv50_transfer_constbuf(struct nv50_context *nv50,
|
||||
struct pipe_resource *buf, unsigned size, unsigned cbi)
|
||||
{
|
||||
struct pipe_context *pipe = &nv50->pipe;
|
||||
struct pipe_transfer *transfer;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
uint32_t *map;
|
||||
unsigned count, start;
|
||||
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
map = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &transfer);
|
||||
if (!map)
|
||||
return;
|
||||
|
||||
count = (buf->width0 + 3) / 4;
|
||||
start = 0;
|
||||
|
||||
while (count) {
|
||||
unsigned nr = AVAIL_RING(chan);
|
||||
|
||||
if (nr < 8) {
|
||||
FIRE_RING(chan);
|
||||
continue;
|
||||
}
|
||||
nr = MIN2(count, nr - 7);
|
||||
nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
nv50_screen_reloc_constbuf(nv50->screen, cbi);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
|
||||
OUT_RING (chan, (start << 8) | cbi);
|
||||
BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), nr);
|
||||
OUT_RINGp (chan, map, nr);
|
||||
|
||||
count -= nr;
|
||||
start += nr;
|
||||
map += nr;
|
||||
}
|
||||
|
||||
pipe_buffer_unmap(pipe, transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
|
||||
void
|
||||
nv50_constbufs_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
unsigned cbi;
|
||||
unsigned s;
|
||||
|
||||
if (p->immd_size) {
|
||||
uint32_t *data = p->immd;
|
||||
unsigned count = p->immd_size / 4;
|
||||
unsigned start = 0;
|
||||
for (s = 0; s < 3; ++s) {
|
||||
struct nv50_resource *res;
|
||||
int i;
|
||||
unsigned p, b;
|
||||
|
||||
while (count) {
|
||||
unsigned nr = AVAIL_RING(chan);
|
||||
if (s == PIPE_SHADER_FRAGMENT)
|
||||
p = NV50_3D_SET_PROGRAM_CB_PROGRAM_FRAGMENT;
|
||||
else
|
||||
if (s == PIPE_SHADER_GEOMETRY)
|
||||
p = NV50_3D_SET_PROGRAM_CB_PROGRAM_GEOMETRY;
|
||||
else
|
||||
p = NV50_3D_SET_PROGRAM_CB_PROGRAM_VERTEX;
|
||||
|
||||
if (nr < 8) {
|
||||
FIRE_RING(chan);
|
||||
while (nv50->constbuf_dirty[s]) {
|
||||
struct nouveau_bo *bo;
|
||||
unsigned start = 0;
|
||||
unsigned words = 0;
|
||||
|
||||
i = ffs(nv50->constbuf_dirty[s]) - 1;
|
||||
nv50->constbuf_dirty[s] &= ~(1 << i);
|
||||
|
||||
res = nv50_resource(nv50->constbuf[s][i]);
|
||||
if (!res) {
|
||||
if (i != 0) {
|
||||
BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1);
|
||||
OUT_RING (chan, (i << 8) | p | 0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
nr = MIN2(count, nr - 7);
|
||||
nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
nv50_screen_reloc_constbuf(nv50->screen, NV50_CB_PMISC);
|
||||
if (i == 0) {
|
||||
b = NV50_CB_PVP + s;
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
|
||||
OUT_RING (chan, (start << 8) | NV50_CB_PMISC);
|
||||
BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), nr);
|
||||
OUT_RINGp (chan, data, nr);
|
||||
/* always upload GL uniforms through CB DATA */
|
||||
bo = nv50->screen->uniforms;
|
||||
words = res->base.width0 / 4;
|
||||
} else {
|
||||
b = s * 16 + i;
|
||||
|
||||
count -= nr;
|
||||
start += nr;
|
||||
data += nr;
|
||||
assert(0);
|
||||
|
||||
if (!nv50_resource_mapped_by_gpu(&res->base)) {
|
||||
nv50_buffer_migrate(nv50, res, NOUVEAU_BO_VRAM);
|
||||
|
||||
BEGIN_RING(chan, RING_3D(CODE_CB_FLUSH), 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
MARK_RING (chan, 6, 2);
|
||||
BEGIN_RING(chan, RING_3D(CB_DEF_ADDRESS_HIGH), 3);
|
||||
OUT_RESRCh(chan, res, 0, NOUVEAU_BO_RD);
|
||||
OUT_RESRCl(chan, res, 0, NOUVEAU_BO_RD);
|
||||
OUT_RING (chan, (b << 16) | (res->base.width0 & 0xffff));
|
||||
BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1);
|
||||
OUT_RING (chan, (b << 12) | (i << 8) | p | 1);
|
||||
|
||||
bo = res->bo;
|
||||
|
||||
nv50_bufctx_add_resident(nv50, NV50_BUFCTX_CONSTANT, res,
|
||||
res->domain | NOUVEAU_BO_RD);
|
||||
}
|
||||
|
||||
if (words) {
|
||||
MARK_RING(chan, 8, 1);
|
||||
|
||||
nouveau_bo_validate(chan, bo, res->domain | NOUVEAU_BO_WR);
|
||||
}
|
||||
|
||||
while (words) {
|
||||
unsigned nr = AVAIL_RING(chan);
|
||||
|
||||
if (nr < 16) {
|
||||
FIRE_RING(chan);
|
||||
nouveau_bo_validate(chan, bo, res->domain | NOUVEAU_BO_WR);
|
||||
continue;
|
||||
}
|
||||
nr = MIN2(MIN2(nr - 3, words), NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
|
||||
OUT_RING (chan, (start << 8) | b);
|
||||
BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nr);
|
||||
OUT_RINGp (chan, &res->data[start * 4], nr);
|
||||
|
||||
start += nr;
|
||||
words -= nr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the state tracker doesn't change the constbuf, and it is first
|
||||
* validated with a program that doesn't use it, this check prevents
|
||||
* it from even being uploaded. */
|
||||
/*
|
||||
if (p->parm_size == 0)
|
||||
return;
|
||||
*/
|
||||
|
||||
switch (p->type) {
|
||||
case PIPE_SHADER_VERTEX:
|
||||
cbi = NV50_CB_PVP;
|
||||
break;
|
||||
case PIPE_SHADER_FRAGMENT:
|
||||
cbi = NV50_CB_PFP;
|
||||
break;
|
||||
case PIPE_SHADER_GEOMETRY:
|
||||
cbi = NV50_CB_PGP;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
nv50_transfer_constbuf(nv50, nv50->constbuf[p->type], p->parm_size, cbi);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p)
|
||||
{
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
int ret;
|
||||
unsigned offset;
|
||||
unsigned size = p->code_size;
|
||||
uint32_t *data = p->code;
|
||||
|
||||
assert(p->translated);
|
||||
|
||||
/* TODO: use a single bo (for each type) for shader code */
|
||||
if (p->bo)
|
||||
return;
|
||||
ret = nouveau_bo_new(chan->device, NOUVEAU_BO_VRAM, 0x100, size, &p->bo);
|
||||
assert(!ret);
|
||||
|
||||
offset = p->code_start = 0;
|
||||
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 2);
|
||||
OUT_RING (chan, NV50_2D_DST_FORMAT_R8_UNORM);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_PITCH, 1);
|
||||
OUT_RING (chan, 0x40000);
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_WIDTH, 2);
|
||||
OUT_RING (chan, 0x10000);
|
||||
OUT_RING (chan, 1);
|
||||
|
||||
while (size) {
|
||||
unsigned nr = size / 4;
|
||||
|
||||
if (AVAIL_RING(chan) < 32)
|
||||
FIRE_RING(chan);
|
||||
|
||||
nr = MIN2(nr, AVAIL_RING(chan) - 18);
|
||||
nr = MIN2(nr, 1792);
|
||||
if (nr < (size / 4))
|
||||
nr &= ~0x3f;
|
||||
assert(!(size & 3));
|
||||
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_ADDRESS_HIGH, 2);
|
||||
OUT_RELOCh(chan, p->bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, p->bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_SIFC_BITMAP_ENABLE, 2);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, NV50_2D_SIFC_FORMAT_R8_UNORM);
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_SIFC_WIDTH, 10);
|
||||
OUT_RING (chan, nr * 4);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
BEGIN_RING_NI(chan, eng2d, NV50_2D_SIFC_DATA, nr);
|
||||
OUT_RINGp (chan, data, nr);
|
||||
|
||||
data += nr;
|
||||
offset += nr * 4;
|
||||
size -= nr * 4;
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CODE_CB_FLUSH, 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_vp_update_stateobj(struct nv50_context *nv50, struct nv50_program *p)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(5, 7, 2);
|
||||
|
||||
nv50_program_validate_code(nv50, p);
|
||||
|
||||
so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2);
|
||||
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_HIGH, 0, 0);
|
||||
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_LOW, 0, 0);
|
||||
so_method(so, tesla, NV50TCL_VP_ATTR_EN_0, 2);
|
||||
so_data (so, p->vp.attrs[0]);
|
||||
so_data (so, p->vp.attrs[1]);
|
||||
so_method(so, tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
|
||||
so_data (so, p->max_out);
|
||||
so_method(so, tesla, NV50TCL_VP_REG_ALLOC_TEMP, 1);
|
||||
so_data (so, p->max_gpr);
|
||||
so_method(so, tesla, NV50TCL_VP_START_ID, 1);
|
||||
so_data (so, p->code_start);
|
||||
|
||||
so_ref(so, &p->so);
|
||||
so_ref(NULL, &so);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_fp_update_stateobj(struct nv50_context *nv50, struct nv50_program *p)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(6, 7, 2);
|
||||
|
||||
nv50_program_validate_code(nv50, p);
|
||||
|
||||
so_method(so, tesla, NV50TCL_FP_ADDRESS_HIGH, 2);
|
||||
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_HIGH, 0, 0);
|
||||
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_LOW, 0, 0);
|
||||
so_method(so, tesla, NV50TCL_FP_REG_ALLOC_TEMP, 1);
|
||||
so_data (so, p->max_gpr);
|
||||
so_method(so, tesla, NV50TCL_FP_RESULT_COUNT, 1);
|
||||
so_data (so, p->max_out);
|
||||
so_method(so, tesla, NV50TCL_FP_CONTROL, 1);
|
||||
so_data (so, p->fp.flags[0]);
|
||||
so_method(so, tesla, NV50TCL_FP_CTRL_UNK196C, 1);
|
||||
so_data (so, p->fp.flags[1]);
|
||||
so_method(so, tesla, NV50TCL_FP_START_ID, 1);
|
||||
so_data (so, p->code_start);
|
||||
|
||||
so_ref(so, &p->so);
|
||||
so_ref(NULL, &so);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_gp_update_stateobj(struct nv50_context *nv50, struct nv50_program *p)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(6, 7, 2);
|
||||
|
||||
nv50_program_validate_code(nv50, p);
|
||||
|
||||
so_method(so, tesla, NV50TCL_GP_ADDRESS_HIGH, 2);
|
||||
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_HIGH, 0, 0);
|
||||
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_LOW, 0, 0);
|
||||
so_method(so, tesla, NV50TCL_GP_REG_ALLOC_TEMP, 1);
|
||||
so_data (so, p->max_gpr);
|
||||
so_method(so, tesla, NV50TCL_GP_REG_ALLOC_RESULT, 1);
|
||||
so_data (so, p->max_out);
|
||||
so_method(so, tesla, NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE, 1);
|
||||
so_data (so, p->gp.prim_type);
|
||||
so_method(so, tesla, NV50TCL_GP_VERTEX_OUTPUT_COUNT, 1);
|
||||
so_data (so, p->gp.vert_count);
|
||||
so_method(so, tesla, NV50TCL_GP_START_ID, 1);
|
||||
so_data (so, p->code_start);
|
||||
|
||||
so_ref(so, &p->so);
|
||||
so_ref(NULL, &so);
|
||||
}
|
||||
|
||||
static boolean
|
||||
nv50_program_validate(struct nv50_program *p)
|
||||
nv50_program_validate(struct nv50_context *nv50, struct nv50_program *prog)
|
||||
{
|
||||
p->translated = nv50_program_tx(p);
|
||||
assert(p->translated);
|
||||
return p->translated;
|
||||
}
|
||||
struct nouveau_resource *heap;
|
||||
int ret;
|
||||
unsigned size;
|
||||
|
||||
static INLINE void
|
||||
nv50_program_validate_common(struct nv50_context *nv50, struct nv50_program *p)
|
||||
{
|
||||
nv50_program_validate_code(nv50, p);
|
||||
if (prog->translated)
|
||||
return TRUE;
|
||||
|
||||
if (p->uses_lmem)
|
||||
nv50->req_lmem |= 1 << p->type;
|
||||
prog->translated = nv50_program_translate(prog);
|
||||
if (!prog->translated)
|
||||
return FALSE;
|
||||
|
||||
if (prog->type == PIPE_SHADER_FRAGMENT) heap = nv50->screen->fp_code_heap;
|
||||
if (prog->type == PIPE_SHADER_GEOMETRY) heap = nv50->screen->gp_code_heap;
|
||||
else
|
||||
nv50->req_lmem &= ~(1 << p->type);
|
||||
heap = nv50->screen->vp_code_heap;
|
||||
|
||||
size = align(prog->code_size, 0x100);
|
||||
|
||||
ret = nouveau_resource_alloc(heap, size, prog, &prog->res);
|
||||
if (ret)
|
||||
return FALSE;
|
||||
prog->code_base = prog->res->start;
|
||||
|
||||
nv50_sifc_linear_u8(nv50, nv50->screen->code, NOUVEAU_BO_VRAM,
|
||||
(prog->type << 16) + prog->code_base, prog->code_size,
|
||||
prog->code);
|
||||
|
||||
BEGIN_RING(nv50->screen->base.channel, RING_3D(CODE_CB_FLUSH), 1);
|
||||
OUT_RING (nv50->screen->base.channel, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct nouveau_stateobj *
|
||||
void
|
||||
nv50_vertprog_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nv50_program *p = nv50->vertprog;
|
||||
struct nouveau_stateobj *so = NULL;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_program *vp = nv50->vertprog;
|
||||
|
||||
if (!p->translated) {
|
||||
if (nv50_program_validate(p))
|
||||
nv50_vp_update_stateobj(nv50, p);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
if (!nv50_program_validate(nv50, vp))
|
||||
return;
|
||||
|
||||
if (nv50->dirty & NV50_NEW_VERTPROG_CB)
|
||||
nv50_program_validate_data(nv50, p);
|
||||
|
||||
if (!(nv50->dirty & NV50_NEW_VERTPROG))
|
||||
return NULL;
|
||||
|
||||
nv50_program_validate_common(nv50, p);
|
||||
|
||||
so_ref(p->so, &so);
|
||||
return so;
|
||||
BEGIN_RING(chan, RING_3D(VP_ATTR_EN(0)), 2);
|
||||
OUT_RING (chan, vp->vp.attrs[0]);
|
||||
OUT_RING (chan, vp->vp.attrs[1]);
|
||||
BEGIN_RING(chan, RING_3D(VP_REG_ALLOC_RESULT), 1);
|
||||
OUT_RING (chan, vp->max_out);
|
||||
BEGIN_RING(chan, RING_3D(VP_REG_ALLOC_TEMP), 1);
|
||||
OUT_RING (chan, vp->max_gpr);
|
||||
BEGIN_RING(chan, RING_3D(VP_START_ID), 1);
|
||||
OUT_RING (chan, vp->code_base);
|
||||
}
|
||||
|
||||
struct nouveau_stateobj *
|
||||
void
|
||||
nv50_fragprog_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nv50_program *p = nv50->fragprog;
|
||||
struct nouveau_stateobj *so = NULL;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_program *fp = nv50->fragprog;
|
||||
|
||||
if (!p->translated) {
|
||||
if (nv50_program_validate(p))
|
||||
nv50_fp_update_stateobj(nv50, p);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
if (!nv50_program_validate(nv50, fp))
|
||||
return;
|
||||
|
||||
if (nv50->dirty & NV50_NEW_FRAGPROG_CB)
|
||||
nv50_program_validate_data(nv50, p);
|
||||
|
||||
if (!(nv50->dirty & NV50_NEW_FRAGPROG))
|
||||
return NULL;
|
||||
|
||||
nv50_program_validate_common(nv50, p);
|
||||
|
||||
so_ref(p->so, &so);
|
||||
return so;
|
||||
BEGIN_RING(chan, RING_3D(FP_REG_ALLOC_TEMP), 1);
|
||||
OUT_RING (chan, fp->max_gpr);
|
||||
BEGIN_RING(chan, RING_3D(FP_RESULT_COUNT), 1);
|
||||
OUT_RING (chan, fp->max_out);
|
||||
BEGIN_RING(chan, RING_3D(FP_CONTROL), 1);
|
||||
OUT_RING (chan, fp->fp.flags[0]);
|
||||
BEGIN_RING(chan, RING_3D(FP_CTRL_UNK196C), 1);
|
||||
OUT_RING (chan, fp->fp.flags[1]);
|
||||
BEGIN_RING(chan, RING_3D(FP_START_ID), 1);
|
||||
OUT_RING (chan, fp->code_base);
|
||||
}
|
||||
|
||||
struct nouveau_stateobj *
|
||||
nv50_geomprog_validate(struct nv50_context *nv50)
|
||||
void
|
||||
nv50_gmtyprog_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nv50_program *p = nv50->geomprog;
|
||||
struct nouveau_stateobj *so = NULL;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_program *gp = nv50->vertprog;
|
||||
|
||||
/* GP may be NULL, but VP and FP may not */
|
||||
if (!p)
|
||||
return NULL; /* GP is deactivated in linkage validation */
|
||||
if (!nv50_program_validate(nv50, gp))
|
||||
return;
|
||||
|
||||
if (!p->translated) {
|
||||
if (nv50_program_validate(p))
|
||||
nv50_gp_update_stateobj(nv50, p);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nv50->dirty & NV50_NEW_GEOMPROG_CB)
|
||||
nv50_program_validate_data(nv50, p);
|
||||
|
||||
if (!(nv50->dirty & NV50_NEW_GEOMPROG))
|
||||
return NULL;
|
||||
|
||||
nv50_program_validate_common(nv50, p);
|
||||
|
||||
so_ref(p->so, &so);
|
||||
return so;
|
||||
BEGIN_RING(chan, RING_3D(GP_REG_ALLOC_TEMP), 1);
|
||||
OUT_RING (chan, gp->max_gpr);
|
||||
BEGIN_RING(chan, RING_3D(GP_REG_ALLOC_RESULT), 1);
|
||||
OUT_RING (chan, gp->max_out);
|
||||
BEGIN_RING(chan, RING_3D(GP_OUTPUT_PRIMITIVE_TYPE), 1);
|
||||
OUT_RING (chan, gp->gp.prim_type);
|
||||
BEGIN_RING(chan, RING_3D(GP_VERTEX_OUTPUT_COUNT), 1);
|
||||
OUT_RING (chan, gp->gp.vert_count);
|
||||
BEGIN_RING(chan, RING_3D(GP_START_ID), 1);
|
||||
OUT_RING (chan, gp->code_base);
|
||||
}
|
||||
|
||||
/* XXX: this might not work correctly in all cases yet: we assume that
|
||||
* an FP generic input that is not written in the VP is gl_PointCoord.
|
||||
*/
|
||||
static uint32_t
|
||||
static void
|
||||
nv50_pntc_replace(struct nv50_context *nv50, uint32_t pntc[8], unsigned m)
|
||||
{
|
||||
struct nv50_program *vp = nv50->vertprog;
|
||||
struct nv50_program *fp = nv50->fragprog;
|
||||
unsigned i, c;
|
||||
|
||||
memset(pntc, 0, 8 * sizeof(uint32_t));
|
||||
|
||||
if (nv50->geomprog)
|
||||
vp = nv50->geomprog;
|
||||
|
||||
for (i = 0; i < fp->in_nr; i++) {
|
||||
unsigned j, n = util_bitcount(fp->in[i].mask);
|
||||
unsigned n = util_bitcount(fp->in[i].mask);
|
||||
|
||||
if (fp->in[i].sn != TGSI_SEMANTIC_GENERIC) {
|
||||
m += n;
|
||||
continue;
|
||||
}
|
||||
if (!(nv50->rast->pipe.sprite_coord_enable & (1 << fp->in[i].si))) {
|
||||
m += n;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < vp->out_nr; ++j)
|
||||
if (vp->out[j].sn == fp->in[i].sn && vp->out[j].si == fp->in[i].si)
|
||||
break;
|
||||
|
||||
if (j < vp->out_nr) {
|
||||
uint32_t en = nv50->rasterizer->pipe.sprite_coord_enable;
|
||||
|
||||
if (!(en & (1 << vp->out[j].si))) {
|
||||
m += n;
|
||||
continue;
|
||||
for (c = 0; c < 4; ++c) {
|
||||
if (fp->in[i].mask & (1 << c)) {
|
||||
pntc[m / 8] |= (c + 1) << ((m % 8) * 4);
|
||||
++m;
|
||||
}
|
||||
}
|
||||
|
||||
/* this is either PointCoord or replaced by sprite coords */
|
||||
for (c = 0; c < 4; c++) {
|
||||
if (!(fp->in[i].mask & (1 << c)))
|
||||
continue;
|
||||
pntc[m / 8] |= (c + 1) << ((m % 8) * 4);
|
||||
++m;
|
||||
}
|
||||
}
|
||||
if (nv50->rasterizer->pipe.sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT)
|
||||
return 0;
|
||||
return (1 << 4);
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_vec4_map(uint32_t *map32, int mid, uint32_t lin[4],
|
||||
nv50_vec4_map(uint8_t *map, int mid, uint32_t lin[4],
|
||||
struct nv50_varying *in, struct nv50_varying *out)
|
||||
{
|
||||
int c;
|
||||
uint8_t mv = out->mask, mf = in->mask, oid = out->hw;
|
||||
uint8_t *map = (uint8_t *)map32;
|
||||
|
||||
for (c = 0; c < 4; ++c) {
|
||||
if (mf & 1) {
|
||||
|
|
@ -465,140 +277,120 @@ nv50_vec4_map(uint32_t *map32, int mid, uint32_t lin[4],
|
|||
return mid;
|
||||
}
|
||||
|
||||
struct nouveau_stateobj *
|
||||
void
|
||||
nv50_fp_linkage_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nv50_program *vp;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_program *vp = nv50->gmtyprog ? nv50->gmtyprog : nv50->vertprog;
|
||||
struct nv50_program *fp = nv50->fragprog;
|
||||
struct nouveau_stateobj *so;
|
||||
struct nv50_varying dummy;
|
||||
int i, n, c, m;
|
||||
|
||||
uint32_t map[16], lin[4], pntc[8];
|
||||
|
||||
uint32_t primid = 0;
|
||||
uint32_t psiz = 0x000;
|
||||
uint32_t interp = fp->fp.interp;
|
||||
uint32_t colors = fp->fp.colors;
|
||||
uint32_t clip = 0x04;
|
||||
uint32_t psiz = 0x000;
|
||||
uint32_t primid = 0;
|
||||
uint32_t sysval = 0;
|
||||
uint32_t lin[4], pntc[8];
|
||||
uint8_t map[64];
|
||||
|
||||
if (nv50->geomprog) {
|
||||
vp = nv50->geomprog;
|
||||
memset(map, 0x80, sizeof(map));
|
||||
} else {
|
||||
vp = nv50->vertprog;
|
||||
memset(map, 0x40, sizeof(map));
|
||||
}
|
||||
memset(lin, 0, sizeof(lin));
|
||||
memset(lin, 0x00, sizeof(lin));
|
||||
|
||||
/* XXX: in buggy-endian mode, is the first element of map (u32)0x000000xx
|
||||
* or is it the first byte ?
|
||||
*/
|
||||
memset(map, nv50->gmtyprog ? 0x80 : 0x40, sizeof(map));
|
||||
|
||||
dummy.linear = 0;
|
||||
dummy.mask = 0xf; /* map all components of HPOS */
|
||||
dummy.linear = 0;
|
||||
m = nv50_vec4_map(map, 0, lin, &dummy, &vp->out[0]);
|
||||
|
||||
if (vp->vp.clpd < 0x40) {
|
||||
for (c = 0; c < vp->vp.clpd_nr; ++c) {
|
||||
map[m / 4] |= (vp->vp.clpd + c) << ((m % 4) * 8);
|
||||
++m;
|
||||
}
|
||||
clip |= vp->vp.clpd_nr << 8;
|
||||
}
|
||||
for (c = 0; c < vp->vp.clpd_nr; ++c)
|
||||
map[m++] |= vp->vp.clpd + c;
|
||||
|
||||
colors |= m << 8; /* adjust BFC0 id */
|
||||
|
||||
/* if light_twoside is active, it seems FFC0_ID == BFC0_ID is bad */
|
||||
if (nv50->rasterizer->pipe.light_twoside) {
|
||||
/* if light_twoside is active, FFC0_ID == BFC0_ID is invalid */
|
||||
if (nv50->rast->pipe.light_twoside) {
|
||||
for (i = 0; i < 2; ++i)
|
||||
m = nv50_vec4_map(map, m, lin,
|
||||
&fp->in[fp->vp.bfc[i]],
|
||||
&vp->out[vp->vp.bfc[i]]);
|
||||
&fp->in[fp->vp.bfc[i]], &vp->out[vp->vp.bfc[i]]);
|
||||
}
|
||||
|
||||
colors += m - 4; /* adjust FFC0 id */
|
||||
interp |= m << 8; /* set mid where 'normal' FP inputs start */
|
||||
interp |= m << 8; /* set map id where 'normal' FP inputs start */
|
||||
|
||||
dummy.mask = 0x0;
|
||||
for (i = 0; i < fp->in_nr; i++) {
|
||||
for (i = 0; i < fp->in_nr; ++i) {
|
||||
for (n = 0; n < vp->out_nr; ++n)
|
||||
if (vp->out[n].sn == fp->in[i].sn &&
|
||||
vp->out[n].si == fp->in[i].si)
|
||||
break;
|
||||
|
||||
m = nv50_vec4_map(map, m, lin,
|
||||
&fp->in[i], (n < vp->out_nr) ? &vp->out[n] : &dummy);
|
||||
}
|
||||
}
|
||||
|
||||
/* PrimitiveID either is replaced by the system value, or
|
||||
* written by the geometry shader into an output register
|
||||
*/
|
||||
if (fp->gp.primid < 0x40) {
|
||||
i = (m % 4) * 8;
|
||||
map[m / 4] = (map[m / 4] & ~(0xff << i)) | (vp->gp.primid << i);
|
||||
primid = m++;
|
||||
primid = m;
|
||||
map[m++] = vp->gp.primid;
|
||||
}
|
||||
|
||||
if (nv50->rasterizer->pipe.point_size_per_vertex) {
|
||||
i = (m % 4) * 8;
|
||||
map[m / 4] = (map[m / 4] & ~(0xff << i)) | (vp->vp.psiz << i);
|
||||
psiz = (m++ << 4) | 1;
|
||||
if (nv50->rast->pipe.point_size_per_vertex) {
|
||||
psiz = (m << 4) | 1;
|
||||
map[m++] = vp->vp.psiz;
|
||||
}
|
||||
|
||||
/* now fill the stateobj (at most 28 so_data) */
|
||||
so = so_new(10, 54, 0);
|
||||
|
||||
n = (m + 3) / 4;
|
||||
assert(m <= 64);
|
||||
if (vp->type == PIPE_SHADER_GEOMETRY) {
|
||||
so_method(so, tesla, NV50TCL_GP_RESULT_MAP_SIZE, 1);
|
||||
so_data (so, m);
|
||||
so_method(so, tesla, NV50TCL_GP_RESULT_MAP(0), n);
|
||||
so_datap (so, map, n);
|
||||
|
||||
if (unlikely(nv50->gmtyprog)) {
|
||||
BEGIN_RING(chan, RING_3D(GP_RESULT_MAP_SIZE), 1);
|
||||
OUT_RING (chan, m);
|
||||
BEGIN_RING(chan, RING_3D(GP_RESULT_MAP(0)), n);
|
||||
OUT_RINGp (chan, map, n);
|
||||
} else {
|
||||
so_method(so, tesla, NV50TCL_VP_GP_BUILTIN_ATTR_EN, 1);
|
||||
so_data (so, vp->vp.attrs[2]);
|
||||
BEGIN_RING(chan, RING_3D(VP_GP_BUILTIN_ATTR_EN), 1);
|
||||
OUT_RING (chan, vp->vp.attrs[2]);
|
||||
|
||||
so_method(so, tesla, NV50TCL_MAP_SEMANTIC_4, 1);
|
||||
so_data (so, primid);
|
||||
BEGIN_RING(chan, RING_3D(MAP_SEMANTIC_4), 1);
|
||||
OUT_RING (chan, primid);
|
||||
|
||||
so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
|
||||
so_data (so, m);
|
||||
so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), n);
|
||||
so_datap (so, map, n);
|
||||
BEGIN_RING(chan, RING_3D(VP_RESULT_MAP_SIZE), 1);
|
||||
OUT_RING (chan, m);
|
||||
BEGIN_RING(chan, RING_3D(VP_RESULT_MAP(0)), n);
|
||||
OUT_RINGp (chan, map, n);
|
||||
}
|
||||
|
||||
so_method(so, tesla, NV50TCL_MAP_SEMANTIC_0, 4);
|
||||
so_data (so, colors);
|
||||
so_data (so, clip);
|
||||
so_data (so, sysval);
|
||||
so_data (so, psiz);
|
||||
BEGIN_RING(chan, RING_3D(MAP_SEMANTIC_0), 4);
|
||||
OUT_RING (chan, colors);
|
||||
OUT_RING (chan, (vp->vp.clpd_nr << 8) | 4);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, psiz);
|
||||
|
||||
so_method(so, tesla, NV50TCL_FP_INTERPOLANT_CTRL, 1);
|
||||
so_data (so, interp);
|
||||
BEGIN_RING(chan, RING_3D(FP_INTERPOLANT_CTRL), 1);
|
||||
OUT_RING (chan, interp);
|
||||
|
||||
so_method(so, tesla, NV50TCL_NOPERSPECTIVE_BITMAP(0), 4);
|
||||
so_datap (so, lin, 4);
|
||||
BEGIN_RING(chan, RING_3D(NOPERSPECTIVE_BITMAP(0)), 4);
|
||||
OUT_RINGp (chan, lin, 4);
|
||||
|
||||
if (nv50->rasterizer->pipe.point_quad_rasterization) {
|
||||
so_method(so, tesla, NV50TCL_POINT_SPRITE_CTRL, 1);
|
||||
so_data (so,
|
||||
nv50_pntc_replace(nv50, pntc, (interp >> 8) & 0xff));
|
||||
if (nv50->rast->pipe.point_quad_rasterization) {
|
||||
nv50_pntc_replace(nv50, pntc, (interp >> 8) & 0xff);
|
||||
|
||||
so_method(so, tesla, NV50TCL_POINT_COORD_REPLACE_MAP(0), 8);
|
||||
so_datap (so, pntc, 8);
|
||||
BEGIN_RING(chan, RING_3D(POINT_SPRITE_CTRL), 1);
|
||||
OUT_RING (chan, (nv50->rast->pipe.sprite_coord_mode ==
|
||||
PIPE_SPRITE_COORD_LOWER_LEFT) ? 0 : 0x10);
|
||||
BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE_MAP(0)), 8);
|
||||
OUT_RINGp (chan, pntc, 8);
|
||||
}
|
||||
|
||||
so_method(so, tesla, NV50TCL_GP_ENABLE, 1);
|
||||
so_data (so, (vp->type == PIPE_SHADER_GEOMETRY) ? 1 : 0);
|
||||
|
||||
return so;
|
||||
BEGIN_RING(chan, RING_3D(GP_ENABLE), 1);
|
||||
OUT_RING (chan, nv50->gmtyprog ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_vp_gp_mapping(uint32_t *map32, int m,
|
||||
nv50_vp_gp_mapping(uint8_t *map, int m,
|
||||
struct nv50_program *vp, struct nv50_program *gp)
|
||||
{
|
||||
uint8_t *map = (uint8_t *)map32;
|
||||
int i, j, c;
|
||||
|
||||
for (i = 0; i < gp->in_nr; ++i) {
|
||||
|
|
@ -625,34 +417,29 @@ nv50_vp_gp_mapping(uint32_t *map32, int m,
|
|||
return m;
|
||||
}
|
||||
|
||||
struct nouveau_stateobj *
|
||||
void
|
||||
nv50_gp_linkage_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nv50_program *vp = nv50->vertprog;
|
||||
struct nv50_program *gp = nv50->geomprog;
|
||||
uint32_t map[16];
|
||||
struct nv50_program *gp = nv50->gmtyprog;
|
||||
int m = 0;
|
||||
int n;
|
||||
uint8_t map[64];
|
||||
|
||||
if (!gp)
|
||||
return NULL;
|
||||
return;
|
||||
memset(map, 0, sizeof(map));
|
||||
|
||||
m = nv50_vp_gp_mapping(map, m, vp, gp);
|
||||
|
||||
so = so_new(3, 24 - 3, 0);
|
||||
n = (m + 3) / 4;
|
||||
|
||||
so_method(so, tesla, NV50TCL_VP_GP_BUILTIN_ATTR_EN, 1);
|
||||
so_data (so, vp->vp.attrs[2] | gp->vp.attrs[2]);
|
||||
BEGIN_RING(chan, RING_3D(VP_GP_BUILTIN_ATTR_EN), 1);
|
||||
OUT_RING (chan, vp->vp.attrs[2] | gp->vp.attrs[2]);
|
||||
|
||||
assert(m <= 32);
|
||||
so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
|
||||
so_data (so, m);
|
||||
|
||||
m = (m + 3) / 4;
|
||||
so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), m);
|
||||
so_datap (so, map, m);
|
||||
|
||||
return so;
|
||||
BEGIN_RING(chan, RING_3D(VP_RESULT_MAP_SIZE), 1);
|
||||
OUT_RING (chan, m);
|
||||
BEGIN_RING(chan, RING_3D(VP_RESULT_MAP(0)), n);
|
||||
OUT_RINGp (chan, map, n);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,449 +1,286 @@
|
|||
/*
|
||||
* Copyright 2008 Ben Skeggs
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "util/u_format.h"
|
||||
|
||||
#include "nv50_context.h"
|
||||
#include "nv50_resource.h"
|
||||
#include "nouveau/nouveau_stateobj.h"
|
||||
#include "os/os_time.h"
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_fb(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_fb(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(32, 79, 18);
|
||||
struct pipe_framebuffer_state *fb = &nv50->framebuffer;
|
||||
unsigned i, w = 0, h = 0, gw = 0;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct pipe_framebuffer_state *fb = &nv50->framebuffer;
|
||||
unsigned i;
|
||||
|
||||
/* Set nr of active RTs and select RT for each colour output.
|
||||
* FP result 0 always goes to RT[0], bits 4 - 6 are ignored.
|
||||
* Ambiguous assignment results in no rendering (no DATA_ERROR).
|
||||
*/
|
||||
so_method(so, tesla, NV50TCL_RT_CONTROL, 1);
|
||||
so_data (so, fb->nr_cbufs |
|
||||
(0 << 4) | (1 << 7) | (2 << 10) | (3 << 13) |
|
||||
(4 << 16) | (5 << 19) | (6 << 22) | (7 << 25));
|
||||
nv50_bufctx_reset(nv50, NV50_BUFCTX_FRAME);
|
||||
|
||||
for (i = 0; i < fb->nr_cbufs; i++) {
|
||||
struct pipe_resource *pt = fb->cbufs[i]->texture;
|
||||
struct nouveau_bo *bo = nv50_miptree(pt)->base.bo;
|
||||
BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
|
||||
OUT_RING (chan, (076543210 << 4) | fb->nr_cbufs);
|
||||
BEGIN_RING(chan, RING_3D(SCREEN_SCISSOR_HORIZ), 2);
|
||||
OUT_RING (chan, fb->width << 16);
|
||||
OUT_RING (chan, fb->height << 16);
|
||||
|
||||
if (!gw) {
|
||||
w = fb->cbufs[i]->width;
|
||||
h = fb->cbufs[i]->height;
|
||||
gw = 1;
|
||||
} else {
|
||||
assert(w == fb->cbufs[i]->width);
|
||||
assert(h == fb->cbufs[i]->height);
|
||||
}
|
||||
MARK_RING(chan, 9 * fb->nr_cbufs, 2 * fb->nr_cbufs);
|
||||
|
||||
assert(nv50_format_table[fb->cbufs[i]->format].rt);
|
||||
for (i = 0; i < fb->nr_cbufs; ++i) {
|
||||
struct nv50_miptree *mt = nv50_miptree(fb->cbufs[i]->texture);
|
||||
struct nv50_surface *sf = nv50_surface(fb->cbufs[i]);
|
||||
struct nouveau_bo *bo = mt->base.bo;
|
||||
uint32_t offset = sf->offset;
|
||||
|
||||
so_method(so, tesla, NV50TCL_RT_HORIZ(i), 2);
|
||||
so_data (so, fb->cbufs[i]->width);
|
||||
so_data (so, fb->cbufs[i]->height);
|
||||
BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(i)), 5);
|
||||
OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
|
||||
OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
|
||||
OUT_RING (chan, nv50_format_table[sf->base.format].rt);
|
||||
OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
|
||||
OUT_RING (chan, mt->layer_stride >> 2);
|
||||
BEGIN_RING(chan, RING_3D(RT_HORIZ(i)), 2);
|
||||
OUT_RING (chan, sf->width);
|
||||
OUT_RING (chan, sf->height);
|
||||
BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1);
|
||||
OUT_RING (chan, sf->depth);
|
||||
|
||||
so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5);
|
||||
so_reloc (so, bo, ((struct nv50_surface *)fb->cbufs[i])->offset, NOUVEAU_BO_VRAM |
|
||||
NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0);
|
||||
so_reloc (so, bo, ((struct nv50_surface *)fb->cbufs[i])->offset, NOUVEAU_BO_VRAM |
|
||||
NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0);
|
||||
so_data (so, nv50_format_table[fb->cbufs[i]->format].rt);
|
||||
so_data (so, nv50_miptree(pt)->
|
||||
level[fb->cbufs[i]->u.tex.level].tile_mode << 4);
|
||||
so_data(so, 0x00000000);
|
||||
nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
|
||||
}
|
||||
|
||||
so_method(so, tesla, NV50TCL_RT_ARRAY_MODE, 1);
|
||||
so_data (so, 1);
|
||||
}
|
||||
if (fb->zsbuf) {
|
||||
struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
|
||||
struct nv50_surface *sf = nv50_surface(fb->zsbuf);
|
||||
struct nouveau_bo *bo = mt->base.bo;
|
||||
int unk = mt->base.base.target == PIPE_TEXTURE_2D;
|
||||
uint32_t offset = sf->offset;
|
||||
|
||||
if (fb->zsbuf) {
|
||||
struct pipe_resource *pt = fb->zsbuf->texture;
|
||||
struct nouveau_bo *bo = nv50_miptree(pt)->base.bo;
|
||||
MARK_RING (chan, 12, 2);
|
||||
BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
|
||||
OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
|
||||
OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
|
||||
OUT_RING (chan, nv50_format_table[fb->zsbuf->format].rt);
|
||||
OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
|
||||
OUT_RING (chan, mt->layer_stride >> 2);
|
||||
BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
|
||||
OUT_RING (chan, sf->width);
|
||||
OUT_RING (chan, sf->height);
|
||||
OUT_RING (chan, (unk << 16) | sf->depth);
|
||||
|
||||
if (!gw) {
|
||||
w = fb->zsbuf->width;
|
||||
h = fb->zsbuf->height;
|
||||
gw = 1;
|
||||
} else {
|
||||
assert(w == fb->zsbuf->width);
|
||||
assert(h == fb->zsbuf->height);
|
||||
}
|
||||
nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
|
||||
} else {
|
||||
BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
|
||||
assert(nv50_format_table[fb->zsbuf->format].rt);
|
||||
|
||||
so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
|
||||
so_reloc (so, bo, ((struct nv50_surface *)(fb->zsbuf))->offset, NOUVEAU_BO_VRAM |
|
||||
NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0);
|
||||
so_reloc (so, bo, ((struct nv50_surface *)(fb->zsbuf))->offset, NOUVEAU_BO_VRAM |
|
||||
NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0);
|
||||
so_data (so, nv50_format_table[fb->zsbuf->format].rt);
|
||||
so_data (so, nv50_miptree(pt)->
|
||||
level[fb->zsbuf->u.tex.level].tile_mode << 4);
|
||||
so_data (so, 0x00000000);
|
||||
|
||||
so_method(so, tesla, NV50TCL_ZETA_ENABLE, 1);
|
||||
so_data (so, 1);
|
||||
so_method(so, tesla, NV50TCL_ZETA_HORIZ, 3);
|
||||
so_data (so, fb->zsbuf->width);
|
||||
so_data (so, fb->zsbuf->height);
|
||||
so_data (so, 0x00010001);
|
||||
} else {
|
||||
so_method(so, tesla, NV50TCL_ZETA_ENABLE, 1);
|
||||
so_data (so, 0);
|
||||
}
|
||||
|
||||
so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ(0), 2);
|
||||
so_data (so, w << 16);
|
||||
so_data (so, h << 16);
|
||||
/* set window lower left corner */
|
||||
so_method(so, tesla, NV50TCL_WINDOW_OFFSET_X, 2);
|
||||
so_data (so, 0);
|
||||
so_data (so, 0);
|
||||
/* set screen scissor rectangle */
|
||||
so_method(so, tesla, NV50TCL_SCREEN_SCISSOR_HORIZ, 2);
|
||||
so_data (so, w << 16);
|
||||
so_data (so, h << 16);
|
||||
|
||||
return so;
|
||||
BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
|
||||
OUT_RING (chan, fb->width << 16);
|
||||
OUT_RING (chan, fb->height << 16);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_validate_samplers(struct nv50_context *nv50, struct nouveau_stateobj *so,
|
||||
unsigned p)
|
||||
nv50_validate_blend_colour(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
unsigned i, j, dw = nv50->sampler_nr[p] * 8;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
|
||||
if (!dw)
|
||||
return;
|
||||
nv50_so_init_sifc(nv50, so, nv50->screen->tsc, NOUVEAU_BO_VRAM,
|
||||
p * (32 * 8 * 4), dw * 4);
|
||||
|
||||
so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), dw);
|
||||
|
||||
for (i = 0; i < nv50->sampler_nr[p]; ++i) {
|
||||
if (nv50->sampler[p][i])
|
||||
so_datap(so, nv50->sampler[p][i]->tsc, 8);
|
||||
else {
|
||||
for (j = 0; j < 8; ++j) /* you get punished */
|
||||
so_data(so, 0); /* ... for leaving holes */
|
||||
}
|
||||
}
|
||||
BEGIN_RING(chan, RING_3D(BLEND_COLOR(0)), 4);
|
||||
OUT_RINGf (chan, nv50->blend_colour.color[0]);
|
||||
OUT_RINGf (chan, nv50->blend_colour.color[1]);
|
||||
OUT_RINGf (chan, nv50->blend_colour.color[2]);
|
||||
OUT_RINGf (chan, nv50->blend_colour.color[3]);
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_blend(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_stencil_ref(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_stateobj *so = NULL;
|
||||
so_ref(nv50->blend->so, &so);
|
||||
return so;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
|
||||
BEGIN_RING(chan, RING_3D(STENCIL_FRONT_FUNC_REF), 1);
|
||||
OUT_RING (chan, nv50->stencil_ref.ref_value[0]);
|
||||
BEGIN_RING(chan, RING_3D(STENCIL_BACK_FUNC_REF), 1);
|
||||
OUT_RING (chan, nv50->stencil_ref.ref_value[1]);
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_zsa(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_stipple(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_stateobj *so = NULL;
|
||||
so_ref(nv50->zsa->so, &so);
|
||||
return so;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
unsigned i;
|
||||
|
||||
BEGIN_RING(chan, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
|
||||
for (i = 0; i < 32; ++i)
|
||||
OUT_RING(chan, util_bswap32(nv50->stipple.stipple[i]));
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_rast(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_scissor(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_stateobj *so = NULL;
|
||||
so_ref(nv50->rasterizer->so, &so);
|
||||
return so;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct pipe_scissor_state *s = &nv50->scissor;
|
||||
#ifdef NV50_SCISSORS_CLIPPING
|
||||
struct pipe_viewport_state *vp = &nv50->viewport;
|
||||
int minx, maxx, miny, maxy;
|
||||
|
||||
if (!(nv50->dirty &
|
||||
(NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) &&
|
||||
nv50->state.scissor == nv50->rast->pipe.scissor)
|
||||
return;
|
||||
nv50->state.scissor = nv50->rast->pipe.scissor;
|
||||
|
||||
if (nv50->state.scissor) {
|
||||
minx = s->minx;
|
||||
maxx = s->maxx;
|
||||
miny = s->miny;
|
||||
maxy = s->maxy;
|
||||
} else {
|
||||
minx = 0;
|
||||
maxx = nv50->framebuffer.width;
|
||||
miny = 0;
|
||||
maxy = nv50->framebuffer.height;
|
||||
}
|
||||
|
||||
minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
|
||||
maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
|
||||
miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
|
||||
maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
|
||||
|
||||
BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
|
||||
OUT_RING (chan, (maxx << 16) | minx);
|
||||
OUT_RING (chan, (maxy << 16) | miny);
|
||||
#else
|
||||
BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
|
||||
OUT_RING (chan, (s->maxx << 16) | s->minx);
|
||||
OUT_RING (chan, (s->maxy << 16) | s->miny);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_blend_colour(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_viewport(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(1, 4, 0);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
float zmin, zmax;
|
||||
|
||||
so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4);
|
||||
so_data (so, fui(nv50->blend_colour.color[0]));
|
||||
so_data (so, fui(nv50->blend_colour.color[1]));
|
||||
so_data (so, fui(nv50->blend_colour.color[2]));
|
||||
so_data (so, fui(nv50->blend_colour.color[3]));
|
||||
return so;
|
||||
BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
|
||||
OUT_RINGf (chan, nv50->viewport.translate[0]);
|
||||
OUT_RINGf (chan, nv50->viewport.translate[1]);
|
||||
OUT_RINGf (chan, nv50->viewport.translate[2]);
|
||||
BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3);
|
||||
OUT_RINGf (chan, nv50->viewport.scale[0]);
|
||||
OUT_RINGf (chan, nv50->viewport.scale[1]);
|
||||
OUT_RINGf (chan, nv50->viewport.scale[2]);
|
||||
|
||||
zmin = nv50->viewport.translate[2] - fabsf(nv50->viewport.scale[2]);
|
||||
zmax = nv50->viewport.translate[2] + fabsf(nv50->viewport.scale[2]);
|
||||
|
||||
#ifdef NV50_SCISSORS_CLIPPING
|
||||
BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
|
||||
OUT_RINGf (chan, zmin);
|
||||
OUT_RINGf (chan, zmax);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_stencil_ref(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_clip(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(2, 2, 0);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
uint32_t clip;
|
||||
|
||||
so_method(so, tesla, NV50TCL_STENCIL_FRONT_FUNC_REF, 1);
|
||||
so_data (so, nv50->stencil_ref.ref_value[0]);
|
||||
so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 1);
|
||||
so_data (so, nv50->stencil_ref.ref_value[1]);
|
||||
return so;
|
||||
clip = nv50->clip.depth_clamp ? 0x0018 : 0x0000;
|
||||
#ifndef NV50_SCISSORS_CLIPPING
|
||||
clip |= 0x1080;
|
||||
#endif
|
||||
|
||||
BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1);
|
||||
OUT_RING (chan, clip);
|
||||
|
||||
if (nv50->clip.nr) {
|
||||
BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
|
||||
OUT_RING (chan, (0 << 8) | NV50_CB_AUX);
|
||||
BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nv50->clip.nr * 4);
|
||||
OUT_RINGp (chan, &nv50->clip.ucp[0][0], nv50->clip.nr * 4);
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1);
|
||||
OUT_RING (chan, (1 << nv50->clip.nr) - 1);
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_stipple(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_blend(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(1, 32, 0);
|
||||
int i;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
|
||||
so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32);
|
||||
for (i = 0; i < 32; i++)
|
||||
so_data(so, util_bswap32(nv50->stipple.stipple[i]));
|
||||
return so;
|
||||
WAIT_RING(chan, nv50->blend->size);
|
||||
OUT_RINGp(chan, nv50->blend->state, nv50->blend->size);
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_scissor(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_zsa(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct pipe_scissor_state *s = &nv50->scissor;
|
||||
struct nouveau_stateobj *so;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
|
||||
so = so_new(1, 2, 0);
|
||||
so_method(so, tesla, NV50TCL_SCISSOR_HORIZ(0), 2);
|
||||
so_data (so, (s->maxx << 16) | s->minx);
|
||||
so_data (so, (s->maxy << 16) | s->miny);
|
||||
return so;
|
||||
WAIT_RING(chan, nv50->zsa->size);
|
||||
OUT_RINGp(chan, nv50->zsa->state, nv50->zsa->size);
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_viewport(struct nv50_context *nv50)
|
||||
static void
|
||||
nv50_validate_rasterizer(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(3, 7, 0);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
|
||||
so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE_X(0), 3);
|
||||
so_data (so, fui(nv50->viewport.translate[0]));
|
||||
so_data (so, fui(nv50->viewport.translate[1]));
|
||||
so_data (so, fui(nv50->viewport.translate[2]));
|
||||
so_method(so, tesla, NV50TCL_VIEWPORT_SCALE_X(0), 3);
|
||||
so_data (so, fui(nv50->viewport.scale[0]));
|
||||
so_data (so, fui(nv50->viewport.scale[1]));
|
||||
so_data (so, fui(nv50->viewport.scale[2]));
|
||||
|
||||
/* no idea what 0f90 does */
|
||||
so_method(so, tesla, 0x0f90, 1);
|
||||
so_data (so, 0);
|
||||
|
||||
return so;
|
||||
WAIT_RING(chan, nv50->rast->size);
|
||||
OUT_RINGp(chan, nv50->rast->state, nv50->rast->size);
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_sampler(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so;
|
||||
unsigned nr = 0, i;
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
nr += nv50->sampler_nr[i];
|
||||
|
||||
so = so_new(1 + 5 * 3, 1 + 19 * 3 + nr * 8, 3 * 2);
|
||||
|
||||
nv50_validate_samplers(nv50, so, 0); /* VP */
|
||||
nv50_validate_samplers(nv50, so, 2); /* FP */
|
||||
|
||||
so_method(so, tesla, 0x1334, 1); /* flush TSC */
|
||||
so_data (so, 0);
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_vtxbuf(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_stateobj *so = NULL;
|
||||
so_ref(nv50->state.vtxbuf, &so);
|
||||
return so;
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_vtxattr(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_stateobj *so = NULL;
|
||||
so_ref(nv50->state.vtxattr, &so);
|
||||
return so;
|
||||
}
|
||||
|
||||
static struct nouveau_stateobj *
|
||||
validate_clip(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_stateobj *so = so_new(1, 1, 0);
|
||||
uint32_t vvcc;
|
||||
|
||||
/* 0x0000 = remove whole primitive only (xyz)
|
||||
* 0x1018 = remove whole primitive only (xy), clamp z
|
||||
* 0x1080 = clip primitive (xyz)
|
||||
* 0x1098 = clip primitive (xy), clamp z
|
||||
*/
|
||||
vvcc = nv50->clip.depth_clamp ? 0x1098 : 0x1080;
|
||||
|
||||
so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1);
|
||||
so_data (so, vvcc);
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
struct state_validate {
|
||||
struct nouveau_stateobj *(*func)(struct nv50_context *nv50);
|
||||
unsigned states;
|
||||
static struct state_validate {
|
||||
void (*func)(struct nv50_context *);
|
||||
uint32_t states;
|
||||
} validate_list[] = {
|
||||
{ validate_fb , NV50_NEW_FRAMEBUFFER },
|
||||
{ validate_blend , NV50_NEW_BLEND },
|
||||
{ validate_zsa , NV50_NEW_ZSA },
|
||||
{ nv50_vertprog_validate , NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB },
|
||||
{ nv50_fragprog_validate , NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB },
|
||||
{ nv50_geomprog_validate , NV50_NEW_GEOMPROG | NV50_NEW_GEOMPROG_CB },
|
||||
{ nv50_fp_linkage_validate, NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG |
|
||||
NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER },
|
||||
{ nv50_gp_linkage_validate, NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG },
|
||||
{ validate_rast , NV50_NEW_RASTERIZER },
|
||||
{ validate_blend_colour , NV50_NEW_BLEND_COLOUR },
|
||||
{ validate_stencil_ref , NV50_NEW_STENCIL_REF },
|
||||
{ validate_stipple , NV50_NEW_STIPPLE },
|
||||
{ validate_scissor , NV50_NEW_SCISSOR },
|
||||
{ validate_viewport , NV50_NEW_VIEWPORT },
|
||||
{ validate_sampler , NV50_NEW_SAMPLER },
|
||||
{ nv50_tex_validate , NV50_NEW_TEXTURE | NV50_NEW_SAMPLER },
|
||||
{ nv50_vbo_validate , NV50_NEW_ARRAYS },
|
||||
{ validate_vtxbuf , NV50_NEW_ARRAYS },
|
||||
{ validate_vtxattr , NV50_NEW_ARRAYS },
|
||||
{ validate_clip , NV50_NEW_CLIP },
|
||||
{ NULL , 0 }
|
||||
{ nv50_validate_fb, NV50_NEW_FRAMEBUFFER },
|
||||
{ nv50_validate_blend, NV50_NEW_BLEND },
|
||||
{ nv50_validate_zsa, NV50_NEW_ZSA },
|
||||
{ nv50_validate_rasterizer, NV50_NEW_RASTERIZER },
|
||||
{ nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR },
|
||||
{ nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF },
|
||||
{ nv50_validate_stipple, NV50_NEW_STIPPLE },
|
||||
#ifdef NV50_SCISSORS_CLIPPING
|
||||
{ nv50_validate_scissor, NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT |
|
||||
NV50_NEW_RASTERIZER |
|
||||
NV50_NEW_FRAMEBUFFER },
|
||||
#else
|
||||
{ nv50_validate_scissor, NV50_NEW_SCISSOR },
|
||||
#endif
|
||||
{ nv50_validate_viewport, NV50_NEW_VIEWPORT },
|
||||
{ nv50_validate_clip, NV50_NEW_CLIP },
|
||||
{ nv50_vertprog_validate, NV50_NEW_VERTPROG },
|
||||
{ nv50_gmtyprog_validate, NV50_NEW_GMTYPROG },
|
||||
{ nv50_fragprog_validate, NV50_NEW_FRAGPROG },
|
||||
{ nv50_fp_linkage_validate, NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
|
||||
NV50_NEW_GMTYPROG },
|
||||
{ nv50_gp_linkage_validate, NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
|
||||
{ nv50_constbufs_validate, NV50_NEW_CONSTBUF },
|
||||
{ nv50_validate_textures, NV50_NEW_TEXTURES },
|
||||
{ nv50_validate_samplers, NV50_NEW_SAMPLERS },
|
||||
{ nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS }
|
||||
};
|
||||
#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
|
||||
|
||||
boolean
|
||||
nv50_state_validate(struct nv50_context *nv50, unsigned wait_dwords)
|
||||
nv50_state_validate(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
unsigned nr_relocs = 128, nr_dwords = wait_dwords + 128 + 4;
|
||||
int ret, i;
|
||||
unsigned i;
|
||||
#if 0
|
||||
if (nv50->screen->cur_ctx != nv50) /* FIXME: not everything is valid */
|
||||
nv50->dirty = 0xffffffff;
|
||||
#endif
|
||||
nv50->screen->cur_ctx = nv50;
|
||||
|
||||
for (i = 0; i < validate_list_len; i++) {
|
||||
struct state_validate *validate = &validate_list[i];
|
||||
struct nouveau_stateobj *so;
|
||||
if (nv50->dirty) {
|
||||
for (i = 0; i < validate_list_len; ++i) {
|
||||
struct state_validate *validate = &validate_list[i];
|
||||
|
||||
if (!(nv50->dirty & validate->states))
|
||||
continue;
|
||||
if (nv50->dirty & validate->states)
|
||||
validate->func(nv50);
|
||||
}
|
||||
nv50->dirty = 0;
|
||||
}
|
||||
|
||||
so = validate->func(nv50);
|
||||
if (!so)
|
||||
continue;
|
||||
nv50_bufctx_emit_relocs(nv50);
|
||||
|
||||
nr_dwords += (so->total + so->cur);
|
||||
nr_relocs += so->cur_reloc;
|
||||
|
||||
so_ref(so, &nv50->state.hw[i]);
|
||||
so_ref(NULL, &so);
|
||||
nv50->state.hw_dirty |= (1 << i);
|
||||
}
|
||||
nv50->dirty = 0;
|
||||
|
||||
if (nv50->screen->cur_ctx != nv50) {
|
||||
for (i = 0; i < validate_list_len; i++) {
|
||||
if (!nv50->state.hw[i] ||
|
||||
(nv50->state.hw_dirty & (1 << i)))
|
||||
continue;
|
||||
|
||||
nr_dwords += (nv50->state.hw[i]->total +
|
||||
nv50->state.hw[i]->cur);
|
||||
nr_relocs += nv50->state.hw[i]->cur_reloc;
|
||||
nv50->state.hw_dirty |= (1 << i);
|
||||
}
|
||||
|
||||
nv50->screen->cur_ctx = nv50;
|
||||
}
|
||||
|
||||
ret = MARK_RING(chan, nr_dwords, nr_relocs);
|
||||
if (ret) {
|
||||
debug_printf("MARK_RING(%d, %d) failed: %d\n",
|
||||
nr_dwords, nr_relocs, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (nv50->state.hw_dirty) {
|
||||
i = ffs(nv50->state.hw_dirty) - 1;
|
||||
nv50->state.hw_dirty &= ~(1 << i);
|
||||
|
||||
so_emit(chan, nv50->state.hw[i]);
|
||||
}
|
||||
|
||||
/* Yes, really, we need to do this. If a buffer that is referenced
|
||||
* on the hardware isn't part of changed state above, without doing
|
||||
* this the kernel is given no clue that the buffer is being used
|
||||
* still. This can cause all sorts of fun issues.
|
||||
*/
|
||||
nv50_tex_relocs(nv50);
|
||||
so_emit_reloc_markers(chan, nv50->state.hw[0]); /* fb */
|
||||
so_emit_reloc_markers(chan, nv50->state.hw[3]); /* vp */
|
||||
so_emit_reloc_markers(chan, nv50->state.hw[4]); /* fp */
|
||||
so_emit_reloc_markers(chan, nv50->state.hw[17]); /* vb */
|
||||
nv50_screen_relocs(nv50->screen);
|
||||
|
||||
/* No idea.. */
|
||||
BEGIN_RING(chan, tesla, 0x142c, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, tesla, 0x142c, 1);
|
||||
OUT_RING (chan, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void nv50_so_init_sifc(struct nv50_context *nv50,
|
||||
struct nouveau_stateobj *so,
|
||||
struct nouveau_bo *bo, unsigned reloc,
|
||||
unsigned offset, unsigned size)
|
||||
{
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
|
||||
reloc |= NOUVEAU_BO_WR;
|
||||
|
||||
so_method(so, eng2d, NV50_2D_DST_FORMAT, 2);
|
||||
so_data (so, NV50_2D_DST_FORMAT_R8_UNORM);
|
||||
so_data (so, 1);
|
||||
so_method(so, eng2d, NV50_2D_DST_PITCH, 5);
|
||||
so_data (so, 262144);
|
||||
so_data (so, 65536);
|
||||
so_data (so, 1);
|
||||
so_reloc (so, bo, offset, reloc | NOUVEAU_BO_HIGH, 0, 0);
|
||||
so_reloc (so, bo, offset, reloc | NOUVEAU_BO_LOW, 0, 0);
|
||||
so_method(so, eng2d, NV50_2D_SIFC_BITMAP_ENABLE, 2);
|
||||
so_data (so, 0);
|
||||
so_data (so, NV50_2D_SIFC_FORMAT_R8_UNORM);
|
||||
so_method(so, eng2d, NV50_2D_SIFC_WIDTH, 10);
|
||||
so_data (so, size);
|
||||
so_data (so, 1);
|
||||
so_data (so, 0);
|
||||
so_data (so, 1);
|
||||
so_data (so, 0);
|
||||
so_data (so, 1);
|
||||
so_data (so, 0);
|
||||
so_data (so, 0);
|
||||
so_data (so, 0);
|
||||
so_data (so, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
72
src/gallium/drivers/nv50/nv50_stateobj.h
Normal file
72
src/gallium/drivers/nv50/nv50_stateobj.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
#ifndef __NV50_STATEOBJ_H__
|
||||
#define __NV50_STATEOBJ_H__
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#define NV50_SCISSORS_CLIPPING
|
||||
|
||||
#define SB_BEGIN_3D(so, m, s) \
|
||||
(so)->state[(so)->size++] = \
|
||||
((s) << 18) | (NV50_SUBCH_3D << 13) | NV50_3D_##m
|
||||
|
||||
#define SB_DATA(so, u) (so)->state[(so)->size++] = (u)
|
||||
|
||||
struct nv50_blend_stateobj {
|
||||
struct pipe_blend_state pipe;
|
||||
int size;
|
||||
uint32_t state[29];
|
||||
};
|
||||
|
||||
struct nv50_tsc_entry {
|
||||
int id;
|
||||
uint32_t tsc[8];
|
||||
};
|
||||
|
||||
static INLINE struct nv50_tsc_entry *
|
||||
nv50_tsc_entry(void *hwcso)
|
||||
{
|
||||
return (struct nv50_tsc_entry *)hwcso;
|
||||
}
|
||||
|
||||
struct nv50_tic_entry {
|
||||
struct pipe_sampler_view pipe;
|
||||
int id;
|
||||
uint32_t tic[8];
|
||||
};
|
||||
|
||||
static INLINE struct nv50_tic_entry *
|
||||
nv50_tic_entry(struct pipe_sampler_view *view)
|
||||
{
|
||||
return (struct nv50_tic_entry *)view;
|
||||
}
|
||||
|
||||
struct nv50_rasterizer_stateobj {
|
||||
struct pipe_rasterizer_state pipe;
|
||||
int size;
|
||||
uint32_t state[40];
|
||||
};
|
||||
|
||||
struct nv50_zsa_stateobj {
|
||||
struct pipe_depth_stencil_alpha_state pipe;
|
||||
int size;
|
||||
uint32_t state[29];
|
||||
};
|
||||
|
||||
struct nv50_vertex_element {
|
||||
struct pipe_vertex_element pipe;
|
||||
uint32_t state;
|
||||
};
|
||||
|
||||
struct nv50_vertex_stateobj {
|
||||
struct translate *translate;
|
||||
unsigned num_elements;
|
||||
uint32_t instance_elts;
|
||||
uint32_t instance_bufs;
|
||||
boolean need_conversion;
|
||||
unsigned vertex_size;
|
||||
unsigned packet_vertex_limit;
|
||||
struct nv50_vertex_element element[1];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -20,306 +20,360 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NOUVEAU_PUSH_H__
|
||||
#include <stdint.h>
|
||||
#include "nouveau/nv04_pushbuf.h"
|
||||
#include "nv50_context.h"
|
||||
#include "nv50_resource.h"
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_pack_color.h"
|
||||
|
||||
#include "util/u_format.h"
|
||||
|
||||
#include "nv50_context.h"
|
||||
#include "nv50_resource.h"
|
||||
|
||||
#include "nv50_defs.xml.h"
|
||||
|
||||
/* return TRUE for formats that can be converted among each other by NV50_2D */
|
||||
static INLINE boolean
|
||||
nv50_2d_format_faithful(enum pipe_format format)
|
||||
{
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_B8G8R8A8_UNORM:
|
||||
case PIPE_FORMAT_B8G8R8X8_UNORM:
|
||||
case PIPE_FORMAT_B8G8R8A8_SRGB:
|
||||
case PIPE_FORMAT_B8G8R8X8_SRGB:
|
||||
case PIPE_FORMAT_B5G6R5_UNORM:
|
||||
case PIPE_FORMAT_B5G5R5A1_UNORM:
|
||||
case PIPE_FORMAT_B10G10R10A2_UNORM:
|
||||
case PIPE_FORMAT_R8_UNORM:
|
||||
case PIPE_FORMAT_R32G32B32A32_FLOAT:
|
||||
case PIPE_FORMAT_R32G32B32_FLOAT:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_B8G8R8A8_UNORM:
|
||||
case PIPE_FORMAT_B8G8R8X8_UNORM:
|
||||
case PIPE_FORMAT_B8G8R8A8_SRGB:
|
||||
case PIPE_FORMAT_B8G8R8X8_SRGB:
|
||||
case PIPE_FORMAT_B5G6R5_UNORM:
|
||||
case PIPE_FORMAT_B5G5R5A1_UNORM:
|
||||
case PIPE_FORMAT_B10G10R10A2_UNORM:
|
||||
case PIPE_FORMAT_R8_UNORM:
|
||||
case PIPE_FORMAT_R32G32B32A32_FLOAT:
|
||||
case PIPE_FORMAT_R32G32B32_FLOAT:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE uint8_t
|
||||
nv50_2d_format(enum pipe_format format)
|
||||
{
|
||||
uint8_t id = nv50_format_table[format].rt;
|
||||
uint8_t id = nv50_format_table[format].rt;
|
||||
|
||||
/* Hardware values for color formats range from 0xc0 to 0xff,
|
||||
* but the 2D engine doesn't support all of them.
|
||||
*/
|
||||
if ((id >= 0xc0) && (0xff0843e080608409ULL & (1ULL << (id - 0xc0))))
|
||||
return id;
|
||||
/* Hardware values for color formats range from 0xc0 to 0xff,
|
||||
* but the 2D engine doesn't support all of them.
|
||||
*/
|
||||
if ((id >= 0xc0) && (0xff0843e080608409ULL & (1ULL << (id - 0xc0))))
|
||||
return id;
|
||||
|
||||
switch (util_format_get_blocksize(format)) {
|
||||
case 1:
|
||||
return NV50_2D_DST_FORMAT_R8_UNORM;
|
||||
case 2:
|
||||
return NV50_2D_DST_FORMAT_R16_UNORM;
|
||||
case 4:
|
||||
return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
switch (util_format_get_blocksize(format)) {
|
||||
case 1:
|
||||
return NV50_SURFACE_FORMAT_R8_UNORM;
|
||||
case 2:
|
||||
return NV50_SURFACE_FORMAT_R16_UNORM;
|
||||
case 4:
|
||||
return NV50_SURFACE_FORMAT_A8R8G8B8_UNORM;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
|
||||
nv50_2d_texture_set(struct nouveau_channel *chan, int dst,
|
||||
struct nv50_miptree *mt, unsigned level, unsigned layer)
|
||||
{
|
||||
struct nv50_miptree *mt = nv50_miptree(ps->texture);
|
||||
struct nouveau_channel *chan = screen->eng2d->channel;
|
||||
struct nouveau_grobj *eng2d = screen->eng2d;
|
||||
struct nouveau_bo *bo = nv50_miptree(ps->texture)->base.bo;
|
||||
int format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
|
||||
int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);
|
||||
struct nouveau_bo *bo = mt->base.bo;
|
||||
uint32_t width, height, depth;
|
||||
uint32_t format;
|
||||
uint32_t mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
|
||||
uint32_t flags = mt->base.domain | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);
|
||||
uint32_t offset = mt->level[level].offset;
|
||||
|
||||
format = nv50_2d_format(ps->format);
|
||||
if (!format) {
|
||||
NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
|
||||
util_format_name(ps->format));
|
||||
return 1;
|
||||
}
|
||||
format = nv50_2d_format(mt->base.base.format);
|
||||
if (!format) {
|
||||
NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
|
||||
util_format_name(mt->base.base.format));
|
||||
return 1;
|
||||
}
|
||||
|
||||
width = u_minify(mt->base.base.width0, level);
|
||||
height = u_minify(mt->base.base.height0, level);
|
||||
|
||||
offset = mt->level[level].offset;
|
||||
if (!mt->layout_3d) {
|
||||
offset += mt->layer_stride * layer;
|
||||
depth = 1;
|
||||
layer = 0;
|
||||
} else {
|
||||
depth = u_minify(mt->base.base.depth0, level);
|
||||
}
|
||||
|
||||
if (!(bo->tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK)) {
|
||||
BEGIN_RING(chan, RING_2D_(mthd), 2);
|
||||
OUT_RING (chan, format);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_2D_(mthd + 0x14), 5);
|
||||
OUT_RING (chan, mt->level[level].pitch);
|
||||
OUT_RING (chan, width);
|
||||
OUT_RING (chan, height);
|
||||
OUT_RELOCh(chan, bo, offset, flags);
|
||||
OUT_RELOCl(chan, bo, offset, flags);
|
||||
} else {
|
||||
BEGIN_RING(chan, RING_2D_(mthd), 5);
|
||||
OUT_RING (chan, format);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, mt->level[level].tile_mode << 4);
|
||||
OUT_RING (chan, depth);
|
||||
OUT_RING (chan, layer);
|
||||
BEGIN_RING(chan, RING_2D_(mthd + 0x18), 4);
|
||||
OUT_RING (chan, width);
|
||||
OUT_RING (chan, height);
|
||||
OUT_RELOCh(chan, bo, offset, flags);
|
||||
OUT_RELOCl(chan, bo, offset, flags);
|
||||
}
|
||||
|
||||
if (!nouveau_bo_tile_layout(bo)) {
|
||||
BEGIN_RING(chan, eng2d, mthd, 2);
|
||||
OUT_RING (chan, format);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, eng2d, mthd + 0x14, 5);
|
||||
OUT_RING (chan, mt->level[ps->u.tex.level].pitch);
|
||||
OUT_RING (chan, ps->width);
|
||||
OUT_RING (chan, ps->height);
|
||||
OUT_RELOCh(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
|
||||
OUT_RELOCl(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
|
||||
} else {
|
||||
BEGIN_RING(chan, eng2d, mthd, 5);
|
||||
OUT_RING (chan, format);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, mt->level[ps->u.tex.level].tile_mode << 4);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
|
||||
OUT_RING (chan, ps->width);
|
||||
OUT_RING (chan, ps->height);
|
||||
OUT_RELOCh(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
|
||||
OUT_RELOCl(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (dst) {
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, surf->width);
|
||||
OUT_RING (chan, surf->height);
|
||||
}
|
||||
if (dst) {
|
||||
BEGIN_RING(chan, RING_2D_(NV50_2D_CLIP_X), 4);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, width);
|
||||
OUT_RING (chan, height);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
|
||||
int dx, int dy, struct pipe_surface *src, int sx, int sy,
|
||||
int w, int h)
|
||||
static int
|
||||
nv50_2d_texture_do_copy(struct nouveau_channel *chan,
|
||||
struct nv50_miptree *dst, unsigned dst_level,
|
||||
unsigned dx, unsigned dy, unsigned dz,
|
||||
struct nv50_miptree *src, unsigned src_level,
|
||||
unsigned sx, unsigned sy, unsigned sz,
|
||||
unsigned w, unsigned h)
|
||||
{
|
||||
struct nouveau_channel *chan = screen->eng2d->channel;
|
||||
struct nouveau_grobj *eng2d = screen->eng2d;
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
ret = MARK_RING(chan, 2*16 + 32, 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = MARK_RING(chan, 2 * 16 + 32, 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nv50_surface_set(screen, dst, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = nv50_2d_texture_set(chan, 1, dst, dst_level, dz);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nv50_surface_set(screen, src, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = nv50_2d_texture_set(chan, 0, src, src_level, sz);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
BEGIN_RING(chan, eng2d, 0x088c, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4);
|
||||
OUT_RING (chan, dx);
|
||||
OUT_RING (chan, dy);
|
||||
OUT_RING (chan, w);
|
||||
OUT_RING (chan, h);
|
||||
BEGIN_RING(chan, eng2d, 0x08c0, 4);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, eng2d, 0x08d0, 4);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, sx);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, sy);
|
||||
/* 0/1 = CENTER/CORNER, 10/00 = POINT/BILINEAR */
|
||||
BEGIN_RING(chan, RING_2D(BLIT_CONTROL), 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, RING_2D(BLIT_DST_X), 4);
|
||||
OUT_RING (chan, dx);
|
||||
OUT_RING (chan, dy);
|
||||
OUT_RING (chan, w);
|
||||
OUT_RING (chan, h);
|
||||
BEGIN_RING(chan, RING_2D(BLIT_DU_DX_FRACT), 4);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_2D(BLIT_SRC_X_FRACT), 4);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, sx);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, sy);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_surface_copy(struct pipe_context *pipe,
|
||||
struct pipe_resource *dest, unsigned dst_level,
|
||||
unsigned destx, unsigned desty, unsigned destz,
|
||||
struct pipe_resource *src, unsigned src_level,
|
||||
const struct pipe_box *src_box)
|
||||
nv50_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)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nv50_screen *screen = nv50->screen;
|
||||
struct pipe_surface *ps_dst, *ps_src, surf_tmpl;
|
||||
struct nv50_screen *screen = nv50_context(pipe)->screen;
|
||||
int ret;
|
||||
unsigned dst_layer = dstz, src_layer = src_box->z;
|
||||
|
||||
assert((src->format == dst->format) ||
|
||||
(nv50_2d_format_faithful(src->format) &&
|
||||
nv50_2d_format_faithful(dst->format)));
|
||||
|
||||
assert((src->format == dest->format) ||
|
||||
(nv50_2d_format_faithful(src->format) &&
|
||||
nv50_2d_format_faithful(dest->format)));
|
||||
assert(src_box->depth == 1);
|
||||
|
||||
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
|
||||
surf_tmpl.format = src->format;
|
||||
surf_tmpl.usage = 0; /* no bind flag - not a surface */
|
||||
surf_tmpl.u.tex.level = src_level;
|
||||
surf_tmpl.u.tex.first_layer = src_box->z;
|
||||
surf_tmpl.u.tex.last_layer = src_box->z;
|
||||
/* XXX really need surfaces here? */
|
||||
ps_src = nv50_miptree_surface_new(pipe, src, &surf_tmpl);
|
||||
surf_tmpl.format = dest->format;
|
||||
surf_tmpl.usage = 0; /* no bind flag - not a surface */
|
||||
surf_tmpl.u.tex.level = dst_level;
|
||||
surf_tmpl.u.tex.first_layer = destz;
|
||||
surf_tmpl.u.tex.last_layer = destz;
|
||||
ps_dst = nv50_miptree_surface_new(pipe, dest, &surf_tmpl);
|
||||
|
||||
nv50_surface_do_copy(screen, ps_dst, destx, desty, ps_src, src_box->x,
|
||||
src_box->y, src_box->width, src_box->height);
|
||||
|
||||
nv50_miptree_surface_del(pipe, ps_src);
|
||||
nv50_miptree_surface_del(pipe, ps_dst);
|
||||
for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
|
||||
ret = nv50_2d_texture_do_copy(screen->base.channel,
|
||||
nv50_miptree(dst), dst_level,
|
||||
dstx, dsty, dst_layer,
|
||||
nv50_miptree(src), src_level,
|
||||
src_box->x, src_box->y, src_layer,
|
||||
src_box->width, src_box->height);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_clear_render_target(struct pipe_context *pipe,
|
||||
struct pipe_surface *dst,
|
||||
const float *rgba,
|
||||
unsigned dstx, unsigned dsty,
|
||||
unsigned width, unsigned height)
|
||||
struct pipe_surface *dst,
|
||||
const float *rgba,
|
||||
unsigned dstx, unsigned dsty,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nv50_screen *screen = nv50->screen;
|
||||
struct nouveau_channel *chan = screen->base.channel;
|
||||
struct nouveau_grobj *tesla = screen->tesla;
|
||||
struct nv50_miptree *mt = nv50_miptree(dst->texture);
|
||||
struct nouveau_bo *bo = mt->base.bo;
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nv50_screen *screen = nv50->screen;
|
||||
struct nouveau_channel *chan = screen->base.channel;
|
||||
struct nv50_miptree *mt = nv50_miptree(dst->texture);
|
||||
struct nv50_surface *sf = nv50_surface(dst);
|
||||
struct nouveau_bo *bo = mt->base.bo;
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_COLOR(0), 4);
|
||||
OUT_RINGf (chan, rgba[0]);
|
||||
OUT_RINGf (chan, rgba[1]);
|
||||
OUT_RINGf (chan, rgba[2]);
|
||||
OUT_RINGf (chan, rgba[3]);
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4);
|
||||
OUT_RINGf (chan, rgba[0]);
|
||||
OUT_RINGf (chan, rgba[1]);
|
||||
OUT_RINGf (chan, rgba[2]);
|
||||
OUT_RINGf (chan, rgba[3]);
|
||||
|
||||
if (MARK_RING(chan, 18, 2))
|
||||
return;
|
||||
if (MARK_RING(chan, 18, 2))
|
||||
return;
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_RT_CONTROL, 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5);
|
||||
OUT_RELOCh(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, nv50_format_table[dst->format].rt);
|
||||
OUT_RING (chan, mt->level[dst->u.tex.level].tile_mode << 4);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_RT_HORIZ(0), 2);
|
||||
OUT_RING (chan, dst->width);
|
||||
OUT_RING (chan, dst->height);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_RT_ARRAY_MODE, 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(0)), 5);
|
||||
OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, nv50_format_table[dst->format].rt);
|
||||
OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, RING_3D(RT_HORIZ(0)), 2);
|
||||
OUT_RING (chan, sf->width);
|
||||
OUT_RING (chan, sf->height);
|
||||
BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1);
|
||||
OUT_RING (chan, 1);
|
||||
|
||||
/* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
|
||||
/* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VIEWPORT_HORIZ(0), 2);
|
||||
OUT_RING (chan, (width << 16) | dstx);
|
||||
OUT_RING (chan, (height << 16) | dsty);
|
||||
BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
|
||||
OUT_RING (chan, (width << 16) | dstx);
|
||||
OUT_RING (chan, (height << 16) | dsty);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
|
||||
OUT_RING (chan, 0x3c);
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
|
||||
OUT_RING (chan, 0x3c);
|
||||
|
||||
nv50->dirty |= NV50_NEW_FRAMEBUFFER;
|
||||
nv50->dirty |= NV50_NEW_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_clear_depth_stencil(struct pipe_context *pipe,
|
||||
struct pipe_surface *dst,
|
||||
unsigned clear_flags,
|
||||
double depth,
|
||||
unsigned stencil,
|
||||
unsigned dstx, unsigned dsty,
|
||||
unsigned width, unsigned height)
|
||||
struct pipe_surface *dst,
|
||||
unsigned clear_flags,
|
||||
double depth,
|
||||
unsigned stencil,
|
||||
unsigned dstx, unsigned dsty,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nv50_screen *screen = nv50->screen;
|
||||
struct nouveau_channel *chan = screen->base.channel;
|
||||
struct nouveau_grobj *tesla = screen->tesla;
|
||||
struct nv50_miptree *mt = nv50_miptree(dst->texture);
|
||||
struct nouveau_bo *bo = mt->base.bo;
|
||||
uint32_t mode = 0;
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nv50_screen *screen = nv50->screen;
|
||||
struct nouveau_channel *chan = screen->base.channel;
|
||||
struct nv50_miptree *mt = nv50_miptree(dst->texture);
|
||||
struct nv50_surface *sf = nv50_surface(dst);
|
||||
struct nouveau_bo *bo = mt->base.bo;
|
||||
uint32_t mode = 0;
|
||||
|
||||
if (clear_flags & PIPE_CLEAR_DEPTH) {
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_DEPTH, 1);
|
||||
OUT_RINGf (chan, depth);
|
||||
mode |= NV50TCL_CLEAR_BUFFERS_Z;
|
||||
}
|
||||
if (clear_flags & PIPE_CLEAR_DEPTH) {
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1);
|
||||
OUT_RINGf (chan, depth);
|
||||
mode |= NV50_3D_CLEAR_BUFFERS_Z;
|
||||
}
|
||||
|
||||
if (clear_flags & PIPE_CLEAR_STENCIL) {
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_STENCIL, 1);
|
||||
OUT_RING (chan, stencil & 0xff);
|
||||
mode |= NV50TCL_CLEAR_BUFFERS_S;
|
||||
}
|
||||
if (clear_flags & PIPE_CLEAR_STENCIL) {
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1);
|
||||
OUT_RING (chan, stencil & 0xff);
|
||||
mode |= NV50_3D_CLEAR_BUFFERS_S;
|
||||
}
|
||||
|
||||
if (MARK_RING(chan, 17, 2))
|
||||
return;
|
||||
if (MARK_RING(chan, 17, 2))
|
||||
return;
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
|
||||
OUT_RELOCh(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, nv50_format_table[dst->format].rt);
|
||||
OUT_RING (chan, mt->level[dst->u.tex.level].tile_mode << 4);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_ZETA_ENABLE, 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_ZETA_HORIZ, 3);
|
||||
OUT_RING (chan, dst->width);
|
||||
OUT_RING (chan, dst->height);
|
||||
OUT_RING (chan, (1 << 16) | 1);
|
||||
BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
|
||||
OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, nv50_format_table[dst->format].rt);
|
||||
OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
|
||||
OUT_RING (chan, sf->width);
|
||||
OUT_RING (chan, sf->height);
|
||||
OUT_RING (chan, (1 << 16) | 1);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VIEWPORT_HORIZ(0), 2);
|
||||
OUT_RING (chan, (width << 16) | dstx);
|
||||
OUT_RING (chan, (height << 16) | dsty);
|
||||
BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
|
||||
OUT_RING (chan, (width << 16) | dstx);
|
||||
OUT_RING (chan, (height << 16) | dsty);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
|
||||
OUT_RING (chan, mode);
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
|
||||
OUT_RING (chan, mode);
|
||||
|
||||
nv50->dirty |= NV50_NEW_FRAMEBUFFER;
|
||||
nv50->dirty |= NV50_NEW_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_clear(struct pipe_context *pipe, unsigned buffers,
|
||||
const float *rgba, double depth, unsigned stencil)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct pipe_framebuffer_state *fb = &nv50->framebuffer;
|
||||
unsigned i;
|
||||
const unsigned dirty = nv50->dirty;
|
||||
uint32_t mode = 0;
|
||||
|
||||
/* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
|
||||
nv50->dirty &= NV50_NEW_FRAMEBUFFER;
|
||||
if (!nv50_state_validate(nv50))
|
||||
return;
|
||||
|
||||
if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4);
|
||||
OUT_RINGf (chan, rgba[0]);
|
||||
OUT_RINGf (chan, rgba[1]);
|
||||
OUT_RINGf (chan, rgba[2]);
|
||||
OUT_RINGf (chan, rgba[3]);
|
||||
mode =
|
||||
NV50_3D_CLEAR_BUFFERS_R | NV50_3D_CLEAR_BUFFERS_G |
|
||||
NV50_3D_CLEAR_BUFFERS_B | NV50_3D_CLEAR_BUFFERS_A;
|
||||
}
|
||||
|
||||
if (buffers & PIPE_CLEAR_DEPTH) {
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1);
|
||||
OUT_RING (chan, fui(depth));
|
||||
mode |= NV50_3D_CLEAR_BUFFERS_Z;
|
||||
}
|
||||
|
||||
if (buffers & PIPE_CLEAR_STENCIL) {
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1);
|
||||
OUT_RING (chan, stencil & 0xff);
|
||||
mode |= NV50_3D_CLEAR_BUFFERS_S;
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
|
||||
OUT_RING (chan, mode);
|
||||
|
||||
for (i = 1; i < fb->nr_cbufs; i++) {
|
||||
BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
|
||||
OUT_RING (chan, (i << 6) | 0x3c);
|
||||
}
|
||||
|
||||
nv50->dirty = dirty & ~NV50_NEW_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_init_surface_functions(struct nv50_context *nv50)
|
||||
{
|
||||
nv50->pipe.resource_copy_region = nv50_surface_copy;
|
||||
nv50->pipe.clear_render_target = nv50_clear_render_target;
|
||||
nv50->pipe.clear_depth_stencil = nv50_clear_depth_stencil;
|
||||
nv50->pipe.resource_copy_region = nv50_resource_copy_region;
|
||||
nv50->pipe.clear_render_target = nv50_clear_render_target;
|
||||
nv50->pipe.clear_depth_stencil = nv50_clear_depth_stencil;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,217 +21,273 @@
|
|||
*/
|
||||
|
||||
#include "nv50_context.h"
|
||||
#include "nv50_texture.h"
|
||||
#include "nv50_resource.h"
|
||||
|
||||
#include "nouveau/nouveau_stateobj.h"
|
||||
#include "nouveau/nouveau_reloc.h"
|
||||
#include "nv50_texture.xml.h"
|
||||
#include "nv50_defs.xml.h"
|
||||
|
||||
#include "util/u_format.h"
|
||||
|
||||
static INLINE uint32_t
|
||||
nv50_tic_swizzle(uint32_t tc, unsigned swz)
|
||||
{
|
||||
switch (swz) {
|
||||
case PIPE_SWIZZLE_RED:
|
||||
return (tc & NV50TIC_0_0_MAPR_MASK) >> NV50TIC_0_0_MAPR_SHIFT;
|
||||
case PIPE_SWIZZLE_GREEN:
|
||||
return (tc & NV50TIC_0_0_MAPG_MASK) >> NV50TIC_0_0_MAPG_SHIFT;
|
||||
case PIPE_SWIZZLE_BLUE:
|
||||
return (tc & NV50TIC_0_0_MAPB_MASK) >> NV50TIC_0_0_MAPB_SHIFT;
|
||||
case PIPE_SWIZZLE_ALPHA:
|
||||
return (tc & NV50TIC_0_0_MAPA_MASK) >> NV50TIC_0_0_MAPA_SHIFT;
|
||||
case PIPE_SWIZZLE_ONE:
|
||||
return 7;
|
||||
case PIPE_SWIZZLE_ZERO:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
switch (swz) {
|
||||
case PIPE_SWIZZLE_RED:
|
||||
return (tc & NV50_TIC_0_MAPR__MASK) >> NV50_TIC_0_MAPR__SHIFT;
|
||||
case PIPE_SWIZZLE_GREEN:
|
||||
return (tc & NV50_TIC_0_MAPG__MASK) >> NV50_TIC_0_MAPG__SHIFT;
|
||||
case PIPE_SWIZZLE_BLUE:
|
||||
return (tc & NV50_TIC_0_MAPB__MASK) >> NV50_TIC_0_MAPB__SHIFT;
|
||||
case PIPE_SWIZZLE_ALPHA:
|
||||
return (tc & NV50_TIC_0_MAPA__MASK) >> NV50_TIC_0_MAPA__SHIFT;
|
||||
case PIPE_SWIZZLE_ONE:
|
||||
return NV50_TIC_MAP_ONE;
|
||||
case PIPE_SWIZZLE_ZERO:
|
||||
default:
|
||||
return NV50_TIC_MAP_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
boolean
|
||||
nv50_tex_construct(struct nv50_sampler_view *view)
|
||||
struct pipe_sampler_view *
|
||||
nv50_create_sampler_view(struct pipe_context *pipe,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_sampler_view *templ)
|
||||
{
|
||||
const struct util_format_description *desc;
|
||||
struct nv50_miptree *mt = nv50_miptree(view->pipe.texture);
|
||||
uint32_t swz[4], *tic = view->tic;
|
||||
const struct util_format_description *desc;
|
||||
uint32_t *tic;
|
||||
uint32_t swz[4];
|
||||
uint32_t depth;
|
||||
struct nv50_tic_entry *view;
|
||||
struct nv50_miptree *mt = nv50_miptree(texture);
|
||||
|
||||
tic[0] = nv50_format_table[view->pipe.format].tic;
|
||||
view = MALLOC_STRUCT(nv50_tic_entry);
|
||||
if (!view)
|
||||
return NULL;
|
||||
|
||||
swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r);
|
||||
swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g);
|
||||
swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b);
|
||||
swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a);
|
||||
view->tic[0] = (tic[0] & ~NV50TIC_0_0_SWIZZLE_MASK) |
|
||||
(swz[0] << NV50TIC_0_0_MAPR_SHIFT) |
|
||||
(swz[1] << NV50TIC_0_0_MAPG_SHIFT) |
|
||||
(swz[2] << NV50TIC_0_0_MAPB_SHIFT) |
|
||||
(swz[3] << NV50TIC_0_0_MAPA_SHIFT);
|
||||
view->pipe = *templ;
|
||||
view->pipe.reference.count = 1;
|
||||
view->pipe.texture = NULL;
|
||||
view->pipe.context = pipe;
|
||||
|
||||
tic[2] = 0x50001000;
|
||||
tic[2] |= ((mt->base.bo->tile_mode & 0x0f) << 22) |
|
||||
((mt->base.bo->tile_mode & 0xf0) << 21);
|
||||
view->id = -1;
|
||||
|
||||
desc = util_format_description(mt->base.base.format);
|
||||
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
|
||||
tic[2] |= NV50TIC_0_2_COLORSPACE_SRGB;
|
||||
pipe_resource_reference(&view->pipe.texture, texture);
|
||||
|
||||
switch (mt->base.base.target) {
|
||||
case PIPE_TEXTURE_1D:
|
||||
tic[2] |= NV50TIC_0_2_TARGET_1D;
|
||||
break;
|
||||
case PIPE_TEXTURE_2D:
|
||||
tic[2] |= NV50TIC_0_2_TARGET_2D;
|
||||
break;
|
||||
case PIPE_TEXTURE_RECT:
|
||||
tic[2] |= NV50TIC_0_2_TARGET_RECT;
|
||||
break;
|
||||
case PIPE_TEXTURE_3D:
|
||||
tic[2] |= NV50TIC_0_2_TARGET_3D;
|
||||
break;
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
tic[2] |= NV50TIC_0_2_TARGET_CUBE;
|
||||
break;
|
||||
default:
|
||||
NOUVEAU_ERR("invalid texture target: %d\n",
|
||||
mt->base.base.target);
|
||||
return FALSE;
|
||||
}
|
||||
tic = &view->tic[0];
|
||||
|
||||
tic[3] = 0x00300000;
|
||||
desc = util_format_description(mt->base.base.format);
|
||||
|
||||
tic[4] = (1 << 31) | mt->base.base.width0;
|
||||
tic[5] = (mt->base.base.last_level << 28) |
|
||||
(mt->base.base.depth0 << 16) | mt->base.base.height0;
|
||||
/* TIC[0] */
|
||||
|
||||
tic[6] = 0x03000000;
|
||||
tic[0] = nv50_format_table[view->pipe.format].tic;
|
||||
|
||||
tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
|
||||
swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r);
|
||||
swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g);
|
||||
swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b);
|
||||
swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a);
|
||||
tic[0] = (tic[0] & ~NV50_TIC_0_SWIZZLE__MASK) |
|
||||
(swz[0] << NV50_TIC_0_MAPR__SHIFT) |
|
||||
(swz[1] << NV50_TIC_0_MAPG__SHIFT) |
|
||||
(swz[2] << NV50_TIC_0_MAPB__SHIFT) |
|
||||
(swz[3] << NV50_TIC_0_MAPA__SHIFT);
|
||||
|
||||
return TRUE;
|
||||
/* tic[1] = mt->base.bo->offset; */
|
||||
tic[2] = /* mt->base.bo->offset >> 32 */ 0;
|
||||
|
||||
tic[2] |= 0x10001000 | /* NV50_TIC_2_NO_BORDER */ 0x40000000;
|
||||
|
||||
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
|
||||
tic[2] |= NV50_TIC_2_COLORSPACE_SRGB;
|
||||
|
||||
if (mt->base.base.target != PIPE_TEXTURE_RECT)
|
||||
tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;
|
||||
|
||||
tic[2] |=
|
||||
((mt->base.bo->tile_mode & 0x0f) << (22 - 0)) |
|
||||
((mt->base.bo->tile_mode & 0xf0) << (25 - 4));
|
||||
|
||||
depth = MAX2(mt->base.base.array_size, mt->base.base.depth0);
|
||||
|
||||
switch (mt->base.base.target) {
|
||||
case PIPE_TEXTURE_1D:
|
||||
tic[2] |= NV50_TIC_2_TARGET_1D;
|
||||
break;
|
||||
case PIPE_TEXTURE_2D:
|
||||
tic[2] |= NV50_TIC_2_TARGET_2D;
|
||||
break;
|
||||
case PIPE_TEXTURE_RECT:
|
||||
tic[2] |= NV50_TIC_2_TARGET_RECT;
|
||||
break;
|
||||
case PIPE_TEXTURE_3D:
|
||||
tic[2] |= NV50_TIC_2_TARGET_3D;
|
||||
break;
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
depth /= 6;
|
||||
if (depth > 1)
|
||||
tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
|
||||
else
|
||||
tic[2] |= NV50_TIC_2_TARGET_CUBE;
|
||||
break;
|
||||
case PIPE_TEXTURE_1D_ARRAY:
|
||||
tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
|
||||
break;
|
||||
case PIPE_TEXTURE_2D_ARRAY:
|
||||
tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
|
||||
break;
|
||||
case PIPE_BUFFER:
|
||||
tic[2] |= NV50_TIC_2_TARGET_BUFFER | /* NV50_TIC_2_LINEAR */ (1 << 18);
|
||||
default:
|
||||
NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mt->base.base.target == PIPE_BUFFER)
|
||||
tic[3] = mt->base.base.width0;
|
||||
else
|
||||
tic[3] = 0x00300000;
|
||||
|
||||
tic[4] = (1 << 31) | mt->base.base.width0;
|
||||
|
||||
tic[5] = mt->base.base.height0 & 0xffff;
|
||||
tic[5] |= depth << 16;
|
||||
tic[5] |= mt->base.base.last_level << 28;
|
||||
|
||||
tic[6] = 0x03000000;
|
||||
|
||||
tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
|
||||
|
||||
return &view->pipe;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_validate_textures(struct nv50_context *nv50, struct nouveau_stateobj *so,
|
||||
unsigned p)
|
||||
static boolean
|
||||
nv50_validate_tic(struct nv50_context *nv50, int s)
|
||||
{
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
unsigned unit, j;
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_bo *txc = nv50->screen->txc;
|
||||
unsigned i;
|
||||
boolean need_flush = FALSE;
|
||||
|
||||
const unsigned rll = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW;
|
||||
const unsigned rlh = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH
|
||||
| NOUVEAU_BO_OR;
|
||||
for (i = 0; i < nv50->num_textures[s]; ++i) {
|
||||
struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
|
||||
struct nv50_resource *res;
|
||||
|
||||
nv50_so_init_sifc(nv50, so, nv50->screen->tic, NOUVEAU_BO_VRAM,
|
||||
p * (32 * 8 * 4), nv50->sampler_view_nr[p] * 8 * 4);
|
||||
if (!tic) {
|
||||
BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1);
|
||||
OUT_RING (chan, (i << 1) | 0);
|
||||
continue;
|
||||
}
|
||||
res = &nv50_miptree(tic->pipe.texture)->base;
|
||||
|
||||
for (unit = 0; unit < nv50->sampler_view_nr[p]; ++unit) {
|
||||
struct nv50_sampler_view *view =
|
||||
nv50_sampler_view(nv50->sampler_views[p][unit]);
|
||||
if (tic->id < 0) {
|
||||
tic->id = nv50_screen_tic_alloc(nv50->screen, tic);
|
||||
|
||||
so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), 8);
|
||||
if (view) {
|
||||
uint32_t tic2 = view->tic[2];
|
||||
struct nv50_miptree *mt =
|
||||
nv50_miptree(view->pipe.texture);
|
||||
MARK_RING (chan, 24 + 8, 4);
|
||||
BEGIN_RING(chan, RING_2D(DST_FORMAT), 2);
|
||||
OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_2D(DST_PITCH), 5);
|
||||
OUT_RING (chan, 262144);
|
||||
OUT_RING (chan, 65536);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RELOCh(chan, txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
|
||||
BEGIN_RING(chan, RING_2D(SIFC_BITMAP_ENABLE), 2);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM);
|
||||
BEGIN_RING(chan, RING_2D(SIFC_WIDTH), 10);
|
||||
OUT_RING (chan, 32);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, tic->id * 32);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING_NI(chan, RING_2D(SIFC_DATA), 8);
|
||||
OUT_RING (chan, tic->tic[0]);
|
||||
OUT_RELOCl(chan, res->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
|
||||
OUT_RELOC (chan, res->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, tic->tic[2], tic->tic[2]);
|
||||
OUT_RINGp (chan, &tic->tic[3], 5);
|
||||
|
||||
tic2 &= ~NV50TIC_0_2_NORMALIZED_COORDS;
|
||||
if (nv50->sampler[p][unit]->normalized)
|
||||
tic2 |= NV50TIC_0_2_NORMALIZED_COORDS;
|
||||
view->tic[2] = tic2;
|
||||
need_flush = TRUE;
|
||||
}
|
||||
nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
|
||||
|
||||
so_data (so, view->tic[0]);
|
||||
so_reloc (so, mt->base.bo, 0, rll, 0, 0);
|
||||
so_reloc (so, mt->base.bo, 0, rlh, tic2, tic2);
|
||||
so_datap (so, &view->tic[3], 5);
|
||||
nv50_bufctx_add_resident(nv50, NV50_BUFCTX_TEXTURES, res,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
|
||||
|
||||
/* Set TEX insn $t src binding $unit in program type p
|
||||
* to TIC, TSC entry (32 * p + unit), mark valid (1).
|
||||
*/
|
||||
so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
|
||||
so_data (so, ((32 * p + unit) << 9) | (unit << 1) | 1);
|
||||
} else {
|
||||
for (j = 0; j < 8; ++j)
|
||||
so_data(so, 0);
|
||||
so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
|
||||
so_data (so, (unit << 1) | 0);
|
||||
}
|
||||
}
|
||||
BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1);
|
||||
OUT_RING (chan, (tic->id << 9) | (i << 1) | 1);
|
||||
}
|
||||
for (; i < nv50->state.num_textures[s]; ++i) {
|
||||
BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1);
|
||||
OUT_RING (chan, (i << 1) | 0);
|
||||
}
|
||||
nv50->state.num_textures[s] = nv50->num_textures[s];
|
||||
|
||||
for (; unit < nv50->state.sampler_view_nr[p]; unit++) {
|
||||
/* Make other bindings invalid. */
|
||||
so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
|
||||
so_data (so, (unit << 1) | 0);
|
||||
}
|
||||
|
||||
nv50->state.sampler_view_nr[p] = nv50->sampler_view_nr[p];
|
||||
return TRUE;
|
||||
return need_flush;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_emit_texture_relocs(struct nv50_context *nv50, int prog)
|
||||
void nv50_validate_textures(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_bo *tic = nv50->screen->tic;
|
||||
int unit;
|
||||
boolean need_flush;
|
||||
|
||||
for (unit = 0; unit < nv50->sampler_view_nr[prog]; unit++) {
|
||||
struct nv50_sampler_view *view;
|
||||
struct nv50_miptree *mt;
|
||||
const unsigned base = ((prog * 32) + unit) * 32;
|
||||
need_flush = nv50_validate_tic(nv50, 0);
|
||||
need_flush |= nv50_validate_tic(nv50, 2);
|
||||
|
||||
view = nv50_sampler_view(nv50->sampler_views[prog][unit]);
|
||||
if (!view)
|
||||
continue;
|
||||
mt = nv50_miptree(view->pipe.texture);
|
||||
|
||||
nouveau_reloc_emit(chan, tic, base + 4, NULL, mt->base.bo, 0, 0,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_LOW, 0, 0);
|
||||
nouveau_reloc_emit(chan, tic, base + 8, NULL, mt->base.bo, 0, 0,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
|
||||
NOUVEAU_BO_HIGH, view->tic[2], view->tic[2]);
|
||||
}
|
||||
if (need_flush) {
|
||||
BEGIN_RING(nv50->screen->base.channel, RING_3D(TIC_FLUSH), 1);
|
||||
OUT_RING (nv50->screen->base.channel, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv50_tex_relocs(struct nv50_context *nv50)
|
||||
static boolean
|
||||
nv50_validate_tsc(struct nv50_context *nv50, int s)
|
||||
{
|
||||
nv50_emit_texture_relocs(nv50, 2); /* FP */
|
||||
nv50_emit_texture_relocs(nv50, 0); /* VP */
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
unsigned i;
|
||||
boolean need_flush = FALSE;
|
||||
|
||||
for (i = 0; i < nv50->num_samplers[s]; ++i) {
|
||||
struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]);
|
||||
|
||||
if (!tsc) {
|
||||
BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1);
|
||||
OUT_RING (chan, (i << 4) | 0);
|
||||
continue;
|
||||
}
|
||||
if (tsc->id < 0) {
|
||||
tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc);
|
||||
|
||||
nv50_sifc_linear_u8(nv50, nv50->screen->txc, NOUVEAU_BO_VRAM,
|
||||
65536 + tsc->id * 32, 32, tsc->tsc);
|
||||
need_flush = TRUE;
|
||||
}
|
||||
nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32);
|
||||
|
||||
BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1);
|
||||
OUT_RING (chan, (tsc->id << 12) | (i << 4) | 1);
|
||||
}
|
||||
for (; i < nv50->state.num_samplers[s]; ++i) {
|
||||
BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1);
|
||||
OUT_RING (chan, (i << 4) | 0);
|
||||
}
|
||||
nv50->state.num_samplers[s] = nv50->num_samplers[s];
|
||||
|
||||
return need_flush;
|
||||
}
|
||||
|
||||
struct nouveau_stateobj *
|
||||
nv50_tex_validate(struct nv50_context *nv50)
|
||||
void nv50_validate_samplers(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_stateobj *so;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
unsigned p, m = 0, d = 0, r = 0;
|
||||
boolean need_flush;
|
||||
|
||||
for (p = 0; p < 3; ++p) {
|
||||
unsigned nr = MAX2(nv50->sampler_view_nr[p],
|
||||
nv50->state.sampler_view_nr[p]);
|
||||
m += nr;
|
||||
d += nr;
|
||||
r += nv50->sampler_view_nr[p];
|
||||
}
|
||||
m = m * 2 + 3 * 4 + 1;
|
||||
d = d * 9 + 3 * 19 + 1;
|
||||
r = r * 2 + 3 * 2;
|
||||
need_flush = nv50_validate_tsc(nv50, 0);
|
||||
need_flush |= nv50_validate_tsc(nv50, 2);
|
||||
|
||||
so = so_new(m, d, r);
|
||||
|
||||
if (nv50_validate_textures(nv50, so, 0) == FALSE ||
|
||||
nv50_validate_textures(nv50, so, 2) == FALSE) {
|
||||
so_ref(NULL, &so);
|
||||
|
||||
NOUVEAU_ERR("failed tex validate\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
so_method(so, tesla, 0x1330, 1); /* flush TIC */
|
||||
so_data (so, 0);
|
||||
|
||||
return so;
|
||||
if (need_flush) {
|
||||
BEGIN_RING(nv50->screen->base.channel, RING_3D(TSC_FLUSH), 1);
|
||||
OUT_RING (nv50->screen->base.channel, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,197 +0,0 @@
|
|||
#ifndef __NV50_TEXTURE_H__
|
||||
#define __NV50_TEXTURE_H__
|
||||
|
||||
/* It'd be really nice to have these in nouveau_class.h generated by
|
||||
* renouveau like the rest of the object header - but not sure it can
|
||||
* handle non-object stuff nicely - need to look into it.
|
||||
*/
|
||||
|
||||
/* Texture image control block */
|
||||
#define NV50TIC_0_0_SWIZZLE_MASK 0x3ffc0000
|
||||
#define NV50TIC_0_0_MAPA_MASK 0x38000000
|
||||
#define NV50TIC_0_0_MAPA_SHIFT 27
|
||||
#define NV50TIC_0_0_MAPA_ZERO 0x00000000
|
||||
#define NV50TIC_0_0_MAPA_C0 0x10000000
|
||||
#define NV50TIC_0_0_MAPA_C1 0x18000000
|
||||
#define NV50TIC_0_0_MAPA_C2 0x20000000
|
||||
#define NV50TIC_0_0_MAPA_C3 0x28000000
|
||||
#define NV50TIC_0_0_MAPA_ONE 0x38000000
|
||||
#define NV50TIC_0_0_MAPB_MASK 0x07000000
|
||||
#define NV50TIC_0_0_MAPB_SHIFT 24
|
||||
#define NV50TIC_0_0_MAPB_ZERO 0x00000000
|
||||
#define NV50TIC_0_0_MAPB_C0 0x02000000
|
||||
#define NV50TIC_0_0_MAPB_C1 0x03000000
|
||||
#define NV50TIC_0_0_MAPB_C2 0x04000000
|
||||
#define NV50TIC_0_0_MAPB_C3 0x05000000
|
||||
#define NV50TIC_0_0_MAPB_ONE 0x07000000
|
||||
#define NV50TIC_0_0_MAPG_MASK 0x00e00000
|
||||
#define NV50TIC_0_0_MAPG_SHIFT 21
|
||||
#define NV50TIC_0_0_MAPG_ZERO 0x00000000
|
||||
#define NV50TIC_0_0_MAPG_C0 0x00400000
|
||||
#define NV50TIC_0_0_MAPG_C1 0x00600000
|
||||
#define NV50TIC_0_0_MAPG_C2 0x00800000
|
||||
#define NV50TIC_0_0_MAPG_C3 0x00a00000
|
||||
#define NV50TIC_0_0_MAPG_ONE 0x00e00000
|
||||
#define NV50TIC_0_0_MAPR_MASK 0x001c0000
|
||||
#define NV50TIC_0_0_MAPR_SHIFT 18
|
||||
#define NV50TIC_0_0_MAPR_ZERO 0x00000000
|
||||
#define NV50TIC_0_0_MAPR_C0 0x00080000
|
||||
#define NV50TIC_0_0_MAPR_C1 0x000c0000
|
||||
#define NV50TIC_0_0_MAPR_C2 0x00100000
|
||||
#define NV50TIC_0_0_MAPR_C3 0x00140000
|
||||
#define NV50TIC_0_0_MAPR_ONE 0x001c0000
|
||||
#define NV50TIC_0_0_TYPEA_MASK 0x00038000
|
||||
#define NV50TIC_0_0_TYPEA_UNORM 0x00010000
|
||||
#define NV50TIC_0_0_TYPEA_SNORM 0x00008000
|
||||
#define NV50TIC_0_0_TYPEA_SINT 0x00018000
|
||||
#define NV50TIC_0_0_TYPEA_UINT 0x00020000
|
||||
#define NV50TIC_0_0_TYPEA_SSCALED 0x00028000
|
||||
#define NV50TIC_0_0_TYPEA_USCALED 0x00030000
|
||||
#define NV50TIC_0_0_TYPEA_FLOAT 0x00038000
|
||||
#define NV50TIC_0_0_TYPEB_MASK 0x00007000
|
||||
#define NV50TIC_0_0_TYPEB_UNORM 0x00002000
|
||||
#define NV50TIC_0_0_TYPEB_SNORM 0x00001000
|
||||
#define NV50TIC_0_0_TYPEB_SINT 0x00003000
|
||||
#define NV50TIC_0_0_TYPEB_UINT 0x00004000
|
||||
#define NV50TIC_0_0_TYPEB_SSCALED 0x00005000
|
||||
#define NV50TIC_0_0_TYPEB_USCALED 0x00006000
|
||||
#define NV50TIC_0_0_TYPEB_FLOAT 0x00007000
|
||||
#define NV50TIC_0_0_TYPEG_MASK 0x00000e00
|
||||
#define NV50TIC_0_0_TYPEG_UNORM 0x00000400
|
||||
#define NV50TIC_0_0_TYPEG_SNORM 0x00000200
|
||||
#define NV50TIC_0_0_TYPEG_SINT 0x00000600
|
||||
#define NV50TIC_0_0_TYPEG_UINT 0x00000800
|
||||
#define NV50TIC_0_0_TYPEG_SSCALED 0x00000a00
|
||||
#define NV50TIC_0_0_TYPEG_USCALED 0x00000c00
|
||||
#define NV50TIC_0_0_TYPEG_FLOAT 0x00000e00
|
||||
#define NV50TIC_0_0_TYPER_MASK 0x000001c0
|
||||
#define NV50TIC_0_0_TYPER_UNORM 0x00000080
|
||||
#define NV50TIC_0_0_TYPER_SNORM 0x00000040
|
||||
#define NV50TIC_0_0_TYPER_SINT 0x000000c0
|
||||
#define NV50TIC_0_0_TYPER_UINT 0x00000100
|
||||
#define NV50TIC_0_0_TYPER_SSCALED 0x00000140
|
||||
#define NV50TIC_0_0_TYPER_USCALED 0x00000180
|
||||
#define NV50TIC_0_0_TYPER_FLOAT 0x000001c0
|
||||
#define NV50TIC_0_0_FMT_MASK 0x0000003f
|
||||
#define NV50TIC_0_0_FMT_32_32_32_32 0x00000001
|
||||
#define NV50TIC_0_0_FMT_16_16_16_16 0x00000003
|
||||
#define NV50TIC_0_0_FMT_32_32 0x00000004
|
||||
#define NV50TIC_0_0_FMT_8_8_8_8 0x00000008
|
||||
#define NV50TIC_0_0_FMT_2_10_10_10 0x00000009
|
||||
#define NV50TIC_0_0_FMT_16_16 0x0000000c
|
||||
#define NV50TIC_0_0_FMT_32 0x0000000f
|
||||
#define NV50TIC_0_0_FMT_4_4_4_4 0x00000012
|
||||
/* #define NV50TIC_0_0_FMT_1_5_5_5 0x00000013 */
|
||||
#define NV50TIC_0_0_FMT_1_5_5_5 0x00000014
|
||||
#define NV50TIC_0_0_FMT_5_6_5 0x00000015
|
||||
#define NV50TIC_0_0_FMT_8_8 0x00000018
|
||||
#define NV50TIC_0_0_FMT_16 0x0000001b
|
||||
#define NV50TIC_0_0_FMT_8 0x0000001d
|
||||
#define NV50TIC_0_0_FMT_5_9_9_9 0x00000020
|
||||
#define NV50TIC_0_0_FMT_10_11_11 0x00000021
|
||||
#define NV50TIC_0_0_FMT_DXT1 0x00000024
|
||||
#define NV50TIC_0_0_FMT_DXT3 0x00000025
|
||||
#define NV50TIC_0_0_FMT_DXT5 0x00000026
|
||||
#define NV50TIC_0_0_FMT_RGTC1 0x00000027
|
||||
#define NV50TIC_0_0_FMT_RGTC2 0x00000028
|
||||
#define NV50TIC_0_0_FMT_24_8 0x00000029
|
||||
#define NV50TIC_0_0_FMT_8_24 0x0000002a
|
||||
#define NV50TIC_0_0_FMT_32_DEPTH 0x0000002f
|
||||
#define NV50TIC_0_0_FMT_32_8 0x00000030
|
||||
#define NV50TIC_0_0_FMT_16_DEPTH 0x0000003a
|
||||
|
||||
#define NV50TIC_0_1_OFFSET_LOW_MASK 0xffffffff
|
||||
#define NV50TIC_0_1_OFFSET_LOW_SHIFT 0
|
||||
|
||||
#define NV50TIC_0_2_COLORSPACE_SRGB 0x00000400
|
||||
#define NV50TIC_0_2_TARGET_1D 0x00000000
|
||||
#define NV50TIC_0_2_TARGET_2D 0x00004000
|
||||
#define NV50TIC_0_2_TARGET_3D 0x00008000
|
||||
#define NV50TIC_0_2_TARGET_CUBE 0x0000c000
|
||||
#define NV50TIC_0_2_TARGET_1D_ARRAY 0x00010000
|
||||
#define NV50TIC_0_2_TARGET_2D_ARRAY 0x00014000
|
||||
#define NV50TIC_0_2_TARGET_BUFFER 0x00018000
|
||||
#define NV50TIC_0_2_TARGET_RECT 0x0001c000
|
||||
/* #define NV50TIC_0_0_TILE_MODE_LINEAR 0x00040000 */
|
||||
#define NV50TIC_0_2_TILE_MODE_Y_MASK 0x01c00000
|
||||
#define NV50TIC_0_2_TILE_MODE_Y_SHIFT 22
|
||||
#define NV50TIC_0_2_TILE_MODE_Z_MASK 0x0e000000
|
||||
#define NV50TIC_0_2_TILE_MODE_Z_SHIFT 25
|
||||
#define NV50TIC_0_2_NORMALIZED_COORDS 0x80000000
|
||||
|
||||
#define NV50TIC_0_3_UNKNOWN_MASK 0xffffffff
|
||||
|
||||
#define NV50TIC_0_4_WIDTH_MASK 0x0000ffff
|
||||
#define NV50TIC_0_4_WIDTH_SHIFT 0
|
||||
|
||||
#define NV50TIC_0_5_LAST_LEVEL_MASK 0xf0000000
|
||||
#define NV50TIC_0_5_LAST_LEVEL_SHIFT 28
|
||||
#define NV50TIC_0_5_DEPTH_MASK 0x0fff0000
|
||||
#define NV50TIC_0_5_DEPTH_SHIFT 16
|
||||
#define NV50TIC_0_5_HEIGHT_MASK 0x0000ffff
|
||||
#define NV50TIC_0_5_HEIGHT_SHIFT 0
|
||||
#define NV50TIC_0_6_UNKNOWN_MASK 0xffffffff
|
||||
|
||||
#define NV50TIC_0_7_BASE_LEVEL_MASK 0x0000000f
|
||||
#define NV50TIC_0_7_BASE_LEVEL_SHIFT 0
|
||||
#define NV50TIC_0_7_MAX_LEVEL_MASK 0x000000f0
|
||||
#define NV50TIC_0_7_MAX_LEVEL_SHIFT 4
|
||||
|
||||
/* Texture sampler control block */
|
||||
#define NV50TSC_1_0_WRAPS_MASK 0x00000007
|
||||
#define NV50TSC_1_0_WRAPS_REPEAT 0x00000000
|
||||
#define NV50TSC_1_0_WRAPS_MIRROR_REPEAT 0x00000001
|
||||
#define NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE 0x00000002
|
||||
#define NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER 0x00000003
|
||||
#define NV50TSC_1_0_WRAPS_CLAMP 0x00000004
|
||||
#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE 0x00000005
|
||||
#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER 0x00000006
|
||||
#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP 0x00000007
|
||||
#define NV50TSC_1_0_WRAPT_MASK 0x00000038
|
||||
#define NV50TSC_1_0_WRAPT_REPEAT 0x00000000
|
||||
#define NV50TSC_1_0_WRAPT_MIRROR_REPEAT 0x00000008
|
||||
#define NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE 0x00000010
|
||||
#define NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER 0x00000018
|
||||
#define NV50TSC_1_0_WRAPT_CLAMP 0x00000020
|
||||
#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP_TO_EDGE 0x00000028
|
||||
#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP_TO_BORDER 0x00000030
|
||||
#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP 0x00000038
|
||||
#define NV50TSC_1_0_WRAPR_MASK 0x000001c0
|
||||
#define NV50TSC_1_0_WRAPR_REPEAT 0x00000000
|
||||
#define NV50TSC_1_0_WRAPR_MIRROR_REPEAT 0x00000040
|
||||
#define NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE 0x00000080
|
||||
#define NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER 0x000000c0
|
||||
#define NV50TSC_1_0_WRAPR_CLAMP 0x00000100
|
||||
#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_EDGE 0x00000140
|
||||
#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_BORDER 0x00000180
|
||||
#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP 0x000001c0
|
||||
#define NV50TSC_1_0_MAX_ANISOTROPY_MASK 0x00700000
|
||||
|
||||
#define NV50TSC_1_1_MAGF_MASK 0x00000003
|
||||
#define NV50TSC_1_1_MAGF_NEAREST 0x00000001
|
||||
#define NV50TSC_1_1_MAGF_LINEAR 0x00000002
|
||||
#define NV50TSC_1_1_MINF_MASK 0x00000030
|
||||
#define NV50TSC_1_1_MINF_NEAREST 0x00000010
|
||||
#define NV50TSC_1_1_MINF_LINEAR 0x00000020
|
||||
#define NV50TSC_1_1_MIPF_MASK 0x000000c0
|
||||
#define NV50TSC_1_1_MIPF_NONE 0x00000040
|
||||
#define NV50TSC_1_1_MIPF_NEAREST 0x00000080
|
||||
#define NV50TSC_1_1_MIPF_LINEAR 0x000000c0
|
||||
#define NV50TSC_1_1_LOD_BIAS_MASK 0x01fff000
|
||||
#define NV50TSC_1_1_UNKN_ANISO_15 0x10000000
|
||||
#define NV50TSC_1_1_UNKN_ANISO_35 0x18000000
|
||||
|
||||
#define NV50TSC_1_2_MIN_LOD_MASK 0x00000f00
|
||||
#define NV50TSC_1_2_MAX_LOD_MASK 0x00f00000
|
||||
|
||||
#define NV50TSC_1_3_UNKNOWN_MASK 0xffffffff
|
||||
|
||||
#define NV50TSC_1_4_BORDER_COLOR_RED_MASK 0xffffffff
|
||||
|
||||
#define NV50TSC_1_5_BORDER_COLOR_GREEN_MASK 0xffffffff
|
||||
|
||||
#define NV50TSC_1_6_BORDER_COLOR_BLUE_MASK 0xffffffff
|
||||
|
||||
#define NV50TSC_1_7_BORDER_COLOR_ALPHA_MASK 0xffffffff
|
||||
|
||||
#endif
|
||||
259
src/gallium/drivers/nv50/nv50_texture.xml.h
Normal file
259
src/gallium/drivers/nv50/nv50_texture.xml.h
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
#ifndef NV50_TEXTURE_XML
|
||||
#define NV50_TEXTURE_XML
|
||||
|
||||
/* Autogenerated file, DO NOT EDIT manually!
|
||||
|
||||
This file was generated by the rules-ng-ng headergen tool in this git repository:
|
||||
http://0x04.net/cgit/index.cgi/rules-ng-ng
|
||||
git clone git://0x04.net/rules-ng-ng
|
||||
|
||||
The rules-ng-ng source files this header was generated from are:
|
||||
- nv50_texture.xml ( 6871 bytes, from 2010-10-03 13:18:37)
|
||||
- copyright.xml ( 6498 bytes, from 2010-10-03 13:18:37)
|
||||
|
||||
Copyright (C) 2006-2010 by the following authors:
|
||||
- Artur Huillet <arthur.huillet@free.fr> (ahuillet)
|
||||
- Ben Skeggs (darktama, darktama_)
|
||||
- B. R. <koala_br@users.sourceforge.net> (koala_br)
|
||||
- Carlos Martin <carlosmn@users.sf.net> (carlosmn)
|
||||
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr)
|
||||
- Dawid Gajownik <gajownik@users.sf.net> (gajownik)
|
||||
- Dmitry Baryshkov
|
||||
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag)
|
||||
- EdB <edb_@users.sf.net> (edb_)
|
||||
- Erik Waling <erikwailing@users.sf.net> (erikwaling)
|
||||
- Francisco Jerez <currojerez@riseup.net> (curro, curro_, currojerez)
|
||||
- imirkin <imirkin@users.sf.net> (imirkin)
|
||||
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome)
|
||||
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy)
|
||||
- Laurent Carlier <lordheavym@gmail.com> (lordheavy)
|
||||
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1)
|
||||
- Maarten Maathuis <madman2003@gmail.com> (stillunknown)
|
||||
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin)
|
||||
- Mark Carey <mark.carey@gmail.com> (careym)
|
||||
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c)
|
||||
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman)
|
||||
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata)
|
||||
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen)
|
||||
- Peter Popov <ironpeter@users.sf.net> (ironpeter)
|
||||
- Richard Hughes <hughsient@users.sf.net> (hughsient)
|
||||
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar)
|
||||
- Serge Martin
|
||||
- Simon Raffeiner
|
||||
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier)
|
||||
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu)
|
||||
- sturmflut <sturmflut@users.sf.net> (sturmflut)
|
||||
- Sylvain Munaut <tnt@246tNt.com>
|
||||
- Victor Stinner <victor.stinner@haypocalc.com> (haypo)
|
||||
- Wladmir van der Laan <laanwj@gmail.com> (miathan6)
|
||||
- Younes Manton <younes.m@gmail.com> (ymanton)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the
|
||||
next paragraph) shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#define NV50_TIC_MAP_ZERO 0x00000000
|
||||
#define NV50_TIC_MAP_C0 0x00000002
|
||||
#define NV50_TIC_MAP_C1 0x00000003
|
||||
#define NV50_TIC_MAP_C2 0x00000004
|
||||
#define NV50_TIC_MAP_C3 0x00000005
|
||||
#define NV50_TIC_MAP_ONE 0x00000007
|
||||
#define NV50_TIC_TYPE_SNORM 0x00000001
|
||||
#define NV50_TIC_TYPE_UNORM 0x00000002
|
||||
#define NV50_TIC_TYPE_SINT 0x00000003
|
||||
#define NV50_TIC_TYPE_UINT 0x00000004
|
||||
#define NV50_TIC_TYPE_SSCALED 0x00000005
|
||||
#define NV50_TIC_TYPE_USCALED 0x00000006
|
||||
#define NV50_TIC_TYPE_FLOAT 0x00000007
|
||||
#define NV50_TSC_WRAP_REPEAT 0x00000000
|
||||
#define NV50_TSC_WRAP_MIRROR_REPEAT 0x00000001
|
||||
#define NV50_TSC_WRAP_CLAMP_TO_EDGE 0x00000002
|
||||
#define NV50_TSC_WRAP_CLAMP_TO_BORDER 0x00000003
|
||||
#define NV50_TSC_WRAP_CLAMP 0x00000004
|
||||
#define NV50_TSC_WRAP_MIRROR_CLAMP_TO_EDGE 0x00000005
|
||||
#define NV50_TSC_WRAP_MIRROR_CLAMP_TO_BORDER 0x00000006
|
||||
#define NV50_TSC_WRAP_MIRROR_CLAMP 0x00000007
|
||||
#define NV50_TIC__SIZE 0x00000020
|
||||
#define NV50_TIC_0 0x00000000
|
||||
#define NV50_TIC_0_MAPA__MASK 0x38000000
|
||||
#define NV50_TIC_0_MAPA__SHIFT 27
|
||||
#define NV50_TIC_0_MAPB__MASK 0x07000000
|
||||
#define NV50_TIC_0_MAPB__SHIFT 24
|
||||
#define NV50_TIC_0_MAPG__MASK 0x00e00000
|
||||
#define NV50_TIC_0_MAPG__SHIFT 21
|
||||
#define NV50_TIC_0_MAPR__MASK 0x001c0000
|
||||
#define NV50_TIC_0_MAPR__SHIFT 18
|
||||
#define NV50_TIC_0_TYPE3__MASK 0x00038000
|
||||
#define NV50_TIC_0_TYPE3__SHIFT 15
|
||||
#define NV50_TIC_0_TYPE2__MASK 0x00007000
|
||||
#define NV50_TIC_0_TYPE2__SHIFT 12
|
||||
#define NV50_TIC_0_TYPE1__MASK 0x00000e00
|
||||
#define NV50_TIC_0_TYPE1__SHIFT 9
|
||||
#define NV50_TIC_0_TYPE0__MASK 0x000001c0
|
||||
#define NV50_TIC_0_TYPE0__SHIFT 6
|
||||
#define NV50_TIC_0_SWIZZLE__MASK 0x3ffc0000
|
||||
#define NV50_TIC_0_FMT__MASK 0x0000003f
|
||||
#define NV50_TIC_0_FMT__SHIFT 0
|
||||
#define NV50_TIC_0_FMT_32_32_32_32 0x00000001
|
||||
#define NV50_TIC_0_FMT_16_16_16_16 0x00000003
|
||||
#define NV50_TIC_0_FMT_32_32 0x00000004
|
||||
#define NV50_TIC_0_FMT_32_8 0x00000005
|
||||
#define NV50_TIC_0_FMT_8_8_8_8 0x00000008
|
||||
#define NV50_TIC_0_FMT_2_10_10_10 0x00000009
|
||||
#define NV50_TIC_0_FMT_16_16 0x0000000c
|
||||
#define NV50_TIC_0_FMT_8_24 0x0000000d
|
||||
#define NV50_TIC_0_FMT_24_8 0x0000000e
|
||||
#define NV50_TIC_0_FMT_32 0x0000000f
|
||||
#define NV50_TIC_0_FMT_4_4_4_4 0x00000012
|
||||
#define NV50_TIC_0_FMT_5_5_5_1 0x00000013
|
||||
#define NV50_TIC_0_FMT_1_5_5_5 0x00000014
|
||||
#define NV50_TIC_0_FMT_5_6_5 0x00000015
|
||||
#define NV50_TIC_0_FMT_6_5_5 0x00000016
|
||||
#define NV50_TIC_0_FMT_8_8 0x00000018
|
||||
#define NV50_TIC_0_FMT_16 0x0000001b
|
||||
#define NV50_TIC_0_FMT_8 0x0000001d
|
||||
#define NV50_TIC_0_FMT_4_4 0x0000001e
|
||||
#define NV50_TIC_0_FMT_UNK1F 0x0000001f
|
||||
#define NV50_TIC_0_FMT_E5_9_9_9 0x00000020
|
||||
#define NV50_TIC_0_FMT_10_11_11 0x00000021
|
||||
#define NV50_TIC_0_FMT_C1_C2_C1_C0 0x00000022
|
||||
#define NV50_TIC_0_FMT_C2_C1_C0_C1 0x00000023
|
||||
#define NV50_TIC_0_FMT_DXT1 0x00000024
|
||||
#define NV50_TIC_0_FMT_DXT3 0x00000025
|
||||
#define NV50_TIC_0_FMT_DXT5 0x00000026
|
||||
#define NV50_TIC_0_FMT_RGTC1 0x00000027
|
||||
#define NV50_TIC_0_FMT_RGTC2 0x00000028
|
||||
#define NV50_TIC_0_FMT_24_8_ZETA 0x00000029
|
||||
#define NV50_TIC_0_FMT_8_24_ZETA 0x0000002a
|
||||
#define NV50_TIC_0_FMT_UNK2C_ZETA 0x0000002c
|
||||
#define NV50_TIC_0_FMT_UNK2D_ZETA 0x0000002d
|
||||
#define NV50_TIC_0_FMT_UNK2E_ZETA 0x0000002e
|
||||
#define NV50_TIC_0_FMT_32_ZETA 0x0000002f
|
||||
#define NV50_TIC_0_FMT_32_8_ZETA 0x00000030
|
||||
#define NV50_TIC_0_FMT_16_ZETA 0x0000003a
|
||||
|
||||
#define NV50_TIC_1 0x00000004
|
||||
#define NV50_TIC_1_OFFSET_LOW__MASK 0xffffffff
|
||||
#define NV50_TIC_1_OFFSET_LOW__SHIFT 0
|
||||
|
||||
#define NV50_TIC_2 0x00000008
|
||||
#define NV50_TIC_2_OFFSET_HIGH__MASK 0x000000ff
|
||||
#define NV50_TIC_2_OFFSET_HIGH__SHIFT 0
|
||||
#define NV50_TIC_2_COLORSPACE_SRGB 0x00000400
|
||||
#define NV50_TIC_2_TARGET__MASK 0x0003c000
|
||||
#define NV50_TIC_2_TARGET__SHIFT 14
|
||||
#define NV50_TIC_2_TARGET_1D 0x00000000
|
||||
#define NV50_TIC_2_TARGET_2D 0x00004000
|
||||
#define NV50_TIC_2_TARGET_3D 0x00008000
|
||||
#define NV50_TIC_2_TARGET_CUBE 0x0000c000
|
||||
#define NV50_TIC_2_TARGET_1D_ARRAY 0x00010000
|
||||
#define NV50_TIC_2_TARGET_2D_ARRAY 0x00014000
|
||||
#define NV50_TIC_2_TARGET_BUFFER 0x00018000
|
||||
#define NV50_TIC_2_TARGET_RECT 0x0001c000
|
||||
#define NV50_TIC_2_TARGET_CUBE_ARRAY 0x00020000
|
||||
#define NV50_TIC_2_TILE_MODE_LINEAR 0x00040000
|
||||
#define NV50_TIC_2_TILE_MODE_Y__MASK 0x01c00000
|
||||
#define NV50_TIC_2_TILE_MODE_Y__SHIFT 22
|
||||
#define NV50_TIC_2_TILE_MODE_Z__MASK 0x0e000000
|
||||
#define NV50_TIC_2_TILE_MODE_Z__SHIFT 25
|
||||
#define NV50_TIC_2_2D_UNK0258__MASK 0x30000000
|
||||
#define NV50_TIC_2_2D_UNK0258__SHIFT 28
|
||||
#define NV50_TIC_2_NORMALIZED_COORDS 0x80000000
|
||||
|
||||
#define NV50_TIC_3 0x0000000c
|
||||
#define NV50_TIC_3_PITCH__MASK 0xffffffff
|
||||
#define NV50_TIC_3_PITCH__SHIFT 0
|
||||
|
||||
#define NV50_TIC_4 0x00000010
|
||||
#define NV50_TIC_4_WIDTH__MASK 0xffffffff
|
||||
#define NV50_TIC_4_WIDTH__SHIFT 0
|
||||
|
||||
#define NV50_TIC_5 0x00000014
|
||||
#define NV50_TIC_5_LAST_LEVEL__MASK 0xf0000000
|
||||
#define NV50_TIC_5_LAST_LEVEL__SHIFT 28
|
||||
#define NV50_TIC_5_DEPTH__MASK 0x0fff0000
|
||||
#define NV50_TIC_5_DEPTH__SHIFT 16
|
||||
#define NV50_TIC_5_HEIGHT__MASK 0x0000ffff
|
||||
#define NV50_TIC_5_HEIGHT__SHIFT 0
|
||||
|
||||
#define NV50_TIC_7 0x0000001c
|
||||
#define NV50_TIC_7_BASE_LEVEL__MASK 0x0000000f
|
||||
#define NV50_TIC_7_BASE_LEVEL__SHIFT 0
|
||||
#define NV50_TIC_7_MAX_LEVEL__MASK 0x000000f0
|
||||
#define NV50_TIC_7_MAX_LEVEL__SHIFT 4
|
||||
|
||||
#define NV50_TSC__SIZE 0x00000020
|
||||
#define NV50_TSC_0 0x00000000
|
||||
#define NV50_TSC_0_WRAPS__MASK 0x00000007
|
||||
#define NV50_TSC_0_WRAPS__SHIFT 0
|
||||
#define NV50_TSC_0_WRAPT__MASK 0x00000038
|
||||
#define NV50_TSC_0_WRAPT__SHIFT 3
|
||||
#define NV50_TSC_0_WRAPR__MASK 0x000001c0
|
||||
#define NV50_TSC_0_WRAPR__SHIFT 6
|
||||
#define NV50_TSC_0_SHADOW_COMPARE_ENABLE 0x00000200
|
||||
#define NV50_TSC_0_SHADOW_COMPARE_FUNC__MASK 0x00001c00
|
||||
#define NV50_TSC_0_SHADOW_COMPARE_FUNC__SHIFT 10
|
||||
#define NV50_TSC_0_ANISOTROPY_MASK__MASK 0x00700000
|
||||
#define NV50_TSC_0_ANISOTROPY_MASK__SHIFT 20
|
||||
|
||||
#define NV50_TSC_1 0x00000004
|
||||
#define NV50_TSC_1_UNKN_ANISO_15 0x10000000
|
||||
#define NV50_TSC_1_UNKN_ANISO_35 0x18000000
|
||||
#define NV50_TSC_1_MAGF__MASK 0x00000003
|
||||
#define NV50_TSC_1_MAGF__SHIFT 0
|
||||
#define NV50_TSC_1_MAGF_NEAREST 0x00000001
|
||||
#define NV50_TSC_1_MAGF_LINEAR 0x00000002
|
||||
#define NV50_TSC_1_MINF__MASK 0x00000030
|
||||
#define NV50_TSC_1_MINF__SHIFT 4
|
||||
#define NV50_TSC_1_MINF_NEAREST 0x00000010
|
||||
#define NV50_TSC_1_MINF_LINEAR 0x00000020
|
||||
#define NV50_TSC_1_MIPF__MASK 0x000000c0
|
||||
#define NV50_TSC_1_MIPF__SHIFT 6
|
||||
#define NV50_TSC_1_MIPF_NONE 0x00000040
|
||||
#define NV50_TSC_1_MIPF_NEAREST 0x00000080
|
||||
#define NV50_TSC_1_MIPF_LINEAR 0x000000c0
|
||||
#define NV50_TSC_1_LOD_BIAS__MASK 0x01fff000
|
||||
#define NV50_TSC_1_LOD_BIAS__SHIFT 12
|
||||
|
||||
#define NV50_TSC_2 0x00000008
|
||||
#define NV50_TSC_2_MIN_LOD__MASK 0x00000f00
|
||||
#define NV50_TSC_2_MIN_LOD__SHIFT 8
|
||||
#define NV50_TSC_2_MAX_LOD__MASK 0x00f00000
|
||||
#define NV50_TSC_2_MAX_LOD__SHIFT 20
|
||||
|
||||
#define NV50_TSC_4 0x00000010
|
||||
#define NV50_TSC_4_BORDER_COLOR_RED__MASK 0xffffffff
|
||||
#define NV50_TSC_4_BORDER_COLOR_RED__SHIFT 0
|
||||
|
||||
#define NV50_TSC_5 0x00000014
|
||||
#define NV50_TSC_5_BORDER_COLOR_GREEN__MASK 0xffffffff
|
||||
#define NV50_TSC_5_BORDER_COLOR_GREEN__SHIFT 0
|
||||
|
||||
#define NV50_TSC_6 0x00000018
|
||||
#define NV50_TSC_6_BORDER_COLOR_BLUE__MASK 0xffffffff
|
||||
#define NV50_TSC_6_BORDER_COLOR_BLUE__SHIFT 0
|
||||
|
||||
#define NV50_TSC_7 0x0000001c
|
||||
#define NV50_TSC_7_BORDER_COLOR_ALPHA__MASK 0xffffffff
|
||||
#define NV50_TSC_7_BORDER_COLOR_ALPHA__SHIFT 0
|
||||
|
||||
|
||||
#endif /* NV50_TEXTURE_XML */
|
||||
|
|
@ -476,6 +476,7 @@ bld_loop_end(struct bld_context *bld, struct nv_basic_block *bb)
|
|||
stk = (struct bld_value_stack *)phi->target;
|
||||
phi->target = NULL;
|
||||
|
||||
/* start with s == 1, src[0] is from outside the loop */
|
||||
for (s = 1, n = 0; n < bb->num_in; ++n) {
|
||||
if (bb->in_kind[n] != CFG_EDGE_BACK)
|
||||
continue;
|
||||
|
|
@ -487,8 +488,11 @@ bld_loop_end(struct bld_context *bld, struct nv_basic_block *bb)
|
|||
for (i = 0; i < 4; ++i)
|
||||
if (phi->src[i] && phi->src[i]->value == val)
|
||||
break;
|
||||
if (i == 4)
|
||||
if (i == 4) {
|
||||
/* skip values we do not want to replace */
|
||||
for (; phi->src[s] && phi->src[s]->value != phi->def[0]; ++s);
|
||||
nv_reference(bld->pc, &phi->src[s++], val);
|
||||
}
|
||||
}
|
||||
bld->pc->current_block = save;
|
||||
|
||||
|
|
@ -1102,9 +1106,8 @@ emit_fetch(struct bld_context *bld, const struct tgsi_full_instruction *insn,
|
|||
|
||||
switch (src->Register.File) {
|
||||
case TGSI_FILE_CONSTANT:
|
||||
dim_idx = src->Dimension.Index ? src->Dimension.Index + 2 : 1;
|
||||
assert(dim_idx < 14);
|
||||
assert(dim_idx == 1); /* for now */
|
||||
dim_idx = src->Dimension.Index;
|
||||
assert(dim_idx < 15);
|
||||
|
||||
res = new_value(bld->pc, NV_FILE_MEM_C(dim_idx), type);
|
||||
SET_TYPE(res, type);
|
||||
|
|
@ -1468,7 +1471,7 @@ bld_tex(struct bld_context *bld, struct nv_value *dst0[4],
|
|||
uint opcode = translate_opcode(insn->Instruction.Opcode);
|
||||
int arg, dim, c;
|
||||
const int tic = insn->Src[1].Register.Index;
|
||||
const int tsc = 0;
|
||||
const int tsc = tic;
|
||||
const int cube = (insn->Texture.Texture == TGSI_TEXTURE_CUBE) ? 1 : 0;
|
||||
|
||||
get_tex_dim(insn, &dim, &arg);
|
||||
|
|
@ -1717,6 +1720,10 @@ bld_instruction(struct bld_context *bld,
|
|||
{
|
||||
struct nv_basic_block *b = new_basic_block(bld->pc);
|
||||
|
||||
if (bld->pc->current_block->exit &&
|
||||
!bld->pc->current_block->exit->is_terminator)
|
||||
bld_flow(bld, NV_OP_BRA, NV_CC_TR, NULL, b, FALSE);
|
||||
|
||||
--bld->cond_lvl;
|
||||
nvbb_attach_block(bld->pc->current_block, b, bld->out_kind);
|
||||
nvbb_attach_block(bld->cond_bb[bld->cond_lvl], b, CFG_EDGE_FORWARD);
|
||||
|
|
@ -1923,6 +1930,7 @@ bld_instruction(struct bld_context *bld,
|
|||
dst0[c] = bld_insn_2(bld, NV_OP_XOR, temp, temp);
|
||||
dst0[c]->insn->cc = NV_CC_EQ;
|
||||
nv_reference(bld->pc, &dst0[c]->insn->flags_src, src1);
|
||||
dst0[c] = bld_insn_2(bld, NV_OP_SELECT, dst0[c], temp);
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_SUB:
|
||||
|
|
|
|||
|
|
@ -1,351 +1,347 @@
|
|||
|
||||
#include "pipe/p_context.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "nv50_context.h"
|
||||
#include "nv50_transfer.h"
|
||||
#include "nv50_resource.h"
|
||||
|
||||
#include "nv50_defs.xml.h"
|
||||
|
||||
struct nv50_transfer {
|
||||
struct pipe_transfer base;
|
||||
struct nouveau_bo *bo;
|
||||
int map_refcnt;
|
||||
unsigned level_offset;
|
||||
unsigned level_tiling;
|
||||
int level_pitch;
|
||||
int level_width;
|
||||
int level_height;
|
||||
int level_depth;
|
||||
int level_x;
|
||||
int level_y;
|
||||
int level_z;
|
||||
unsigned nblocksx;
|
||||
unsigned nblocksy;
|
||||
struct pipe_transfer base;
|
||||
struct nv50_m2mf_rect rect[2];
|
||||
uint32_t nblocksx;
|
||||
uint32_t nblocksy;
|
||||
};
|
||||
|
||||
static void
|
||||
nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
|
||||
struct nouveau_bo *src_bo, unsigned src_offset,
|
||||
int src_pitch, unsigned src_tile_mode,
|
||||
int sx, int sy, int sz, int sw, int sh, int sd,
|
||||
struct nouveau_bo *dst_bo, unsigned dst_offset,
|
||||
int dst_pitch, unsigned dst_tile_mode,
|
||||
int dx, int dy, int dz, int dw, int dh, int dd,
|
||||
int cpp, int width, int height,
|
||||
unsigned src_reloc, unsigned dst_reloc)
|
||||
nv50_m2mf_transfer_rect(struct pipe_screen *pscreen,
|
||||
const struct nv50_m2mf_rect *dst,
|
||||
const struct nv50_m2mf_rect *src,
|
||||
uint32_t nblocksx, uint32_t nblocksy)
|
||||
{
|
||||
struct nv50_screen *screen = nv50_screen(pscreen);
|
||||
struct nouveau_channel *chan = screen->m2mf->channel;
|
||||
struct nouveau_grobj *m2mf = screen->m2mf;
|
||||
struct nouveau_channel *chan = nouveau_screen(pscreen)->channel;
|
||||
const int cpp = dst->cpp;
|
||||
uint32_t src_ofst = src->base;
|
||||
uint32_t dst_ofst = dst->base;
|
||||
uint32_t height = nblocksy;
|
||||
uint32_t sy = src->y;
|
||||
uint32_t dy = dst->y;
|
||||
|
||||
src_reloc |= NOUVEAU_BO_RD;
|
||||
dst_reloc |= NOUVEAU_BO_WR;
|
||||
assert(dst->cpp == src->cpp);
|
||||
|
||||
WAIT_RING (chan, 14);
|
||||
if (nouveau_bo_tile_layout(src->bo)) {
|
||||
BEGIN_RING(chan, RING_MF(LINEAR_IN), 6);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, src->tile_mode << 4);
|
||||
OUT_RING (chan, src->width * cpp);
|
||||
OUT_RING (chan, src->height);
|
||||
OUT_RING (chan, src->depth);
|
||||
OUT_RING (chan, src->z);
|
||||
} else {
|
||||
src_ofst += src->y * src->pitch + src->x * cpp;
|
||||
|
||||
if (!nouveau_bo_tile_layout(src_bo)) {
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_IN, 1);
|
||||
OUT_RING (chan, src_pitch);
|
||||
src_offset += (sy * src_pitch) + (sx * cpp);
|
||||
} else {
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 6);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, src_tile_mode << 4);
|
||||
OUT_RING (chan, sw * cpp);
|
||||
OUT_RING (chan, sh);
|
||||
OUT_RING (chan, sd);
|
||||
OUT_RING (chan, sz); /* copying only 1 zslice per call */
|
||||
}
|
||||
BEGIN_RING(chan, RING_MF(LINEAR_IN), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_MF_(NV04_M2MF_PITCH_IN), 1);
|
||||
OUT_RING (chan, src->pitch);
|
||||
}
|
||||
|
||||
if (!nouveau_bo_tile_layout(dst_bo)) {
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT, 1);
|
||||
OUT_RING (chan, dst_pitch);
|
||||
dst_offset += (dy * dst_pitch) + (dx * cpp);
|
||||
} else {
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 6);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, dst_tile_mode << 4);
|
||||
OUT_RING (chan, dw * cpp);
|
||||
OUT_RING (chan, dh);
|
||||
OUT_RING (chan, dd);
|
||||
OUT_RING (chan, dz); /* copying only 1 zslice per call */
|
||||
}
|
||||
if (nouveau_bo_tile_layout(dst->bo)) {
|
||||
BEGIN_RING(chan, RING_MF(LINEAR_OUT), 6);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, dst->tile_mode << 4);
|
||||
OUT_RING (chan, dst->width * cpp);
|
||||
OUT_RING (chan, dst->height);
|
||||
OUT_RING (chan, dst->depth);
|
||||
OUT_RING (chan, dst->z);
|
||||
} else {
|
||||
dst_ofst += dst->y * dst->pitch + dst->x * cpp;
|
||||
|
||||
while (height) {
|
||||
int line_count = height > 2047 ? 2047 : height;
|
||||
BEGIN_RING(chan, RING_MF(LINEAR_OUT), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_MF_(NV04_M2MF_PITCH_OUT), 1);
|
||||
OUT_RING (chan, dst->pitch);
|
||||
}
|
||||
|
||||
MARK_RING (chan, 15, 4); /* flush on lack of space or relocs */
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2);
|
||||
OUT_RELOCh(chan, src_bo, src_offset, src_reloc);
|
||||
OUT_RELOCh(chan, dst_bo, dst_offset, dst_reloc);
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 2);
|
||||
OUT_RELOCl(chan, src_bo, src_offset, src_reloc);
|
||||
OUT_RELOCl(chan, dst_bo, dst_offset, dst_reloc);
|
||||
if (nouveau_bo_tile_layout(src_bo)) {
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_IN, 1);
|
||||
OUT_RING (chan, (sy << 16) | (sx * cpp));
|
||||
} else {
|
||||
src_offset += (line_count * src_pitch);
|
||||
}
|
||||
if (nouveau_bo_tile_layout(dst_bo)) {
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_OUT, 1);
|
||||
OUT_RING (chan, (dy << 16) | (dx * cpp));
|
||||
} else {
|
||||
dst_offset += (line_count * dst_pitch);
|
||||
}
|
||||
BEGIN_RING(chan, m2mf,
|
||||
NV04_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN, 4);
|
||||
OUT_RING (chan, width * cpp);
|
||||
OUT_RING (chan, line_count);
|
||||
OUT_RING (chan, 0x00000101);
|
||||
OUT_RING (chan, 0);
|
||||
FIRE_RING (chan);
|
||||
while (height) {
|
||||
int line_count = height > 2047 ? 2047 : height;
|
||||
|
||||
height -= line_count;
|
||||
sy += line_count;
|
||||
dy += line_count;
|
||||
}
|
||||
MARK_RING (chan, 17, 4);
|
||||
|
||||
BEGIN_RING(chan, RING_MF(OFFSET_IN_HIGH), 2);
|
||||
OUT_RELOCh(chan, src->bo, src_ofst, src->domain | NOUVEAU_BO_RD);
|
||||
OUT_RELOCh(chan, dst->bo, dst_ofst, dst->domain | NOUVEAU_BO_WR);
|
||||
|
||||
BEGIN_RING(chan, RING_MF_(NV04_M2MF_OFFSET_IN), 2);
|
||||
OUT_RELOCl(chan, src->bo, src_ofst, src->domain | NOUVEAU_BO_RD);
|
||||
OUT_RELOCl(chan, dst->bo, dst_ofst, dst->domain | NOUVEAU_BO_WR);
|
||||
|
||||
if (nouveau_bo_tile_layout(src->bo)) {
|
||||
BEGIN_RING(chan, RING_MF(TILING_POSITION_IN), 1);
|
||||
OUT_RING (chan, (sy << 16) | (src->x * cpp));
|
||||
} else {
|
||||
src_ofst += line_count * src->pitch;
|
||||
}
|
||||
if (nouveau_bo_tile_layout(dst->bo)) {
|
||||
BEGIN_RING(chan, RING_MF(TILING_POSITION_OUT), 1);
|
||||
OUT_RING (chan, (dy << 16) | (dst->x * cpp));
|
||||
} else {
|
||||
dst_ofst += line_count * dst->pitch;
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, RING_MF_(NV04_M2MF_LINE_LENGTH_IN), 4);
|
||||
OUT_RING (chan, nblocksx * cpp);
|
||||
OUT_RING (chan, line_count);
|
||||
OUT_RING (chan, (1 << 8) | (1 << 0));
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
height -= line_count;
|
||||
sy += line_count;
|
||||
dy += line_count;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv50_sifc_linear_u8(struct nv50_context *nv50,
|
||||
struct nouveau_bo *dst, unsigned domain, int offset,
|
||||
unsigned size, void *data)
|
||||
{
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
uint32_t *src = (uint32_t *)data;
|
||||
unsigned count = (size + 3) / 4;
|
||||
unsigned xcoord = offset & 0xff;
|
||||
|
||||
offset &= ~0xff;
|
||||
|
||||
MARK_RING (chan, 23, 4);
|
||||
BEGIN_RING(chan, RING_2D(DST_FORMAT), 2);
|
||||
OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_2D(DST_PITCH), 5);
|
||||
OUT_RING (chan, 262144);
|
||||
OUT_RING (chan, 65536);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RELOCh(chan, dst, offset, domain | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, dst, offset, domain | NOUVEAU_BO_WR);
|
||||
BEGIN_RING(chan, RING_2D(SIFC_BITMAP_ENABLE), 2);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM);
|
||||
BEGIN_RING(chan, RING_2D(SIFC_WIDTH), 10);
|
||||
OUT_RING (chan, size);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, xcoord);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
while (count) {
|
||||
unsigned nr = AVAIL_RING(chan);
|
||||
|
||||
if (nr < 9) {
|
||||
FIRE_RING(chan);
|
||||
nouveau_bo_validate(chan, dst, NOUVEAU_BO_WR);
|
||||
continue;
|
||||
}
|
||||
nr = MIN2(count, nr - 1);
|
||||
nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
BEGIN_RING_NI(chan, RING_2D(SIFC_DATA), nr);
|
||||
OUT_RINGp (chan, src, nr);
|
||||
|
||||
src += nr;
|
||||
count -= nr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv50_m2mf_copy_linear(struct nv50_context *nv50,
|
||||
struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
|
||||
struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
|
||||
unsigned size)
|
||||
{
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
|
||||
BEGIN_RING(chan, RING_MF(LINEAR_IN), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_MF(LINEAR_OUT), 1);
|
||||
OUT_RING (chan, 1);
|
||||
|
||||
while (size) {
|
||||
unsigned bytes = MIN2(size, 1 << 17);
|
||||
|
||||
MARK_RING (chan, 11, 4);
|
||||
BEGIN_RING(chan, RING_MF(OFFSET_IN_HIGH), 2);
|
||||
OUT_RELOCh(chan, src, srcoff, srcdom | NOUVEAU_BO_RD);
|
||||
OUT_RELOCh(chan, dst, dstoff, dstdom | NOUVEAU_BO_WR);
|
||||
BEGIN_RING(chan, RING_MF_(NV04_M2MF_OFFSET_IN), 2);
|
||||
OUT_RELOCl(chan, src, srcoff, srcdom | NOUVEAU_BO_RD);
|
||||
OUT_RELOCl(chan, dst, dstoff, dstdom | NOUVEAU_BO_WR);
|
||||
BEGIN_RING(chan, RING_MF_(NV04_M2MF_LINE_LENGTH_IN), 4);
|
||||
OUT_RING (chan, bytes);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, (1 << 8) | (1 << 0));
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
srcoff += bytes;
|
||||
dstoff += bytes;
|
||||
size -= bytes;
|
||||
}
|
||||
}
|
||||
|
||||
struct pipe_transfer *
|
||||
nv50_miptree_transfer_new(struct pipe_context *pcontext,
|
||||
struct pipe_resource *pt,
|
||||
unsigned level,
|
||||
unsigned usage,
|
||||
const struct pipe_box *box)
|
||||
nv50_miptree_transfer_new(struct pipe_context *pctx,
|
||||
struct pipe_resource *res,
|
||||
unsigned level,
|
||||
unsigned usage,
|
||||
const struct pipe_box *box)
|
||||
{
|
||||
struct pipe_screen *pscreen = pcontext->screen;
|
||||
struct nouveau_device *dev = nouveau_screen(pscreen)->device;
|
||||
struct nv50_miptree *mt = nv50_miptree(pt);
|
||||
struct nv50_miptree_level *lvl = &mt->level[level];
|
||||
struct nv50_transfer *tx;
|
||||
unsigned nx, ny, image = 0, boxz = 0;
|
||||
int ret;
|
||||
struct nv50_context *nv50 = nv50_context(pctx);
|
||||
struct pipe_screen *pscreen = pctx->screen;
|
||||
struct nouveau_device *dev = nv50->screen->base.device;
|
||||
struct nv50_miptree *mt = nv50_miptree(res);
|
||||
struct nv50_miptree_level *lvl = &mt->level[level];
|
||||
struct nv50_transfer *tx;
|
||||
uint32_t size;
|
||||
uint32_t w, h, d, z, layer;
|
||||
int ret;
|
||||
|
||||
/* XXX can't unify these here? */
|
||||
if (pt->target == PIPE_TEXTURE_CUBE)
|
||||
image = box->z;
|
||||
else if (pt->target == PIPE_TEXTURE_3D)
|
||||
boxz = box->z;
|
||||
if (mt->layout_3d) {
|
||||
z = box->z;
|
||||
d = u_minify(res->depth0, level);
|
||||
layer = 0;
|
||||
} else {
|
||||
z = 0;
|
||||
d = 1;
|
||||
layer = box->z;
|
||||
}
|
||||
|
||||
tx = CALLOC_STRUCT(nv50_transfer);
|
||||
if (!tx)
|
||||
return NULL;
|
||||
tx = CALLOC_STRUCT(nv50_transfer);
|
||||
if (!tx)
|
||||
return NULL;
|
||||
|
||||
/* Don't handle 3D transfers yet.
|
||||
*/
|
||||
assert(box->depth == 1);
|
||||
pipe_resource_reference(&tx->base.resource, res);
|
||||
|
||||
tx->base.level = level;
|
||||
tx->base.usage = usage;
|
||||
tx->base.box = *box;
|
||||
|
||||
pipe_resource_reference(&tx->base.resource, pt);
|
||||
tx->base.level = level;
|
||||
tx->base.usage = usage;
|
||||
tx->base.box = *box;
|
||||
tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, level));
|
||||
tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, level));
|
||||
tx->base.stride = tx->nblocksx * util_format_get_blocksize(pt->format);
|
||||
tx->base.usage = usage;
|
||||
tx->nblocksx = util_format_get_nblocksx(res->format, box->width);
|
||||
tx->nblocksy = util_format_get_nblocksy(res->format, box->height);
|
||||
|
||||
tx->level_pitch = lvl->pitch;
|
||||
tx->level_width = u_minify(mt->base.base.width0, level);
|
||||
tx->level_height = u_minify(mt->base.base.height0, level);
|
||||
tx->level_depth = u_minify(mt->base.base.depth0, level);
|
||||
tx->level_offset = lvl->image_offset[image];
|
||||
tx->level_tiling = lvl->tile_mode;
|
||||
tx->level_z = boxz;
|
||||
tx->level_x = util_format_get_nblocksx(pt->format, box->x);
|
||||
tx->level_y = util_format_get_nblocksy(pt->format, box->y);
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
|
||||
tx->nblocksy * tx->base.stride, &tx->bo);
|
||||
if (ret) {
|
||||
FREE(tx);
|
||||
return NULL;
|
||||
}
|
||||
tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
|
||||
tx->base.layer_stride = tx->nblocksy * tx->base.stride;
|
||||
|
||||
if (usage & PIPE_TRANSFER_READ) {
|
||||
nx = util_format_get_nblocksx(pt->format, box->width);
|
||||
ny = util_format_get_nblocksy(pt->format, box->height);
|
||||
w = u_minify(res->width0, level);
|
||||
h = u_minify(res->height0, level);
|
||||
|
||||
nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset,
|
||||
tx->level_pitch, tx->level_tiling,
|
||||
box->x, box->y, boxz,
|
||||
tx->nblocksx, tx->nblocksy,
|
||||
tx->level_depth,
|
||||
tx->bo, 0,
|
||||
tx->base.stride, tx->bo->tile_mode,
|
||||
0, 0, 0,
|
||||
tx->nblocksx, tx->nblocksy, 1,
|
||||
util_format_get_blocksize(pt->format), nx, ny,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
|
||||
NOUVEAU_BO_GART);
|
||||
}
|
||||
tx->rect[0].cpp = tx->rect[1].cpp = util_format_get_blocksize(res->format);
|
||||
|
||||
return &tx->base;
|
||||
tx->rect[0].bo = mt->base.bo;
|
||||
tx->rect[0].base = lvl->offset + layer * mt->layer_stride;
|
||||
tx->rect[0].tile_mode = lvl->tile_mode;
|
||||
tx->rect[0].x = util_format_get_nblocksx(res->format, box->x);
|
||||
tx->rect[0].y = util_format_get_nblocksy(res->format, box->y);
|
||||
tx->rect[0].z = z;
|
||||
tx->rect[0].width = util_format_get_nblocksx(res->format, w);
|
||||
tx->rect[0].height = util_format_get_nblocksy(res->format, h);
|
||||
tx->rect[0].depth = d;
|
||||
tx->rect[0].pitch = lvl->pitch;
|
||||
tx->rect[0].domain = NOUVEAU_BO_VRAM;
|
||||
|
||||
size = tx->base.layer_stride;
|
||||
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
|
||||
size * tx->base.box.depth, &tx->rect[1].bo);
|
||||
if (ret) {
|
||||
FREE(tx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tx->rect[1].width = tx->nblocksx;
|
||||
tx->rect[1].height = tx->nblocksy;
|
||||
tx->rect[1].depth = 1;
|
||||
tx->rect[1].pitch = tx->base.stride;
|
||||
tx->rect[1].domain = NOUVEAU_BO_GART;
|
||||
|
||||
if (usage & PIPE_TRANSFER_READ) {
|
||||
unsigned base = tx->rect[0].base;
|
||||
unsigned i;
|
||||
for (i = 0; i < box->depth; ++i) {
|
||||
nv50_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0],
|
||||
tx->nblocksx, tx->nblocksy);
|
||||
if (mt->layout_3d)
|
||||
tx->rect[0].z++;
|
||||
else
|
||||
tx->rect[0].base += mt->layer_stride;
|
||||
tx->rect[1].base += size;
|
||||
}
|
||||
tx->rect[0].z = z;
|
||||
tx->rect[0].base = base;
|
||||
tx->rect[1].base = 0;
|
||||
}
|
||||
|
||||
return &tx->base;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_miptree_transfer_del(struct pipe_context *pcontext,
|
||||
struct pipe_transfer *ptx)
|
||||
nv50_miptree_transfer_del(struct pipe_context *pctx,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
|
||||
struct nv50_miptree *mt = nv50_miptree(ptx->resource);
|
||||
struct pipe_resource *pt = ptx->resource;
|
||||
struct pipe_screen *pscreen = pctx->screen;
|
||||
struct nv50_transfer *tx = (struct nv50_transfer *)transfer;
|
||||
struct nv50_miptree *mt = nv50_miptree(tx->base.resource);
|
||||
unsigned i;
|
||||
|
||||
unsigned nx = util_format_get_nblocksx(pt->format, tx->base.box.width);
|
||||
unsigned ny = util_format_get_nblocksy(pt->format, tx->base.box.height);
|
||||
if (tx->base.usage & PIPE_TRANSFER_WRITE) {
|
||||
for (i = 0; i < tx->base.box.depth; ++i) {
|
||||
nv50_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1],
|
||||
tx->nblocksx, tx->nblocksy);
|
||||
if (mt->layout_3d)
|
||||
tx->rect[0].z++;
|
||||
else
|
||||
tx->rect[0].base += mt->layer_stride;
|
||||
tx->rect[1].base += tx->nblocksy * tx->base.stride;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptx->usage & PIPE_TRANSFER_WRITE) {
|
||||
struct pipe_screen *pscreen = pcontext->screen;
|
||||
nouveau_bo_ref(NULL, &tx->rect[1].bo);
|
||||
pipe_resource_reference(&transfer->resource, NULL);
|
||||
|
||||
nv50_transfer_rect_m2mf(pscreen, tx->bo, 0,
|
||||
tx->base.stride, tx->bo->tile_mode,
|
||||
0, 0, 0,
|
||||
tx->nblocksx, tx->nblocksy, 1,
|
||||
mt->base.bo, tx->level_offset,
|
||||
tx->level_pitch, tx->level_tiling,
|
||||
tx->level_x, tx->level_y, tx->level_z,
|
||||
tx->nblocksx, tx->nblocksy,
|
||||
tx->level_depth,
|
||||
util_format_get_blocksize(pt->format), nx, ny,
|
||||
NOUVEAU_BO_GART, NOUVEAU_BO_VRAM |
|
||||
NOUVEAU_BO_GART);
|
||||
}
|
||||
|
||||
nouveau_bo_ref(NULL, &tx->bo);
|
||||
pipe_resource_reference(&ptx->resource, NULL);
|
||||
FREE(ptx);
|
||||
FREE(tx);
|
||||
}
|
||||
|
||||
void *
|
||||
nv50_miptree_transfer_map(struct pipe_context *pcontext,
|
||||
struct pipe_transfer *ptx)
|
||||
nv50_miptree_transfer_map(struct pipe_context *pctx,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
|
||||
unsigned flags = 0;
|
||||
int ret;
|
||||
struct nv50_transfer *tx = (struct nv50_transfer *)transfer;
|
||||
int ret;
|
||||
unsigned flags = 0;
|
||||
|
||||
if (tx->map_refcnt++)
|
||||
return tx->bo->map;
|
||||
if (tx->rect[1].bo->map)
|
||||
return tx->rect[1].bo->map;
|
||||
|
||||
if (ptx->usage & PIPE_TRANSFER_WRITE)
|
||||
flags |= NOUVEAU_BO_WR;
|
||||
if (ptx->usage & PIPE_TRANSFER_READ)
|
||||
flags |= NOUVEAU_BO_RD;
|
||||
if (transfer->usage & PIPE_TRANSFER_READ)
|
||||
flags = NOUVEAU_BO_RD;
|
||||
if (transfer->usage & PIPE_TRANSFER_WRITE)
|
||||
flags |= NOUVEAU_BO_WR;
|
||||
|
||||
ret = nouveau_bo_map(tx->bo, flags);
|
||||
if (ret) {
|
||||
tx->map_refcnt = 0;
|
||||
return NULL;
|
||||
}
|
||||
return tx->bo->map;
|
||||
ret = nouveau_bo_map(tx->rect[1].bo, flags);
|
||||
if (ret)
|
||||
return NULL;
|
||||
return tx->rect[1].bo->map;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_miptree_transfer_unmap(struct pipe_context *pcontext,
|
||||
struct pipe_transfer *ptx)
|
||||
nv50_miptree_transfer_unmap(struct pipe_context *pctx,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
|
||||
struct nv50_transfer *tx = (struct nv50_transfer *)transfer;
|
||||
|
||||
if (--tx->map_refcnt)
|
||||
return;
|
||||
nouveau_bo_unmap(tx->bo);
|
||||
nouveau_bo_unmap(tx->rect[1].bo);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nv50_upload_sifc(struct nv50_context *nv50,
|
||||
struct nouveau_bo *bo, unsigned dst_offset, unsigned reloc,
|
||||
unsigned dst_format, int dst_w, int dst_h, int dst_pitch,
|
||||
void *src, unsigned src_format, int src_pitch,
|
||||
int x, int y, int w, int h, int cpp)
|
||||
{
|
||||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
|
||||
unsigned line_dwords = (w * cpp + 3) / 4;
|
||||
|
||||
reloc |= NOUVEAU_BO_WR;
|
||||
|
||||
MARK_RING (chan, 32, 2); /* flush on lack of space or relocs */
|
||||
|
||||
if (nouveau_bo_tile_layout(bo)) {
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 5);
|
||||
OUT_RING (chan, dst_format);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, bo->tile_mode << 4);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
} else {
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 2);
|
||||
OUT_RING (chan, dst_format);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_PITCH, 1);
|
||||
OUT_RING (chan, dst_pitch);
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_DST_WIDTH, 4);
|
||||
OUT_RING (chan, dst_w);
|
||||
OUT_RING (chan, dst_h);
|
||||
OUT_RELOCh(chan, bo, dst_offset, reloc);
|
||||
OUT_RELOCl(chan, bo, dst_offset, reloc);
|
||||
|
||||
/* NV50_2D_OPERATION_SRCCOPY assumed already set */
|
||||
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_SIFC_BITMAP_ENABLE, 2);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, src_format);
|
||||
BEGIN_RING(chan, eng2d, NV50_2D_SIFC_WIDTH, 10);
|
||||
OUT_RING (chan, w);
|
||||
OUT_RING (chan, h);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, x);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, y);
|
||||
|
||||
while (h--) {
|
||||
const uint32_t *p = src;
|
||||
unsigned count = line_dwords;
|
||||
|
||||
while (count) {
|
||||
unsigned nr = MIN2(count, 1792);
|
||||
|
||||
if (AVAIL_RING(chan) <= nr) {
|
||||
FIRE_RING (chan);
|
||||
|
||||
BEGIN_RING(chan, eng2d,
|
||||
NV50_2D_DST_ADDRESS_HIGH, 2);
|
||||
OUT_RELOCh(chan, bo, dst_offset, reloc);
|
||||
OUT_RELOCl(chan, bo, dst_offset, reloc);
|
||||
}
|
||||
assert(AVAIL_RING(chan) > nr);
|
||||
|
||||
BEGIN_RING(chan, eng2d,
|
||||
NV50_2D_SIFC_DATA | (2 << 29), nr);
|
||||
OUT_RINGp (chan, p, nr);
|
||||
|
||||
p += nr;
|
||||
count -= nr;
|
||||
}
|
||||
|
||||
src = (uint8_t *) src + src_pitch;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,38 @@
|
|||
|
||||
#ifndef NV50_TRANSFER_H
|
||||
#define NV50_TRANSFER_H
|
||||
#ifndef __NV50_TRANSFER_H__
|
||||
#define __NV50_TRANSFER_H__
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
|
||||
struct pipe_transfer *
|
||||
nv50_miptree_transfer_new(struct pipe_context *pcontext,
|
||||
struct pipe_resource *pt,
|
||||
unsigned level,
|
||||
unsigned usage,
|
||||
const struct pipe_box *box);
|
||||
struct pipe_resource *pt,
|
||||
unsigned level,
|
||||
unsigned usage,
|
||||
const struct pipe_box *box);
|
||||
void
|
||||
nv50_miptree_transfer_del(struct pipe_context *pcontext,
|
||||
struct pipe_transfer *ptx);
|
||||
struct pipe_transfer *ptx);
|
||||
void *
|
||||
nv50_miptree_transfer_map(struct pipe_context *pcontext,
|
||||
struct pipe_transfer *ptx);
|
||||
struct pipe_transfer *ptx);
|
||||
void
|
||||
nv50_miptree_transfer_unmap(struct pipe_context *pcontext,
|
||||
struct pipe_transfer *ptx);
|
||||
struct pipe_transfer *ptx);
|
||||
|
||||
extern void
|
||||
nv50_upload_sifc(struct nv50_context *nv50,
|
||||
struct nouveau_bo *bo, unsigned dst_offset, unsigned reloc,
|
||||
unsigned dst_format, int dst_w, int dst_h, int dst_pitch,
|
||||
void *src, unsigned src_format, int src_pitch,
|
||||
int x, int y, int w, int h, int cpp);
|
||||
struct nv50_m2mf_rect {
|
||||
struct nouveau_bo *bo;
|
||||
uint32_t base;
|
||||
unsigned domain;
|
||||
uint32_t pitch;
|
||||
uint32_t width;
|
||||
uint32_t x;
|
||||
uint32_t height;
|
||||
uint32_t y;
|
||||
uint16_t depth;
|
||||
uint16_t z;
|
||||
uint16_t tile_mode;
|
||||
uint16_t cpp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
104
src/gallium/drivers/nv50/nv50_winsys.h
Normal file
104
src/gallium/drivers/nv50/nv50_winsys.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
|
||||
#ifndef __NV50_WINSYS_H__
|
||||
#define __NV50_WINSYS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#include "nouveau/nouveau_bo.h"
|
||||
#include "nouveau/nouveau_channel.h"
|
||||
#include "nouveau/nouveau_grobj.h"
|
||||
#include "nouveau/nouveau_device.h"
|
||||
#include "nouveau/nouveau_resource.h"
|
||||
#include "nouveau/nouveau_pushbuf.h"
|
||||
#include "nouveau/nouveau_reloc.h"
|
||||
|
||||
#include "nv50_resource.h" /* OUT_RESRC */
|
||||
|
||||
#ifndef NV04_PFIFO_MAX_PACKET_LEN
|
||||
#define NV04_PFIFO_MAX_PACKET_LEN 2047
|
||||
#endif
|
||||
|
||||
#define NV50_SUBCH_3D 5
|
||||
#define NV50_SUBCH_2D 6
|
||||
#define NV50_SUBCH_MF 7
|
||||
|
||||
#define NV50_MF_(n) NV50_M2MF_##n
|
||||
|
||||
#define RING_3D(n) ((NV50_SUBCH_3D << 13) | NV50_3D_##n)
|
||||
#define RING_2D(n) ((NV50_SUBCH_2D << 13) | NV50_2D_##n)
|
||||
#define RING_MF(n) ((NV50_SUBCH_MF << 13) | NV50_MF_(n))
|
||||
|
||||
#define RING_3D_(m) ((NV50_SUBCH_3D << 13) | (m))
|
||||
#define RING_2D_(m) ((NV50_SUBCH_2D << 13) | (m))
|
||||
#define RING_MF_(m) ((NV50_SUBCH_MF << 13) | (m))
|
||||
|
||||
#define RING_GR(gr, m) (((gr)->subc << 13) | (m))
|
||||
|
||||
int nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
|
||||
|
||||
static inline uint32_t
|
||||
nouveau_bo_tile_layout(struct nouveau_bo *bo)
|
||||
{
|
||||
return bo->tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
nouveau_bo_validate(struct nouveau_channel *chan,
|
||||
struct nouveau_bo *bo, unsigned flags)
|
||||
{
|
||||
nouveau_reloc_emit(chan, NULL, 0, NULL, bo, 0, 0, flags, 0, 0);
|
||||
}
|
||||
|
||||
/* incremental methods */
|
||||
static INLINE void
|
||||
BEGIN_RING(struct nouveau_channel *chan, uint32_t mthd, unsigned size)
|
||||
{
|
||||
WAIT_RING(chan, size + 1);
|
||||
OUT_RING (chan, (size << 18) | mthd);
|
||||
}
|
||||
|
||||
/* non-incremental */
|
||||
static INLINE void
|
||||
BEGIN_RING_NI(struct nouveau_channel *chan, uint32_t mthd, unsigned size)
|
||||
{
|
||||
WAIT_RING(chan, size + 1);
|
||||
OUT_RING (chan, (0x2 << 29) | (size << 18) | mthd);
|
||||
}
|
||||
|
||||
static INLINE int
|
||||
OUT_RESRCh(struct nouveau_channel *chan, struct nv50_resource *res,
|
||||
unsigned delta, unsigned flags)
|
||||
{
|
||||
return OUT_RELOCh(chan, res->bo, res->offset + delta, res->domain | flags);
|
||||
}
|
||||
|
||||
static INLINE int
|
||||
OUT_RESRCl(struct nouveau_channel *chan, struct nv50_resource *res,
|
||||
unsigned delta, unsigned flags)
|
||||
{
|
||||
if (flags & NOUVEAU_BO_WR)
|
||||
res->status |= NV50_BUFFER_STATUS_DIRTY;
|
||||
return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags);
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned s)
|
||||
{
|
||||
struct nouveau_subchannel *subc = &gr->channel->subc[s];
|
||||
|
||||
assert(s < 8);
|
||||
if (subc->gr) {
|
||||
assert(subc->gr->bound != NOUVEAU_GROBJ_BOUND_EXPLICIT);
|
||||
subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
|
||||
}
|
||||
subc->gr = gr;
|
||||
subc->gr->subc = s;
|
||||
subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
|
||||
|
||||
BEGIN_RING(chan, RING_GR(gr, 0x0000), 1);
|
||||
OUT_RING (chan, gr->handle);
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue