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:
Christoph Bumiller 2011-02-28 12:41:09 +01:00
parent d1dbbf7bf4
commit f80c03e187
41 changed files with 8740 additions and 6536 deletions

View file

@ -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)

View file

@ -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')

View 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 */

File diff suppressed because it is too large Load diff

View 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 */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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

View 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 */

View file

@ -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;
}

View 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);
}

View 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__

View file

@ -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 },

View file

@ -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);
}

View 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);
}
}

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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));
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View 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

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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

View 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 */

View file

@ -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:

View file

@ -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;
}
}

View file

@ -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

View 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