mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-06 00:10:20 +01:00
gallium/cell: Remove the driver.
Complicates Gallium3D development and doesn't seem to have active users. Signed-off-by: Kai Wasserbäch <kai@dev.carbon-project.org> Signed-off-by: José Fonseca <jfonseca@vmware.com>
This commit is contained in:
parent
09e67706e9
commit
ccd4d4367f
91 changed files with 9 additions and 21010 deletions
2
Makefile
2
Makefile
|
|
@ -112,8 +112,6 @@ linux \
|
|||
linux-i965 \
|
||||
linux-alpha \
|
||||
linux-alpha-static \
|
||||
linux-cell \
|
||||
linux-cell-debug \
|
||||
linux-debug \
|
||||
linux-dri \
|
||||
linux-dri-debug \
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ def AddOptions(opts):
|
|||
opts.Add(EnumOption('machine', 'use machine-specific assembly code', default_machine,
|
||||
allowed_values=('generic', 'ppc', 'x86', 'x86_64')))
|
||||
opts.Add(EnumOption('platform', 'target platform', host_platform,
|
||||
allowed_values=('linux', 'cell', 'windows', 'darwin', 'cygwin', 'sunos', 'freebsd8')))
|
||||
allowed_values=('linux', 'windows', 'darwin', 'cygwin', 'sunos', 'freebsd8')))
|
||||
opts.Add(BoolOption('embedded', 'embedded build', 'no'))
|
||||
opts.Add('toolchain', 'compiler toolchain', default_toolchain)
|
||||
opts.Add(BoolOption('gles', 'EXPERIMENTAL: enable OpenGL ES support', 'no'))
|
||||
|
|
|
|||
|
|
@ -1,71 +0,0 @@
|
|||
# linux-cell (non-debug build)
|
||||
|
||||
include $(TOP)/configs/linux
|
||||
|
||||
CONFIG_NAME = linux-cell
|
||||
|
||||
|
||||
# Omiting other gallium drivers:
|
||||
GALLIUM_DRIVERS_DIRS = cell softpipe trace rbug identity
|
||||
|
||||
|
||||
# Compiler and flags
|
||||
CC = ppu32-gcc
|
||||
CXX = ppu32-g++
|
||||
HOST_CC = gcc
|
||||
APP_CC = gcc
|
||||
APP_CXX = g++
|
||||
|
||||
OPT_FLAGS = -O3
|
||||
|
||||
# Cell SDK location
|
||||
## For SDK 2.1: (plus, remove -DSPU_MAIN_PARAM_LONG_LONG below)
|
||||
#SDK = /opt/ibm/cell-sdk/prototype/sysroot/usr
|
||||
## For SDK 3.0:
|
||||
SDK = /opt/cell/sdk/usr
|
||||
|
||||
|
||||
|
||||
COMMON_C_CPP_FLAGS = $(OPT_FLAGS) -Wall -Winline \
|
||||
-fPIC -m32 -mabi=altivec -maltivec \
|
||||
-I. -I$(SDK)/include \
|
||||
-DGALLIUM_CELL $(DEFINES)
|
||||
|
||||
CFLAGS = $(COMMON_C_CPP_FLAGS) -Wmissing-prototypes -std=c99
|
||||
|
||||
CXXFLAGS = $(COMMON_C_CPP_FLAGS)
|
||||
|
||||
|
||||
SRC_DIRS = glsl mapi/glapi mapi/vgapi mesa \
|
||||
gallium gallium/winsys gallium/targets glu
|
||||
|
||||
# Build no traditional Mesa drivers:
|
||||
DRIVER_DIRS =
|
||||
|
||||
|
||||
MKDEP_OPTIONS = -fdepend -Y
|
||||
|
||||
|
||||
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread \
|
||||
-L$(SDK)/lib -m32 -Wl,-m,elf32ppc -R$(SDK)/lib -lspe2
|
||||
|
||||
|
||||
CELL_SPU_LIB = $(TOP)/src/gallium/drivers/cell/spu/g3d_spu.a
|
||||
|
||||
|
||||
### SPU stuff
|
||||
|
||||
SPU_CC = spu-gcc
|
||||
|
||||
SPU_CFLAGS = $(OPT_FLAGS) -W -Wall -Winline -Wmissing-prototypes -Wno-main \
|
||||
-I. -I$(SDK)/spu/include -I$(TOP)/src/mesa/ $(INCLUDE_DIRS) \
|
||||
-DSPU_MAIN_PARAM_LONG_LONG \
|
||||
-include spu_intrinsics.h
|
||||
|
||||
SPU_LFLAGS = -L$(SDK)/spu/lib -Wl,-N -lmisc -lm
|
||||
|
||||
SPU_AR = ppu-ar
|
||||
SPU_AR_FLAGS = -qcs
|
||||
|
||||
SPU_EMBED = ppu32-embedspu
|
||||
SPU_EMBED_FLAGS = -m32
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# linux-cell-debug
|
||||
|
||||
include $(TOP)/configs/linux-cell
|
||||
|
||||
# just override name and OPT_FLAGS here:
|
||||
|
||||
CONFIG_NAME = linux-cell-debug
|
||||
|
||||
OPT_FLAGS = -g -DDEBUG
|
||||
|
||||
138
docs/cell.html
138
docs/cell.html
|
|
@ -1,138 +0,0 @@
|
|||
<HTML>
|
||||
|
||||
<TITLE>Cell Driver</TITLE>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="mesa.css"></head>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1>Mesa/Gallium Cell Driver</H1>
|
||||
|
||||
<p>
|
||||
The Mesa
|
||||
<a href="http://en.wikipedia.org/wiki/Cell_%28microprocessor%29" target="_parent">Cell</a>
|
||||
driver is part of the
|
||||
<a href="http://wiki.freedesktop.org/wiki/Software/gallium" target="_parent">Gallium3D</a>
|
||||
architecture.
|
||||
Tungsten Graphics did the original implementation of the Cell driver.
|
||||
</p>
|
||||
|
||||
|
||||
<H2>Source Code</H2>
|
||||
|
||||
<p>
|
||||
The latest Cell driver source code is on the master branch of the Mesa
|
||||
git repository.
|
||||
</p>
|
||||
<p>
|
||||
To build the driver you'll need the IBM Cell SDK (version 2.1 or 3.0).
|
||||
To use the driver you'll need a Cell system, such as a PS3 running Linux,
|
||||
or the Cell Simulator (untested, though).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If using Cell SDK 2.1, see the configs/linux-cell file for some
|
||||
special changes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To compile the code, run <code>make linux-cell</code>.
|
||||
Or to build in debug mode, run <code>make linux-cell-debug</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To use the library, make sure your current directory is the top of the
|
||||
Mesa tree, then set <code>LD_LIBRARY_PATH</code> like this:
|
||||
<pre>
|
||||
export LD_LIBRARY_PATH=$PWD/lib/gallium:$PWD/lib/
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Verify that the Cell driver is being used by running
|
||||
<code>progs/xdemos/glxinfo</code> and looking for:
|
||||
<pre>
|
||||
OpenGL renderer string: Gallium 0.3, Cell on Xlib
|
||||
</pre>
|
||||
|
||||
|
||||
<H2>Driver Implementation Summary</H2>
|
||||
|
||||
<p>
|
||||
Rasterization is parallelized across the SPUs in a tiled-based manner.
|
||||
Batches of transformed triangles are sent to the SPUs (actually, pulled by from
|
||||
main memory by the SPUs).
|
||||
Each SPU loops over a set of 32x32-pixel screen tiles, rendering the triangles
|
||||
into each tile.
|
||||
Because of the limited SPU memory, framebuffer tiles are paged in/out of
|
||||
SPU local store as needed.
|
||||
Similarly, textures are tiled and brought into local store as needed.
|
||||
</p>
|
||||
|
||||
|
||||
<H2>Status</H2>
|
||||
|
||||
<p>
|
||||
As of October 2008, the driver runs quite a few OpenGL demos.
|
||||
Features that work include:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Point/line/triangle rendering, glDrawPixels
|
||||
<li>2D, NPOT and cube texture maps with nearest/linear/mipmap filtering
|
||||
<li>Dynamic SPU code generation for fragment shaders, but not complete
|
||||
<li>Dynamic SPU code generation for fragment ops (blend, Z-test, etc), but not complete
|
||||
<li>Dynamic PPU/PPC code generation for vertex shaders, but not complete
|
||||
</ul>
|
||||
<p>
|
||||
Performance has recently improved with the addition of PPC code generation
|
||||
for vertex shaders, but the code quality isn't too great yet.
|
||||
</p>
|
||||
<p>
|
||||
Another bottleneck is SwapBuffers. It may be the limiting factor for
|
||||
many simple GL tests.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<H2>Debug Options</H2>
|
||||
|
||||
<p>
|
||||
The CELL_DEBUG env var can be set to a comma-separated list of one or
|
||||
more of the following debug options:
|
||||
</p>
|
||||
<ul>
|
||||
<li><b>checker</b> - use a different background clear color for each SPU.
|
||||
This lets you see which SPU is rendering which screen tiles.
|
||||
<li><b>sync</b> - wait/synchronize after each DMA transfer
|
||||
<li><b>asm</b> - print generated SPU assembly code to stdout
|
||||
<li><b>fragops</b> - emit fragment ops debug messages
|
||||
<li><b>fragopfallback</b> - don't use codegen for fragment ops
|
||||
<li><b>cmd</b> - print SPU commands as their received
|
||||
<li><b>cache</b> - print texture cache statistics when program exits
|
||||
</ul>
|
||||
<p>
|
||||
Note that some of these options may only work for linux-cell-debug builds.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If the GALLIUM_NOPPC env var is set, PPC code generation will not be used
|
||||
and vertex shaders will be run with the TGSI interpreter.
|
||||
</p>
|
||||
<p>
|
||||
If the GALLIUM_NOCELL env var is set, the softpipe driver will be used
|
||||
intead of the Cell driver.
|
||||
This is useful for comparison/validation.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<H2>Contributing</H2>
|
||||
|
||||
<p>
|
||||
If you're interested in contributing to the effort, familiarize yourself
|
||||
with the code, join the <a href="lists.html">mesa3d-dev mailing list</a>,
|
||||
and describe what you'd like to do.
|
||||
</p>
|
||||
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
|
@ -78,8 +78,7 @@ a:visited {
|
|||
<li><a href="devinfo.html" target="MainFrame">Development Notes</a>
|
||||
<li><a href="sourcedocs.html" target="MainFrame">Source Documentation</a>
|
||||
<li><a href="subset.html" target="MainFrame">Mesa Subset Driver</a>
|
||||
<LI><A HREF="dispatch.html" target="MainFrame">GL Dispatch</A>
|
||||
<li><a href="cell.html" target="MainFrame">Cell Driver</A>
|
||||
<li><a HREF="dispatch.html" target="MainFrame">GL Dispatch</a>
|
||||
</ul>
|
||||
|
||||
<b>Links</b>
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ This is a bug-fix release.
|
|||
<h2>January 24, 2008</h2>
|
||||
|
||||
<p>
|
||||
Added a new page describing the <a href="cell.html">Mesa Cell driver</a>.
|
||||
Added a new page describing the Mesa Cell driver.
|
||||
</p>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ tbd
|
|||
by the gallium drivers for this hardware.</li>
|
||||
<li>Removed the i965g driver, which was broken and with nobody in sight to fix
|
||||
the situation</li>
|
||||
<li>Removed the Gallium cell driver, it was just a burden on Gallium
|
||||
development and nobody seems to use it.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ baa7a1e850b6e39bae58868fd0684004 MesaGLUT-7.5.tar.bz2
|
|||
<ul>
|
||||
<li>softpipe - a software/reference driver
|
||||
<li>i915 - Intel 915/945 driver
|
||||
<li><a href="cell.html">Cell</a> - IBM/Sony/Toshiba Cell processor driver
|
||||
<li>Cell - IBM/Sony/Toshiba Cell processor driver
|
||||
<li>nouveau (for NVIDIA GPUs) and R300 for (AMD/ATI R300).
|
||||
<b>PLEASE NOTE: these drivers are incomplete and still under development.
|
||||
It's probably NOT worthwhile to report any bugs unless you have patches.
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ each directory.
|
|||
interfaces
|
||||
<li><b>drivers</b> - Gallium3D device drivers
|
||||
<ul>
|
||||
<li><b>cell</b> - Driver for Cell processor.
|
||||
<li><b>i915</b> - Driver for Intel i915/i945.
|
||||
<li><b>llvmpipe</b> - Software driver using LLVM for runtime code generation.
|
||||
<li><b>nv*</b> - Drivers for NVIDIA GPUs.
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
- Pipe drivers:
|
||||
- \ref softpipe
|
||||
- \ref i915g
|
||||
- Cell driver (cell_context.h, cell_winsys.h)
|
||||
- \ref failover
|
||||
|
||||
- Winsys drivers:
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ C_SOURCES := \
|
|||
rtasm/rtasm_cpu.c \
|
||||
rtasm/rtasm_execmem.c \
|
||||
rtasm/rtasm_ppc.c \
|
||||
rtasm/rtasm_ppc_spe.c \
|
||||
rtasm/rtasm_x86sse.c \
|
||||
tgsi/tgsi_build.c \
|
||||
tgsi/tgsi_dump.c \
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,433 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright IBM Corporation 2008
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Real-time assembly generation interface for Cell B.E. SPEs.
|
||||
* For details, see /opt/cell/sdk/docs/arch/SPU_ISA_v1.2_27Jan2007_pub.pdf
|
||||
*
|
||||
* \author Ian Romanick <idr@us.ibm.com>
|
||||
* \author Brian Paul
|
||||
*/
|
||||
|
||||
#ifndef RTASM_PPC_SPE_H
|
||||
#define RTASM_PPC_SPE_H
|
||||
|
||||
/** 4 bytes per instruction */
|
||||
#define SPE_INST_SIZE 4
|
||||
|
||||
/** number of general-purpose SIMD registers */
|
||||
#define SPE_NUM_REGS 128
|
||||
|
||||
/** Return Address register (aka $lr / Link Register) */
|
||||
#define SPE_REG_RA 0
|
||||
|
||||
/** Stack Pointer register (aka $sp) */
|
||||
#define SPE_REG_SP 1
|
||||
|
||||
|
||||
struct spe_function
|
||||
{
|
||||
uint32_t *store; /**< instruction buffer */
|
||||
uint num_inst;
|
||||
uint max_inst;
|
||||
|
||||
/**
|
||||
* The "set count" reflects the number of nested register sets
|
||||
* are allowed. In the unlikely case that we exceed the set count,
|
||||
* register allocation will start to be confused, which is critical
|
||||
* enough that we check for it.
|
||||
*/
|
||||
unsigned char set_count;
|
||||
|
||||
/**
|
||||
* Flags for used and unused registers. Each byte corresponds to a
|
||||
* register; a 0 in that byte means that the register is available.
|
||||
* A value of 1 means that the register was allocated in the current
|
||||
* register set. Any other value N means that the register was allocated
|
||||
* N register sets ago.
|
||||
*
|
||||
* \sa
|
||||
* spe_allocate_register, spe_allocate_available_register,
|
||||
* spe_allocate_register_set, spe_release_register_set, spe_release_register,
|
||||
*/
|
||||
unsigned char regs[SPE_NUM_REGS];
|
||||
|
||||
boolean print; /**< print/dump instructions as they're emitted? */
|
||||
int indent; /**< number of spaces to indent */
|
||||
};
|
||||
|
||||
|
||||
extern void spe_init_func(struct spe_function *p, uint code_size);
|
||||
extern void spe_release_func(struct spe_function *p);
|
||||
extern uint spe_code_size(const struct spe_function *p);
|
||||
|
||||
extern int spe_allocate_available_register(struct spe_function *p);
|
||||
extern int spe_allocate_register(struct spe_function *p, int reg);
|
||||
extern void spe_release_register(struct spe_function *p, int reg);
|
||||
extern void spe_allocate_register_set(struct spe_function *p);
|
||||
extern void spe_release_register_set(struct spe_function *p);
|
||||
|
||||
extern uint spe_get_registers_used(const struct spe_function *p, ubyte used[]);
|
||||
|
||||
extern void spe_print_code(struct spe_function *p, boolean enable);
|
||||
extern void spe_indent(struct spe_function *p, int spaces);
|
||||
extern void spe_comment(struct spe_function *p, int rel_indent, const char *s);
|
||||
|
||||
|
||||
#endif /* RTASM_PPC_SPE_H */
|
||||
|
||||
#ifndef EMIT
|
||||
#define EMIT(_name, _op) \
|
||||
extern void _name (struct spe_function *p);
|
||||
#define EMIT_(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT);
|
||||
#define EMIT_R(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT, int rA);
|
||||
#define EMIT_RR(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT, int rA, int rB);
|
||||
#define EMIT_RRR(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT, int rA, int rB, int rC);
|
||||
#define EMIT_RI7(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT, int rA, int imm);
|
||||
#define EMIT_RI8(_name, _op, bias) \
|
||||
extern void _name (struct spe_function *p, int rT, int rA, int imm);
|
||||
#define EMIT_RI10(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT, int rA, int imm);
|
||||
#define EMIT_RI10s(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT, int rA, int imm);
|
||||
#define EMIT_RI16(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT, int imm);
|
||||
#define EMIT_RI18(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int rT, int imm);
|
||||
#define EMIT_I16(_name, _op) \
|
||||
extern void _name (struct spe_function *p, int imm);
|
||||
#define UNDEF_EMIT_MACROS
|
||||
#endif /* EMIT */
|
||||
|
||||
|
||||
/* Memory load / store instructions
|
||||
*/
|
||||
EMIT_RR (spe_lqx, 0x1c4)
|
||||
EMIT_RI16(spe_lqa, 0x061)
|
||||
EMIT_RI16(spe_lqr, 0x067)
|
||||
EMIT_RR (spe_stqx, 0x144)
|
||||
EMIT_RI16(spe_stqa, 0x041)
|
||||
EMIT_RI16(spe_stqr, 0x047)
|
||||
EMIT_RI7 (spe_cbd, 0x1f4)
|
||||
EMIT_RR (spe_cbx, 0x1d4)
|
||||
EMIT_RI7 (spe_chd, 0x1f5)
|
||||
EMIT_RI7 (spe_chx, 0x1d5)
|
||||
EMIT_RI7 (spe_cwd, 0x1f6)
|
||||
EMIT_RI7 (spe_cwx, 0x1d6)
|
||||
EMIT_RI7 (spe_cdd, 0x1f7)
|
||||
EMIT_RI7 (spe_cdx, 0x1d7)
|
||||
|
||||
|
||||
/* Constant formation instructions
|
||||
*/
|
||||
EMIT_RI16(spe_ilh, 0x083)
|
||||
EMIT_RI16(spe_ilhu, 0x082)
|
||||
EMIT_RI16(spe_il, 0x081)
|
||||
EMIT_RI18(spe_ila, 0x021)
|
||||
EMIT_RI16(spe_iohl, 0x0c1)
|
||||
EMIT_RI16(spe_fsmbi, 0x065)
|
||||
|
||||
|
||||
|
||||
/* Integer and logical instructions
|
||||
*/
|
||||
EMIT_RR (spe_ah, 0x0c8)
|
||||
EMIT_RI10(spe_ahi, 0x01d)
|
||||
EMIT_RR (spe_a, 0x0c0)
|
||||
EMIT_RI10s(spe_ai, 0x01c)
|
||||
EMIT_RR (spe_sfh, 0x048)
|
||||
EMIT_RI10(spe_sfhi, 0x00d)
|
||||
EMIT_RR (spe_sf, 0x040)
|
||||
EMIT_RI10(spe_sfi, 0x00c)
|
||||
EMIT_RR (spe_addx, 0x340)
|
||||
EMIT_RR (spe_cg, 0x0c2)
|
||||
EMIT_RR (spe_cgx, 0x342)
|
||||
EMIT_RR (spe_sfx, 0x341)
|
||||
EMIT_RR (spe_bg, 0x042)
|
||||
EMIT_RR (spe_bgx, 0x343)
|
||||
EMIT_RR (spe_mpy, 0x3c4)
|
||||
EMIT_RR (spe_mpyu, 0x3cc)
|
||||
EMIT_RI10(spe_mpyi, 0x074)
|
||||
EMIT_RI10(spe_mpyui, 0x075)
|
||||
EMIT_RRR (spe_mpya, 0x00c)
|
||||
EMIT_RR (spe_mpyh, 0x3c5)
|
||||
EMIT_RR (spe_mpys, 0x3c7)
|
||||
EMIT_RR (spe_mpyhh, 0x3c6)
|
||||
EMIT_RR (spe_mpyhha, 0x346)
|
||||
EMIT_RR (spe_mpyhhu, 0x3ce)
|
||||
EMIT_RR (spe_mpyhhau, 0x34e)
|
||||
EMIT_R (spe_clz, 0x2a5)
|
||||
EMIT_R (spe_cntb, 0x2b4)
|
||||
EMIT_R (spe_fsmb, 0x1b6)
|
||||
EMIT_R (spe_fsmh, 0x1b5)
|
||||
EMIT_R (spe_fsm, 0x1b4)
|
||||
EMIT_R (spe_gbb, 0x1b2)
|
||||
EMIT_R (spe_gbh, 0x1b1)
|
||||
EMIT_R (spe_gb, 0x1b0)
|
||||
EMIT_RR (spe_avgb, 0x0d3)
|
||||
EMIT_RR (spe_absdb, 0x053)
|
||||
EMIT_RR (spe_sumb, 0x253)
|
||||
EMIT_R (spe_xsbh, 0x2b6)
|
||||
EMIT_R (spe_xshw, 0x2ae)
|
||||
EMIT_R (spe_xswd, 0x2a6)
|
||||
EMIT_RR (spe_and, 0x0c1)
|
||||
EMIT_RR (spe_andc, 0x2c1)
|
||||
EMIT_RI10s(spe_andbi, 0x016)
|
||||
EMIT_RI10s(spe_andhi, 0x015)
|
||||
EMIT_RI10s(spe_andi, 0x014)
|
||||
EMIT_RR (spe_or, 0x041)
|
||||
EMIT_RR (spe_orc, 0x2c9)
|
||||
EMIT_RI10s(spe_orbi, 0x006)
|
||||
EMIT_RI10s(spe_orhi, 0x005)
|
||||
EMIT_RI10s(spe_ori, 0x004)
|
||||
EMIT_R (spe_orx, 0x1f0)
|
||||
EMIT_RR (spe_xor, 0x241)
|
||||
EMIT_RI10s(spe_xorbi, 0x046)
|
||||
EMIT_RI10s(spe_xorhi, 0x045)
|
||||
EMIT_RI10s(spe_xori, 0x044)
|
||||
EMIT_RR (spe_nand, 0x0c9)
|
||||
EMIT_RR (spe_nor, 0x049)
|
||||
EMIT_RR (spe_eqv, 0x249)
|
||||
EMIT_RRR (spe_selb, 0x008)
|
||||
EMIT_RRR (spe_shufb, 0x00b)
|
||||
|
||||
|
||||
/* Shift and rotate instructions
|
||||
*/
|
||||
EMIT_RR (spe_shlh, 0x05f)
|
||||
EMIT_RI7 (spe_shlhi, 0x07f)
|
||||
EMIT_RR (spe_shl, 0x05b)
|
||||
EMIT_RI7 (spe_shli, 0x07b)
|
||||
EMIT_RR (spe_shlqbi, 0x1db)
|
||||
EMIT_RI7 (spe_shlqbii, 0x1fb)
|
||||
EMIT_RR (spe_shlqby, 0x1df)
|
||||
EMIT_RI7 (spe_shlqbyi, 0x1ff)
|
||||
EMIT_RR (spe_shlqbybi, 0x1cf)
|
||||
EMIT_RR (spe_roth, 0x05c)
|
||||
EMIT_RI7 (spe_rothi, 0x07c)
|
||||
EMIT_RR (spe_rot, 0x058)
|
||||
EMIT_RI7 (spe_roti, 0x078)
|
||||
EMIT_RR (spe_rotqby, 0x1dc)
|
||||
EMIT_RI7 (spe_rotqbyi, 0x1fc)
|
||||
EMIT_RR (spe_rotqbybi, 0x1cc)
|
||||
EMIT_RR (spe_rotqbi, 0x1d8)
|
||||
EMIT_RI7 (spe_rotqbii, 0x1f8)
|
||||
EMIT_RR (spe_rothm, 0x05d)
|
||||
EMIT_RI7 (spe_rothmi, 0x07d)
|
||||
EMIT_RR (spe_rotm, 0x059)
|
||||
EMIT_RI7 (spe_rotmi, 0x079)
|
||||
EMIT_RR (spe_rotqmby, 0x1dd)
|
||||
EMIT_RI7 (spe_rotqmbyi, 0x1fd)
|
||||
EMIT_RR (spe_rotqmbybi, 0x1cd)
|
||||
EMIT_RR (spe_rotqmbi, 0x1c9)
|
||||
EMIT_RI7 (spe_rotqmbii, 0x1f9)
|
||||
EMIT_RR (spe_rotmah, 0x05e)
|
||||
EMIT_RI7 (spe_rotmahi, 0x07e)
|
||||
EMIT_RR (spe_rotma, 0x05a)
|
||||
EMIT_RI7 (spe_rotmai, 0x07a)
|
||||
|
||||
|
||||
/* Compare, branch, and halt instructions
|
||||
*/
|
||||
EMIT_RR (spe_heq, 0x3d8)
|
||||
EMIT_RI10(spe_heqi, 0x07f)
|
||||
EMIT_RR (spe_hgt, 0x258)
|
||||
EMIT_RI10(spe_hgti, 0x04f)
|
||||
EMIT_RR (spe_hlgt, 0x2d8)
|
||||
EMIT_RI10(spe_hlgti, 0x05f)
|
||||
EMIT_RR (spe_ceqb, 0x3d0)
|
||||
EMIT_RI10(spe_ceqbi, 0x07e)
|
||||
EMIT_RR (spe_ceqh, 0x3c8)
|
||||
EMIT_RI10(spe_ceqhi, 0x07d)
|
||||
EMIT_RR (spe_ceq, 0x3c0)
|
||||
EMIT_RI10(spe_ceqi, 0x07c)
|
||||
EMIT_RR (spe_cgtb, 0x250)
|
||||
EMIT_RI10(spe_cgtbi, 0x04e)
|
||||
EMIT_RR (spe_cgth, 0x248)
|
||||
EMIT_RI10(spe_cgthi, 0x04d)
|
||||
EMIT_RR (spe_cgt, 0x240)
|
||||
EMIT_RI10(spe_cgti, 0x04c)
|
||||
EMIT_RR (spe_clgtb, 0x2d0)
|
||||
EMIT_RI10(spe_clgtbi, 0x05e)
|
||||
EMIT_RR (spe_clgth, 0x2c8)
|
||||
EMIT_RI10(spe_clgthi, 0x05d)
|
||||
EMIT_RR (spe_clgt, 0x2c0)
|
||||
EMIT_RI10(spe_clgti, 0x05c)
|
||||
EMIT_I16 (spe_br, 0x064)
|
||||
EMIT_I16 (spe_bra, 0x060)
|
||||
EMIT_RI16(spe_brsl, 0x066)
|
||||
EMIT_RI16(spe_brasl, 0x062)
|
||||
EMIT_RI16(spe_brnz, 0x042)
|
||||
EMIT_RI16(spe_brz, 0x040)
|
||||
EMIT_RI16(spe_brhnz, 0x046)
|
||||
EMIT_RI16(spe_brhz, 0x044)
|
||||
|
||||
/* Control instructions
|
||||
*/
|
||||
EMIT (spe_lnop, 0x001)
|
||||
|
||||
extern void
|
||||
spe_lqd(struct spe_function *p, int rT, int rA, int offset);
|
||||
|
||||
extern void
|
||||
spe_stqd(struct spe_function *p, int rT, int rA, int offset);
|
||||
|
||||
extern void spe_bi(struct spe_function *p, int rA, int d, int e);
|
||||
extern void spe_iret(struct spe_function *p, int rA, int d, int e);
|
||||
extern void spe_bisled(struct spe_function *p, int rT, int rA,
|
||||
int d, int e);
|
||||
extern void spe_bisl(struct spe_function *p, int rT, int rA,
|
||||
int d, int e);
|
||||
extern void spe_biz(struct spe_function *p, int rT, int rA,
|
||||
int d, int e);
|
||||
extern void spe_binz(struct spe_function *p, int rT, int rA,
|
||||
int d, int e);
|
||||
extern void spe_bihz(struct spe_function *p, int rT, int rA,
|
||||
int d, int e);
|
||||
extern void spe_bihnz(struct spe_function *p, int rT, int rA,
|
||||
int d, int e);
|
||||
|
||||
|
||||
/** Load/splat immediate float into rT. */
|
||||
extern void
|
||||
spe_load_float(struct spe_function *p, int rT, float x);
|
||||
|
||||
/** Load/splat immediate int into rT. */
|
||||
extern void
|
||||
spe_load_int(struct spe_function *p, int rT, int i);
|
||||
|
||||
/** Load/splat immediate unsigned int into rT. */
|
||||
extern void
|
||||
spe_load_uint(struct spe_function *p, int rT, uint ui);
|
||||
|
||||
/** And immediate value into rT. */
|
||||
extern void
|
||||
spe_and_uint(struct spe_function *p, int rT, int rA, uint ui);
|
||||
|
||||
/** Xor immediate value into rT. */
|
||||
extern void
|
||||
spe_xor_uint(struct spe_function *p, int rT, int rA, uint ui);
|
||||
|
||||
/** Compare equal with immediate value. */
|
||||
extern void
|
||||
spe_compare_equal_uint(struct spe_function *p, int rT, int rA, uint ui);
|
||||
|
||||
/** Compare greater with immediate value. */
|
||||
extern void
|
||||
spe_compare_greater_uint(struct spe_function *p, int rT, int rA, uint ui);
|
||||
|
||||
/** Replicate word 0 of rA across rT. */
|
||||
extern void
|
||||
spe_splat(struct spe_function *p, int rT, int rA);
|
||||
|
||||
/** rT = complement_all_bits(rA). */
|
||||
extern void
|
||||
spe_complement(struct spe_function *p, int rT, int rA);
|
||||
|
||||
/** rT = rA. */
|
||||
extern void
|
||||
spe_move(struct spe_function *p, int rT, int rA);
|
||||
|
||||
/** rT = {0,0,0,0}. */
|
||||
extern void
|
||||
spe_zero(struct spe_function *p, int rT);
|
||||
|
||||
/** rT = splat(rA, word) */
|
||||
extern void
|
||||
spe_splat_word(struct spe_function *p, int rT, int rA, int word);
|
||||
|
||||
/** rT = float min(rA, rB) */
|
||||
extern void
|
||||
spe_float_min(struct spe_function *p, int rT, int rA, int rB);
|
||||
|
||||
/** rT = float max(rA, rB) */
|
||||
extern void
|
||||
spe_float_max(struct spe_function *p, int rT, int rA, int rB);
|
||||
|
||||
|
||||
/* Floating-point instructions
|
||||
*/
|
||||
EMIT_RR (spe_fa, 0x2c4)
|
||||
EMIT_RR (spe_dfa, 0x2cc)
|
||||
EMIT_RR (spe_fs, 0x2c5)
|
||||
EMIT_RR (spe_dfs, 0x2cd)
|
||||
EMIT_RR (spe_fm, 0x2c6)
|
||||
EMIT_RR (spe_dfm, 0x2ce)
|
||||
EMIT_RRR (spe_fma, 0x00e)
|
||||
EMIT_RR (spe_dfma, 0x35c)
|
||||
EMIT_RRR (spe_fnms, 0x00d)
|
||||
EMIT_RR (spe_dfnms, 0x35e)
|
||||
EMIT_RRR (spe_fms, 0x00f)
|
||||
EMIT_RR (spe_dfms, 0x35d)
|
||||
EMIT_RR (spe_dfnma, 0x35f)
|
||||
EMIT_R (spe_frest, 0x1b8)
|
||||
EMIT_R (spe_frsqest, 0x1b9)
|
||||
EMIT_RR (spe_fi, 0x3d4)
|
||||
EMIT_RI8 (spe_csflt, 0x1da, 155)
|
||||
EMIT_RI8 (spe_cflts, 0x1d8, 173)
|
||||
EMIT_RI8 (spe_cuflt, 0x1db, 155)
|
||||
EMIT_RI8 (spe_cfltu, 0x1d9, 173)
|
||||
EMIT_R (spe_frds, 0x3b9)
|
||||
EMIT_R (spe_fesd, 0x3b8)
|
||||
EMIT_RR (spe_dfceq, 0x3c3)
|
||||
EMIT_RR (spe_dfcmeq, 0x3cb)
|
||||
EMIT_RR (spe_dfcgt, 0x2c3)
|
||||
EMIT_RR (spe_dfcmgt, 0x2cb)
|
||||
EMIT_RI7 (spe_dftsv, 0x3bf)
|
||||
EMIT_RR (spe_fceq, 0x3c2)
|
||||
EMIT_RR (spe_fcmeq, 0x3ca)
|
||||
EMIT_RR (spe_fcgt, 0x2c2)
|
||||
EMIT_RR (spe_fcmgt, 0x2ca)
|
||||
EMIT_R (spe_fscrwr, 0x3ba)
|
||||
EMIT_ (spe_fscrrd, 0x398)
|
||||
|
||||
|
||||
/* Channel instructions
|
||||
*/
|
||||
EMIT_R (spe_rdch, 0x00d)
|
||||
EMIT_R (spe_rdchcnt, 0x00f)
|
||||
EMIT_R (spe_wrch, 0x10d)
|
||||
|
||||
|
||||
#ifdef UNDEF_EMIT_MACROS
|
||||
#undef EMIT
|
||||
#undef EMIT_
|
||||
#undef EMIT_R
|
||||
#undef EMIT_RR
|
||||
#undef EMIT_RRR
|
||||
#undef EMIT_RI7
|
||||
#undef EMIT_RI8
|
||||
#undef EMIT_RI10
|
||||
#undef EMIT_RI10s
|
||||
#undef EMIT_RI16
|
||||
#undef EMIT_RI18
|
||||
#undef EMIT_I16
|
||||
#undef UNDEF_EMIT_MACROS
|
||||
#endif /* EMIT_ */
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
|
||||
/* Helper function to choose and instantiate one of the software rasterizers:
|
||||
* cell, llvmpipe, softpipe.
|
||||
* llvmpipe, softpipe.
|
||||
*/
|
||||
|
||||
#ifdef GALLIUM_SOFTPIPE
|
||||
|
|
@ -19,21 +19,12 @@
|
|||
#include "llvmpipe/lp_public.h"
|
||||
#endif
|
||||
|
||||
#ifdef GALLIUM_CELL
|
||||
#include "cell/ppu/cell_public.h"
|
||||
#endif
|
||||
|
||||
|
||||
static INLINE struct pipe_screen *
|
||||
sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
|
||||
{
|
||||
struct pipe_screen *screen = NULL;
|
||||
|
||||
#if defined(GALLIUM_CELL)
|
||||
if (screen == NULL && strcmp(driver, "cell") == 0)
|
||||
screen = cell_create_screen(winsys);
|
||||
#endif
|
||||
|
||||
#if defined(GALLIUM_LLVMPIPE)
|
||||
if (screen == NULL && strcmp(driver, "llvmpipe") == 0)
|
||||
screen = llvmpipe_create_screen(winsys);
|
||||
|
|
@ -54,9 +45,7 @@ sw_screen_create(struct sw_winsys *winsys)
|
|||
const char *default_driver;
|
||||
const char *driver;
|
||||
|
||||
#if defined(GALLIUM_CELL)
|
||||
default_driver = "cell";
|
||||
#elif defined(GALLIUM_LLVMPIPE)
|
||||
#if defined(GALLIUM_LLVMPIPE)
|
||||
default_driver = "llvmpipe";
|
||||
#elif defined(GALLIUM_SOFTPIPE)
|
||||
default_driver = "softpipe";
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
# Cell Gallium driver Makefile
|
||||
|
||||
|
||||
default:
|
||||
( cd spu ; make )
|
||||
( cd ppu ; make )
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
( cd spu ; make clean )
|
||||
( cd ppu ; make clean )
|
||||
|
|
@ -1,377 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Types and tokens which are common to the SPU and PPU code.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CELL_COMMON_H
|
||||
#define CELL_COMMON_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_format.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/** The standard assert macro doesn't seem to work reliably */
|
||||
#define ASSERT(x) \
|
||||
if (!(x)) { \
|
||||
ubyte *p = NULL; \
|
||||
fprintf(stderr, "%s:%d: %s(): assertion %s failed.\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, #x); \
|
||||
*p = 0; \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
|
||||
#define JOIN(x, y) JOIN_AGAIN(x, y)
|
||||
#define JOIN_AGAIN(x, y) x ## y
|
||||
|
||||
#define STATIC_ASSERT(e) \
|
||||
{typedef char JOIN(assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1];}
|
||||
|
||||
|
||||
|
||||
/** for sanity checking */
|
||||
#define ASSERT_ALIGN16(ptr) \
|
||||
ASSERT((((unsigned long) (ptr)) & 0xf) == 0);
|
||||
|
||||
|
||||
/** round up value to next multiple of 4 */
|
||||
#define ROUNDUP4(k) (((k) + 0x3) & ~0x3)
|
||||
|
||||
/** round up value to next multiple of 8 */
|
||||
#define ROUNDUP8(k) (((k) + 0x7) & ~0x7)
|
||||
|
||||
/** round up value to next multiple of 16 */
|
||||
#define ROUNDUP16(k) (((k) + 0xf) & ~0xf)
|
||||
|
||||
|
||||
#define CELL_MAX_SPUS 8
|
||||
|
||||
#define CELL_MAX_SAMPLERS 4
|
||||
#define CELL_MAX_TEXTURE_LEVELS 12 /* 2k x 2k */
|
||||
#define CELL_MAX_CONSTANTS 32 /**< number of float[4] constants */
|
||||
#define CELL_MAX_WIDTH 1024 /**< max framebuffer width */
|
||||
#define CELL_MAX_HEIGHT 1024 /**< max framebuffer width */
|
||||
|
||||
#define TILE_SIZE 32
|
||||
|
||||
|
||||
/**
|
||||
* The low byte of a mailbox word contains the command opcode.
|
||||
* Remaining higher bytes are command specific.
|
||||
*/
|
||||
#define CELL_CMD_OPCODE_MASK 0xff
|
||||
|
||||
#define CELL_CMD_EXIT 1
|
||||
#define CELL_CMD_CLEAR_SURFACE 2
|
||||
#define CELL_CMD_FINISH 3
|
||||
#define CELL_CMD_RENDER 4
|
||||
#define CELL_CMD_BATCH 5
|
||||
#define CELL_CMD_RELEASE_VERTS 6
|
||||
#define CELL_CMD_STATE_FRAMEBUFFER 10
|
||||
#define CELL_CMD_STATE_FRAGMENT_OPS 11
|
||||
#define CELL_CMD_STATE_SAMPLER 12
|
||||
#define CELL_CMD_STATE_TEXTURE 13
|
||||
#define CELL_CMD_STATE_VERTEX_INFO 14
|
||||
#define CELL_CMD_STATE_VIEWPORT 15
|
||||
#define CELL_CMD_STATE_UNIFORMS 16
|
||||
#define CELL_CMD_STATE_VS_ARRAY_INFO 17
|
||||
#define CELL_CMD_STATE_BIND_VS 18
|
||||
#define CELL_CMD_STATE_FRAGMENT_PROGRAM 19
|
||||
#define CELL_CMD_STATE_ATTRIB_FETCH 20
|
||||
#define CELL_CMD_STATE_FS_CONSTANTS 21
|
||||
#define CELL_CMD_STATE_RASTERIZER 22
|
||||
#define CELL_CMD_VS_EXECUTE 23
|
||||
#define CELL_CMD_FLUSH_BUFFER_RANGE 24
|
||||
#define CELL_CMD_FENCE 25
|
||||
|
||||
|
||||
/** Command/batch buffers */
|
||||
#define CELL_NUM_BUFFERS 4
|
||||
#define CELL_BUFFER_SIZE (4*1024) /**< 16KB would be the max */
|
||||
|
||||
#define CELL_BUFFER_STATUS_FREE 10
|
||||
#define CELL_BUFFER_STATUS_USED 20
|
||||
|
||||
/** Debug flags */
|
||||
#define CELL_DEBUG_CHECKER (1 << 0)
|
||||
#define CELL_DEBUG_ASM (1 << 1)
|
||||
#define CELL_DEBUG_SYNC (1 << 2)
|
||||
#define CELL_DEBUG_FRAGMENT_OPS (1 << 3)
|
||||
#define CELL_DEBUG_FRAGMENT_OP_FALLBACK (1 << 4)
|
||||
#define CELL_DEBUG_CMD (1 << 5)
|
||||
#define CELL_DEBUG_CACHE (1 << 6)
|
||||
|
||||
#define CELL_FENCE_IDLE 0
|
||||
#define CELL_FENCE_EMITTED 1
|
||||
#define CELL_FENCE_SIGNALLED 2
|
||||
|
||||
#define CELL_FACING_FRONT 0
|
||||
#define CELL_FACING_BACK 1
|
||||
|
||||
struct cell_fence
|
||||
{
|
||||
/** There's a 16-byte status qword per SPU */
|
||||
volatile uint status[CELL_MAX_SPUS][4];
|
||||
};
|
||||
|
||||
#ifdef __SPU__
|
||||
typedef vector unsigned int opcode_t;
|
||||
#else
|
||||
typedef unsigned int opcode_t[4];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Fence command sent to SPUs. In response, the SPUs will write
|
||||
* CELL_FENCE_STATUS_SIGNALLED back to the fence status word in main memory.
|
||||
*/
|
||||
struct cell_command_fence
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_FENCE */
|
||||
struct cell_fence *fence;
|
||||
uint32_t pad_[3];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Command to specify per-fragment operations state and generated code.
|
||||
* Note that this is a variant-length structure, allocated with as
|
||||
* much memory as needed to hold the generated code; the "code"
|
||||
* field *must* be the last field in the structure. Also, the entire
|
||||
* length of the structure (including the variant code field) must be
|
||||
* a multiple of 8 bytes; we require that this structure itself be
|
||||
* a multiple of 8 bytes, and that the generated code also be a multiple
|
||||
* of 8 bytes.
|
||||
*
|
||||
* Also note that the dsa, blend, blend_color fields are really only needed
|
||||
* for the fallback/C per-pixel code. They're not used when we generate
|
||||
* dynamic SPU fragment code (which is the normal case), and will eventually
|
||||
* be removed from this structure.
|
||||
*/
|
||||
struct cell_command_fragment_ops
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_STATE_FRAGMENT_OPS */
|
||||
|
||||
/* Fields for the fallback case */
|
||||
struct pipe_depth_stencil_alpha_state dsa;
|
||||
struct pipe_blend_state blend;
|
||||
struct pipe_blend_color blend_color;
|
||||
|
||||
/* Fields for the generated SPU code */
|
||||
unsigned total_code_size;
|
||||
unsigned front_code_index;
|
||||
unsigned back_code_index;
|
||||
/* this field has variant length, and must be the last field in
|
||||
* the structure
|
||||
*/
|
||||
unsigned code[0];
|
||||
};
|
||||
|
||||
|
||||
/** Max instructions for fragment programs */
|
||||
#define SPU_MAX_FRAGMENT_PROGRAM_INSTS 512
|
||||
|
||||
/**
|
||||
* Command to send a fragment program to SPUs.
|
||||
*/
|
||||
struct cell_command_fragment_program
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_STATE_FRAGMENT_PROGRAM */
|
||||
uint num_inst; /**< Number of instructions */
|
||||
uint32_t pad[3];
|
||||
unsigned code[SPU_MAX_FRAGMENT_PROGRAM_INSTS];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tell SPUs about the framebuffer size, location
|
||||
*/
|
||||
struct cell_command_framebuffer
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_STATE_FRAMEBUFFER */
|
||||
int width, height;
|
||||
void *color_start, *depth_start;
|
||||
enum pipe_format color_format, depth_format;
|
||||
uint32_t pad_[2];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tell SPUs about rasterizer state.
|
||||
*/
|
||||
struct cell_command_rasterizer
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_STATE_RASTERIZER */
|
||||
struct pipe_rasterizer_state rasterizer;
|
||||
/*uint32_t pad[1];*/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clear framebuffer to the given value/color.
|
||||
*/
|
||||
struct cell_command_clear_surface
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_CLEAR_SURFACE */
|
||||
uint surface; /**< Temporary: 0=color, 1=Z */
|
||||
uint value;
|
||||
uint32_t pad[2];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Array info used by the vertex shader's vertex puller.
|
||||
*/
|
||||
struct cell_array_info
|
||||
{
|
||||
uint64_t base; /**< Base address of the 0th element. */
|
||||
uint attr; /**< Attribute that this state is for. */
|
||||
uint pitch; /**< Byte pitch from one entry to the next. */
|
||||
uint size;
|
||||
uint function_offset;
|
||||
};
|
||||
|
||||
|
||||
struct cell_attribute_fetch_code
|
||||
{
|
||||
uint64_t base;
|
||||
uint size;
|
||||
};
|
||||
|
||||
|
||||
struct cell_buffer_range
|
||||
{
|
||||
uint64_t base;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
|
||||
struct cell_shader_info
|
||||
{
|
||||
uint64_t declarations;
|
||||
uint64_t instructions;
|
||||
uint64_t immediates;
|
||||
|
||||
unsigned num_outputs;
|
||||
unsigned num_declarations;
|
||||
unsigned num_instructions;
|
||||
unsigned num_immediates;
|
||||
};
|
||||
|
||||
|
||||
#define SPU_VERTS_PER_BATCH 64
|
||||
struct cell_command_vs
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_VS_EXECUTE */
|
||||
uint64_t vOut[SPU_VERTS_PER_BATCH];
|
||||
unsigned num_elts;
|
||||
unsigned elts[SPU_VERTS_PER_BATCH];
|
||||
float plane[12][4];
|
||||
unsigned nr_planes;
|
||||
unsigned nr_attrs;
|
||||
};
|
||||
|
||||
|
||||
struct cell_command_render
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_RENDER */
|
||||
uint prim_type; /**< PIPE_PRIM_x */
|
||||
uint num_verts;
|
||||
uint vertex_size; /**< bytes per vertex */
|
||||
uint num_indexes;
|
||||
uint vertex_buf; /**< which cell->buffer[] contains the vertex data */
|
||||
float xmin, ymin, xmax, ymax; /* XXX another dummy field */
|
||||
uint min_index;
|
||||
boolean inline_verts;
|
||||
uint32_t pad_[1];
|
||||
};
|
||||
|
||||
|
||||
struct cell_command_release_verts
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_RELEASE_VERTS */
|
||||
uint vertex_buf; /**< in [0, CELL_NUM_BUFFERS-1] */
|
||||
uint32_t pad_[3];
|
||||
};
|
||||
|
||||
|
||||
struct cell_command_sampler
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_STATE_SAMPLER */
|
||||
uint unit;
|
||||
struct pipe_sampler_state state;
|
||||
uint32_t pad_[3];
|
||||
};
|
||||
|
||||
|
||||
struct cell_command_texture
|
||||
{
|
||||
opcode_t opcode; /**< CELL_CMD_STATE_TEXTURE */
|
||||
uint target; /**< PIPE_TEXTURE_x */
|
||||
uint unit;
|
||||
void *start[CELL_MAX_TEXTURE_LEVELS]; /**< Address in main memory */
|
||||
ushort width[CELL_MAX_TEXTURE_LEVELS];
|
||||
ushort height[CELL_MAX_TEXTURE_LEVELS];
|
||||
ushort depth[CELL_MAX_TEXTURE_LEVELS];
|
||||
};
|
||||
|
||||
|
||||
#define MAX_SPU_FUNCTIONS 12
|
||||
/**
|
||||
* Used to tell the PPU about the address of particular functions in the
|
||||
* SPU's address space.
|
||||
*/
|
||||
struct cell_spu_function_info
|
||||
{
|
||||
uint num;
|
||||
char names[MAX_SPU_FUNCTIONS][16];
|
||||
uint addrs[MAX_SPU_FUNCTIONS];
|
||||
char pad[12]; /**< Pad struct to multiple of 16 bytes (256 currently) */
|
||||
};
|
||||
|
||||
|
||||
/** This is the object passed to spe_create_thread() */
|
||||
PIPE_ALIGN_TYPE(16,
|
||||
struct cell_init_info
|
||||
{
|
||||
unsigned id;
|
||||
unsigned num_spus;
|
||||
unsigned debug_flags; /**< mask of CELL_DEBUG_x flags */
|
||||
float inv_timebase; /**< 1.0/timebase, for perf measurement */
|
||||
|
||||
/** Buffers for command batches, vertex/index data */
|
||||
ubyte *buffers[CELL_NUM_BUFFERS];
|
||||
uint *buffer_status; /**< points at cell_context->buffer_status */
|
||||
|
||||
struct cell_spu_function_info *spu_functions;
|
||||
});
|
||||
|
||||
|
||||
#endif /* CELL_COMMON_H */
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
# Gallium3D Cell driver: PPU code
|
||||
|
||||
# This makefile builds the libcell.a library which gets pulled into
|
||||
# the main libGL.so library
|
||||
|
||||
|
||||
TOP = ../../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
# This is the "top-level" cell PPU driver code, will get pulled into libGL.so
|
||||
# by the winsys Makefile.
|
||||
CELL_LIB = ../libcell.a
|
||||
|
||||
|
||||
# This is the SPU code. We'd like to be able to put this into the libcell.a
|
||||
# archive with the PPU code, but nesting .a libs doesn't seem to work.
|
||||
# So, it's pulled into libGL.so in gallium/winsys/xlib/Makefile
|
||||
SPU_CODE_MODULE = ../spu/g3d_spu.a
|
||||
|
||||
|
||||
SOURCES = \
|
||||
cell_batch.c \
|
||||
cell_clear.c \
|
||||
cell_context.c \
|
||||
cell_draw_arrays.c \
|
||||
cell_fence.c \
|
||||
cell_flush.c \
|
||||
cell_gen_fragment.c \
|
||||
cell_gen_fp.c \
|
||||
cell_state_derived.c \
|
||||
cell_state_emit.c \
|
||||
cell_state_shader.c \
|
||||
cell_pipe_state.c \
|
||||
cell_screen.c \
|
||||
cell_state_vertex.c \
|
||||
cell_spu.c \
|
||||
cell_surface.c \
|
||||
cell_texture.c \
|
||||
cell_vbuf.c \
|
||||
cell_vertex_fetch.c \
|
||||
cell_vertex_shader.c
|
||||
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o) \
|
||||
|
||||
INCLUDE_DIRS = \
|
||||
-I$(TOP)/src/mesa \
|
||||
-I$(TOP)/src/gallium/include \
|
||||
-I$(TOP)/src/gallium/auxiliary \
|
||||
-I$(TOP)/src/gallium/drivers
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
.c.s:
|
||||
$(CC) -S $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
default: $(CELL_LIB)
|
||||
|
||||
|
||||
$(CELL_LIB): $(OBJECTS) $(SPU_CODE_MODULE)
|
||||
# ar -ru $(CELL_LIB) $(OBJECTS) $(SPU_CODE_MODULE) # doesn't work
|
||||
ar -ru $(CELL_LIB) $(OBJECTS)
|
||||
|
||||
#$(PROG): $(PPU_OBJECTS)
|
||||
# $(CC) -o $(PROG) $(PPU_OBJECTS) $(SPU_CODE_MODULE) $(PPU_LFLAGS)
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ $(CELL_LIB)
|
||||
|
||||
|
||||
|
||||
depend: $(SOURCES)
|
||||
rm -f depend
|
||||
touch depend
|
||||
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(SOURCES) 2> /dev/null
|
||||
|
||||
include depend
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,260 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "cell_batch.h"
|
||||
#include "cell_fence.h"
|
||||
#include "cell_spu.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Search the buffer pool for an empty/free buffer and return its index.
|
||||
* Buffers are used for storing vertex data, state and commands which
|
||||
* will be sent to the SPUs.
|
||||
* If no empty buffers are available, wait for one.
|
||||
* \return buffer index in [0, CELL_NUM_BUFFERS-1]
|
||||
*/
|
||||
uint
|
||||
cell_get_empty_buffer(struct cell_context *cell)
|
||||
{
|
||||
static uint prev_buffer = 0;
|
||||
uint buf = (prev_buffer + 1) % CELL_NUM_BUFFERS;
|
||||
uint tries = 0;
|
||||
|
||||
/* Find a buffer that's marked as free by all SPUs */
|
||||
while (1) {
|
||||
uint spu, num_free = 0;
|
||||
|
||||
for (spu = 0; spu < cell->num_spus; spu++) {
|
||||
if (cell->buffer_status[spu][buf][0] == CELL_BUFFER_STATUS_FREE) {
|
||||
num_free++;
|
||||
|
||||
if (num_free == cell->num_spus) {
|
||||
/* found a free buffer, now mark status as used */
|
||||
for (spu = 0; spu < cell->num_spus; spu++) {
|
||||
cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
|
||||
}
|
||||
/*
|
||||
printf("PPU: ALLOC BUFFER %u, %u tries\n", buf, tries);
|
||||
*/
|
||||
prev_buffer = buf;
|
||||
|
||||
/* release tex buffer associated w/ prev use of this batch buf */
|
||||
cell_free_fenced_buffers(cell, &cell->fenced_buffers[buf]);
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* try next buf */
|
||||
buf = (buf + 1) % CELL_NUM_BUFFERS;
|
||||
|
||||
tries++;
|
||||
if (tries == 100) {
|
||||
/*
|
||||
printf("PPU WAITING for buffer...\n");
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append a fence command to the current batch buffer.
|
||||
* Note that we're sure there's always room for this because of the
|
||||
* adjusted size check in cell_batch_free_space().
|
||||
*/
|
||||
static void
|
||||
emit_fence(struct cell_context *cell)
|
||||
{
|
||||
const uint batch = cell->cur_batch;
|
||||
const uint size = cell->buffer_size[batch];
|
||||
struct cell_command_fence *fence_cmd;
|
||||
struct cell_fence *fence = &cell->fenced_buffers[batch].fence;
|
||||
uint i;
|
||||
|
||||
/* set fence status to emitted, not yet signalled */
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
fence->status[i][0] = CELL_FENCE_EMITTED;
|
||||
}
|
||||
|
||||
STATIC_ASSERT(sizeof(struct cell_command_fence) % 16 == 0);
|
||||
ASSERT(size % 16 == 0);
|
||||
ASSERT(size + sizeof(struct cell_command_fence) <= CELL_BUFFER_SIZE);
|
||||
|
||||
fence_cmd = (struct cell_command_fence *) (cell->buffer[batch] + size);
|
||||
fence_cmd->opcode[0] = CELL_CMD_FENCE;
|
||||
fence_cmd->fence = fence;
|
||||
|
||||
/* update batch buffer size */
|
||||
cell->buffer_size[batch] = size + sizeof(struct cell_command_fence);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Flush the current batch buffer to the SPUs.
|
||||
* An empty buffer will be found and set as the new current batch buffer
|
||||
* for subsequent commands/data.
|
||||
*/
|
||||
void
|
||||
cell_batch_flush(struct cell_context *cell)
|
||||
{
|
||||
static boolean flushing = FALSE;
|
||||
uint batch = cell->cur_batch;
|
||||
uint size = cell->buffer_size[batch];
|
||||
uint spu, cmd_word;
|
||||
|
||||
assert(!flushing);
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
/* Before we use this batch buffer, make sure any fenced texture buffers
|
||||
* are released.
|
||||
*/
|
||||
if (cell->fenced_buffers[batch].head) {
|
||||
emit_fence(cell);
|
||||
size = cell->buffer_size[batch];
|
||||
}
|
||||
|
||||
flushing = TRUE;
|
||||
|
||||
assert(batch < CELL_NUM_BUFFERS);
|
||||
|
||||
/*
|
||||
printf("cell_batch_dispatch: buf %u at %p, size %u\n",
|
||||
batch, &cell->buffer[batch][0], size);
|
||||
*/
|
||||
|
||||
/*
|
||||
* Build "BATCH" command and send to all SPUs.
|
||||
*/
|
||||
cmd_word = CELL_CMD_BATCH | (batch << 8) | (size << 16);
|
||||
|
||||
for (spu = 0; spu < cell->num_spus; spu++) {
|
||||
assert(cell->buffer_status[spu][batch][0] == CELL_BUFFER_STATUS_USED);
|
||||
send_mbox_message(cell_global.spe_contexts[spu], cmd_word);
|
||||
}
|
||||
|
||||
/* When the SPUs are done copying the buffer into their locals stores
|
||||
* they'll write a BUFFER_STATUS_FREE message into the buffer_status[]
|
||||
* array indicating that the PPU can re-use the buffer.
|
||||
*/
|
||||
|
||||
batch = cell_get_empty_buffer(cell);
|
||||
|
||||
cell->buffer_size[batch] = 0; /* empty */
|
||||
cell->cur_batch = batch;
|
||||
|
||||
flushing = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of bytes free in the current batch buffer.
|
||||
*/
|
||||
uint
|
||||
cell_batch_free_space(const struct cell_context *cell)
|
||||
{
|
||||
uint free = CELL_BUFFER_SIZE - cell->buffer_size[cell->cur_batch];
|
||||
free -= sizeof(struct cell_command_fence);
|
||||
return free;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocate space in the current batch buffer for 'bytes' space.
|
||||
* Bytes must be a multiple of 16 bytes. Allocation will be 16 byte aligned.
|
||||
* \return address in batch buffer to put data
|
||||
*/
|
||||
void *
|
||||
cell_batch_alloc16(struct cell_context *cell, uint bytes)
|
||||
{
|
||||
void *pos;
|
||||
uint size;
|
||||
|
||||
ASSERT(bytes % 16 == 0);
|
||||
ASSERT(bytes <= CELL_BUFFER_SIZE);
|
||||
ASSERT(cell->cur_batch >= 0);
|
||||
|
||||
#ifdef ASSERT
|
||||
{
|
||||
uint spu;
|
||||
for (spu = 0; spu < cell->num_spus; spu++) {
|
||||
ASSERT(cell->buffer_status[spu][cell->cur_batch][0]
|
||||
== CELL_BUFFER_STATUS_USED);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size = cell->buffer_size[cell->cur_batch];
|
||||
|
||||
if (bytes > cell_batch_free_space(cell)) {
|
||||
cell_batch_flush(cell);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
ASSERT(size % 16 == 0);
|
||||
ASSERT(size + bytes <= CELL_BUFFER_SIZE);
|
||||
|
||||
pos = (void *) (cell->buffer[cell->cur_batch] + size);
|
||||
|
||||
cell->buffer_size[cell->cur_batch] = size + bytes;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* One-time init of batch buffers.
|
||||
*/
|
||||
void
|
||||
cell_init_batch_buffers(struct cell_context *cell)
|
||||
{
|
||||
uint spu, buf;
|
||||
|
||||
/* init command, vertex/index buffer info */
|
||||
for (buf = 0; buf < CELL_NUM_BUFFERS; buf++) {
|
||||
cell->buffer_size[buf] = 0;
|
||||
|
||||
/* init batch buffer status values,
|
||||
* mark 0th buffer as used, rest as free.
|
||||
*/
|
||||
for (spu = 0; spu < cell->num_spus; spu++) {
|
||||
if (buf == 0)
|
||||
cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
|
||||
else
|
||||
cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_FREE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_BATCH_H
|
||||
#define CELL_BATCH_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
|
||||
struct cell_context;
|
||||
|
||||
|
||||
extern uint
|
||||
cell_get_empty_buffer(struct cell_context *cell);
|
||||
|
||||
extern void
|
||||
cell_batch_flush(struct cell_context *cell);
|
||||
|
||||
extern uint
|
||||
cell_batch_free_space(const struct cell_context *cell);
|
||||
|
||||
extern void *
|
||||
cell_batch_alloc16(struct cell_context *cell, uint bytes);
|
||||
|
||||
extern void
|
||||
cell_init_batch_buffers(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_BATCH_H */
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Authors
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_pack_color.h"
|
||||
#include "cell/common.h"
|
||||
#include "cell_clear.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_batch.h"
|
||||
#include "cell_flush.h"
|
||||
#include "cell_spu.h"
|
||||
#include "cell_state.h"
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->clear()
|
||||
*/
|
||||
void
|
||||
cell_clear(struct pipe_context *pipe, unsigned buffers,
|
||||
const pipe_color_union *color,
|
||||
double depth, unsigned stencil)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
if (cell->dirty)
|
||||
cell_update_derived(cell);
|
||||
|
||||
if (buffers & PIPE_CLEAR_COLOR) {
|
||||
uint surfIndex = 0;
|
||||
union util_color uc;
|
||||
|
||||
util_pack_color(color->f, cell->framebuffer.cbufs[0]->format, &uc);
|
||||
|
||||
/* Build a CLEAR command and place it in the current batch buffer */
|
||||
STATIC_ASSERT(sizeof(struct cell_command_clear_surface) % 16 == 0);
|
||||
struct cell_command_clear_surface *clr
|
||||
= (struct cell_command_clear_surface *)
|
||||
cell_batch_alloc16(cell, sizeof(*clr));
|
||||
clr->opcode[0] = CELL_CMD_CLEAR_SURFACE;
|
||||
clr->surface = surfIndex;
|
||||
clr->value = uc.ui;
|
||||
}
|
||||
|
||||
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
|
||||
uint surfIndex = 1;
|
||||
uint clearValue;
|
||||
|
||||
clearValue = util_pack_z_stencil(cell->framebuffer.zsbuf->format,
|
||||
depth, stencil);
|
||||
|
||||
/* Build a CLEAR command and place it in the current batch buffer */
|
||||
STATIC_ASSERT(sizeof(struct cell_command_clear_surface) % 16 == 0);
|
||||
struct cell_command_clear_surface *clr
|
||||
= (struct cell_command_clear_surface *)
|
||||
cell_batch_alloc16(cell, sizeof(*clr));
|
||||
clr->opcode[0] = CELL_CMD_CLEAR_SURFACE;
|
||||
clr->surface = surfIndex;
|
||||
clr->value = clearValue;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_CLEAR_H
|
||||
#define CELL_CLEAR_H
|
||||
|
||||
|
||||
struct pipe_context;
|
||||
|
||||
|
||||
extern void
|
||||
cell_clear(struct pipe_context *pipe, unsigned buffers,
|
||||
const union pipe_color_union *color,
|
||||
double depth, unsigned stencil);
|
||||
|
||||
|
||||
#endif /* CELL_CLEAR_H */
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Authors
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_format.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "pipe/p_screen.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_private.h"
|
||||
|
||||
#include "cell/common.h"
|
||||
#include "cell_batch.h"
|
||||
#include "cell_clear.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_draw_arrays.h"
|
||||
#include "cell_fence.h"
|
||||
#include "cell_flush.h"
|
||||
#include "cell_state.h"
|
||||
#include "cell_surface.h"
|
||||
#include "cell_spu.h"
|
||||
#include "cell_pipe_state.h"
|
||||
#include "cell_texture.h"
|
||||
#include "cell_vbuf.h"
|
||||
|
||||
|
||||
|
||||
static void
|
||||
cell_destroy_context( struct pipe_context *pipe )
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < cell->num_vertex_buffers; i++) {
|
||||
pipe_resource_reference(&cell->vertex_buffer[i].buffer, NULL);
|
||||
}
|
||||
|
||||
util_delete_keymap(cell->fragment_ops_cache, NULL);
|
||||
|
||||
cell_spu_exit(cell);
|
||||
|
||||
align_free(cell);
|
||||
}
|
||||
|
||||
|
||||
static struct draw_context *
|
||||
cell_draw_create(struct cell_context *cell)
|
||||
{
|
||||
struct draw_context *draw = draw_create(&cell->pipe);
|
||||
|
||||
#if 0 /* broken */
|
||||
if (getenv("GALLIUM_CELL_VS")) {
|
||||
/* plug in SPU-based vertex transformation code */
|
||||
draw->shader_queue_flush = cell_vertex_shader_queue_flush;
|
||||
draw->driver_private = cell;
|
||||
}
|
||||
#endif
|
||||
|
||||
return draw;
|
||||
}
|
||||
|
||||
|
||||
static const struct debug_named_value cell_debug_flags[] = {
|
||||
{"checker", CELL_DEBUG_CHECKER, NULL},/**< modulate tile clear color by SPU ID */
|
||||
{"asm", CELL_DEBUG_ASM, NULL}, /**< dump SPU asm code */
|
||||
{"sync", CELL_DEBUG_SYNC, NULL}, /**< SPUs do synchronous DMA */
|
||||
{"fragops", CELL_DEBUG_FRAGMENT_OPS, NULL}, /**< SPUs emit fragment ops debug messages*/
|
||||
{"fragopfallback", CELL_DEBUG_FRAGMENT_OP_FALLBACK, NULL}, /**< SPUs use reference implementation for fragment ops*/
|
||||
{"cmd", CELL_DEBUG_CMD, NULL}, /**< SPUs dump command buffer info */
|
||||
{"cache", CELL_DEBUG_CACHE, NULL}, /**< report texture cache stats on exit */
|
||||
DEBUG_NAMED_VALUE_END
|
||||
};
|
||||
|
||||
|
||||
struct pipe_context *
|
||||
cell_create_context(struct pipe_screen *screen,
|
||||
void *priv )
|
||||
{
|
||||
struct cell_context *cell;
|
||||
uint i;
|
||||
|
||||
/* some fields need to be 16-byte aligned, so align the whole object */
|
||||
cell = (struct cell_context*) align_malloc(sizeof(struct cell_context), 16);
|
||||
if (!cell)
|
||||
return NULL;
|
||||
|
||||
memset(cell, 0, sizeof(*cell));
|
||||
|
||||
cell->winsys = NULL; /* XXX: fixme - get this from screen? */
|
||||
cell->pipe.winsys = NULL;
|
||||
cell->pipe.screen = screen;
|
||||
cell->pipe.priv = priv;
|
||||
cell->pipe.destroy = cell_destroy_context;
|
||||
|
||||
cell->pipe.clear = cell_clear;
|
||||
cell->pipe.flush = cell_flush;
|
||||
|
||||
#if 0
|
||||
cell->pipe.begin_query = cell_begin_query;
|
||||
cell->pipe.end_query = cell_end_query;
|
||||
cell->pipe.wait_query = cell_wait_query;
|
||||
#endif
|
||||
|
||||
cell_init_draw_functions(cell);
|
||||
cell_init_state_functions(cell);
|
||||
cell_init_shader_functions(cell);
|
||||
cell_init_surface_functions(cell);
|
||||
cell_init_vertex_functions(cell);
|
||||
cell_init_texture_transfer_funcs(cell);
|
||||
|
||||
cell->draw = cell_draw_create(cell);
|
||||
|
||||
/* Create cache of fragment ops generated code */
|
||||
cell->fragment_ops_cache =
|
||||
util_new_keymap(sizeof(struct cell_fragment_ops_key), ~0, NULL);
|
||||
|
||||
cell_init_vbuf(cell);
|
||||
|
||||
draw_set_rasterize_stage(cell->draw, cell->vbuf);
|
||||
|
||||
/* convert all points/lines to tris for the time being */
|
||||
draw_wide_point_threshold(cell->draw, 0.0);
|
||||
draw_wide_line_threshold(cell->draw, 0.0);
|
||||
|
||||
/* get env vars or read config file to get debug flags */
|
||||
cell->debug_flags = debug_get_flags_option("CELL_DEBUG",
|
||||
cell_debug_flags,
|
||||
0 );
|
||||
|
||||
for (i = 0; i < CELL_NUM_BUFFERS; i++)
|
||||
cell_fence_init(&cell->fenced_buffers[i].fence);
|
||||
|
||||
|
||||
/*
|
||||
* SPU stuff
|
||||
*/
|
||||
/* This call only works with SDK 3.0. Anyone still using 2.1??? */
|
||||
cell->num_cells = spe_cpu_info_get(SPE_COUNT_PHYSICAL_CPU_NODES, -1);
|
||||
cell->num_spus = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, -1);
|
||||
if (cell->debug_flags) {
|
||||
printf("Cell: found %d Cell(s) with %u SPUs\n",
|
||||
cell->num_cells, cell->num_spus);
|
||||
}
|
||||
if (getenv("CELL_NUM_SPUS")) {
|
||||
cell->num_spus = atoi(getenv("CELL_NUM_SPUS"));
|
||||
assert(cell->num_spus > 0);
|
||||
}
|
||||
|
||||
cell_start_spus(cell);
|
||||
|
||||
cell_init_batch_buffers(cell);
|
||||
|
||||
/* make sure SPU initializations are done before proceeding */
|
||||
cell_flush_int(cell, CELL_FLUSH_WAIT);
|
||||
|
||||
return &cell->pipe;
|
||||
}
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_CONTEXT_H
|
||||
#define CELL_CONTEXT_H
|
||||
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "draw/draw_vertex.h"
|
||||
#include "draw/draw_vbuf.h"
|
||||
/*#include "cell_winsys.h"*/
|
||||
#include "cell/common.h"
|
||||
#include "rtasm/rtasm_ppc_spe.h"
|
||||
#include "tgsi/tgsi_scan.h"
|
||||
#include "util/u_keymap.h"
|
||||
|
||||
|
||||
struct cell_vbuf_render;
|
||||
|
||||
|
||||
/**
|
||||
* Cell vertex shader state, subclass of pipe_shader_state.
|
||||
*/
|
||||
struct cell_vertex_shader_state
|
||||
{
|
||||
struct pipe_shader_state shader;
|
||||
struct tgsi_shader_info info;
|
||||
void *draw_data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cell fragment shader state, subclass of pipe_shader_state.
|
||||
*/
|
||||
struct cell_fragment_shader_state
|
||||
{
|
||||
struct pipe_shader_state shader;
|
||||
struct tgsi_shader_info info;
|
||||
struct spe_function code;
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Key for mapping per-fragment state to cached SPU machine code.
|
||||
* keymap(cell_fragment_ops_key) => cell_command_fragment_ops
|
||||
*/
|
||||
struct cell_fragment_ops_key
|
||||
{
|
||||
struct pipe_blend_state blend;
|
||||
struct pipe_blend_color blend_color;
|
||||
struct pipe_depth_stencil_alpha_state dsa;
|
||||
enum pipe_format color_format;
|
||||
enum pipe_format zs_format;
|
||||
};
|
||||
|
||||
|
||||
struct cell_buffer_node;
|
||||
|
||||
/**
|
||||
* Fenced buffer list. List of buffers which can be unreferenced after
|
||||
* the fence has been executed/signalled.
|
||||
*/
|
||||
struct cell_buffer_list
|
||||
{
|
||||
PIPE_ALIGN_VAR(16) struct cell_fence fence;
|
||||
struct cell_buffer_node *head;
|
||||
};
|
||||
|
||||
struct cell_velems_state
|
||||
{
|
||||
unsigned count;
|
||||
struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
|
||||
};
|
||||
|
||||
/**
|
||||
* Per-context state, subclass of pipe_context.
|
||||
*/
|
||||
struct cell_context
|
||||
{
|
||||
struct pipe_context pipe;
|
||||
|
||||
struct cell_winsys *winsys;
|
||||
|
||||
const struct pipe_blend_state *blend;
|
||||
const struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
|
||||
uint num_samplers;
|
||||
const struct pipe_depth_stencil_alpha_state *depth_stencil;
|
||||
const struct pipe_rasterizer_state *rasterizer;
|
||||
const struct cell_vertex_shader_state *vs;
|
||||
const struct cell_fragment_shader_state *fs;
|
||||
const struct cell_velems_state *velems;
|
||||
|
||||
struct spe_function logic_op;
|
||||
|
||||
struct pipe_blend_color blend_color;
|
||||
struct pipe_stencil_ref stencil_ref;
|
||||
struct pipe_clip_state clip;
|
||||
struct pipe_resource *constants[2];
|
||||
struct pipe_framebuffer_state framebuffer;
|
||||
struct pipe_poly_stipple poly_stipple;
|
||||
struct pipe_scissor_state scissor;
|
||||
struct cell_resource *texture[PIPE_MAX_SAMPLERS];
|
||||
struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
|
||||
uint num_textures;
|
||||
struct pipe_viewport_state viewport;
|
||||
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
|
||||
uint num_vertex_buffers;
|
||||
struct pipe_index_buffer index_buffer;
|
||||
|
||||
ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS];
|
||||
ubyte *zsbuf_map;
|
||||
|
||||
uint dirty;
|
||||
uint dirty_textures; /* bitmask of texture units */
|
||||
uint dirty_samplers; /* bitmask of sampler units */
|
||||
|
||||
/** Cache of code generated for per-fragment ops */
|
||||
struct keymap *fragment_ops_cache;
|
||||
|
||||
/** The primitive drawing context */
|
||||
struct draw_context *draw;
|
||||
struct draw_stage *render_stage;
|
||||
|
||||
/** For post-transformed vertex buffering: */
|
||||
struct cell_vbuf_render *vbuf_render;
|
||||
struct draw_stage *vbuf;
|
||||
|
||||
struct vertex_info vertex_info;
|
||||
|
||||
/** Mapped constant buffers */
|
||||
const void *mapped_constants[PIPE_SHADER_TYPES];
|
||||
|
||||
PIPE_ALIGN_VAR(16) struct cell_spu_function_info spu_functions;
|
||||
|
||||
uint num_cells, num_spus;
|
||||
|
||||
/** Buffers for command batches, vertex/index data */
|
||||
uint buffer_size[CELL_NUM_BUFFERS];
|
||||
PIPE_ALIGN_VAR(16) ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE];
|
||||
|
||||
int cur_batch; /**< which buffer is being filled w/ commands */
|
||||
|
||||
/** [4] to ensure 16-byte alignment for each status word */
|
||||
PIPE_ALIGN_VAR(16) uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4];
|
||||
|
||||
|
||||
/** Associated with each command/batch buffer is a list of pipe_buffers
|
||||
* that are fenced. When the last command in a buffer is executed, the
|
||||
* fence will be signalled, indicating that any pipe_buffers preceeding
|
||||
* that fence can be unreferenced (and probably freed).
|
||||
*/
|
||||
struct cell_buffer_list fenced_buffers[CELL_NUM_BUFFERS];
|
||||
|
||||
|
||||
struct spe_function attrib_fetch;
|
||||
unsigned attrib_fetch_offsets[PIPE_MAX_ATTRIBS];
|
||||
|
||||
unsigned debug_flags;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static INLINE struct cell_context *
|
||||
cell_context(struct pipe_context *pipe)
|
||||
{
|
||||
return (struct cell_context *) pipe;
|
||||
}
|
||||
|
||||
|
||||
struct pipe_context *
|
||||
cell_create_context(struct pipe_screen *screen,
|
||||
void *priv );
|
||||
|
||||
extern void
|
||||
cell_vertex_shader_queue_flush(struct draw_context *draw);
|
||||
|
||||
|
||||
/* XXX find a better home for this */
|
||||
extern void cell_update_vertex_fetch(struct draw_context *draw);
|
||||
|
||||
|
||||
#endif /* CELL_CONTEXT_H */
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Author:
|
||||
* Brian Paul
|
||||
* Keith Whitwell
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "cell_draw_arrays.h"
|
||||
#include "cell_state.h"
|
||||
#include "cell_flush.h"
|
||||
#include "cell_texture.h"
|
||||
|
||||
#include "draw/draw_context.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw vertex arrays, with optional indexing.
|
||||
* Basically, map the vertex buffers (and drawing surfaces), then hand off
|
||||
* the drawing to the 'draw' module.
|
||||
*
|
||||
* XXX should the element buffer be specified/bound with a separate function?
|
||||
*/
|
||||
static void
|
||||
cell_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
struct draw_context *draw = cell->draw;
|
||||
void *mapped_indices = NULL;
|
||||
unsigned i;
|
||||
|
||||
if (cell->dirty)
|
||||
cell_update_derived( cell );
|
||||
|
||||
#if 0
|
||||
cell_map_surfaces(cell);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Map vertex buffers
|
||||
*/
|
||||
for (i = 0; i < cell->num_vertex_buffers; i++) {
|
||||
void *buf = cell_resource(cell->vertex_buffer[i].buffer)->data;
|
||||
draw_set_mapped_vertex_buffer(draw, i, buf);
|
||||
}
|
||||
/* Map index buffer, if present */
|
||||
if (info->indexed && cell->index_buffer.buffer)
|
||||
mapped_indices = cell_resource(cell->index_buffer.buffer)->data;
|
||||
|
||||
draw_set_mapped_index_buffer(draw, mapped_indices);
|
||||
|
||||
/* draw! */
|
||||
draw_vbo(draw, info);
|
||||
|
||||
/*
|
||||
* unmap vertex/index buffers - will cause draw module to flush
|
||||
*/
|
||||
for (i = 0; i < cell->num_vertex_buffers; i++) {
|
||||
draw_set_mapped_vertex_buffer(draw, i, NULL);
|
||||
}
|
||||
if (mapped_indices) {
|
||||
draw_set_mapped_index_buffer(draw, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Flush only when a user vertex/index buffer is present
|
||||
* (or even better, modify draw module to do this
|
||||
* internally when this condition is seen?)
|
||||
*/
|
||||
draw_flush(draw);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cell_init_draw_functions(struct cell_context *cell)
|
||||
{
|
||||
cell->pipe.draw_vbo = cell_draw_vbo;
|
||||
}
|
||||
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CELL_DRAW_ARRAYS_H
|
||||
#define CELL_DRAW_ARRAYS_H
|
||||
|
||||
|
||||
extern void
|
||||
cell_init_draw_functions(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_DRAW_ARRAYS_H */
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_batch.h"
|
||||
#include "cell_fence.h"
|
||||
#include "cell_texture.h"
|
||||
|
||||
|
||||
void
|
||||
cell_fence_init(struct cell_fence *fence)
|
||||
{
|
||||
uint i;
|
||||
ASSERT_ALIGN16(fence->status);
|
||||
for (i = 0; i < CELL_MAX_SPUS; i++) {
|
||||
fence->status[i][0] = CELL_FENCE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean
|
||||
cell_fence_signalled(const struct cell_context *cell,
|
||||
const struct cell_fence *fence)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
if (fence->status[i][0] != CELL_FENCE_SIGNALLED)
|
||||
return FALSE;
|
||||
/*assert(fence->status[i][0] == CELL_FENCE_EMITTED);*/
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
boolean
|
||||
cell_fence_finish(const struct cell_context *cell,
|
||||
const struct cell_fence *fence,
|
||||
uint64_t timeout)
|
||||
{
|
||||
while (!cell_fence_signalled(cell, fence)) {
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
assert(fence->status[i][0] == CELL_FENCE_SIGNALLED);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct cell_buffer_node
|
||||
{
|
||||
struct pipe_resource *buffer;
|
||||
struct cell_buffer_node *next;
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
static void
|
||||
cell_add_buffer_to_list(struct cell_context *cell,
|
||||
struct cell_buffer_list *list,
|
||||
struct pipe_resource *buffer)
|
||||
{
|
||||
struct cell_buffer_node *node = CALLOC_STRUCT(cell_buffer_node);
|
||||
/* create new list node which references the buffer, insert at head */
|
||||
if (node) {
|
||||
pipe_resource_reference(&node->buffer, buffer);
|
||||
node->next = list->head;
|
||||
list->head = node;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Wait for completion of the given fence, then unreference any buffers
|
||||
* on the list.
|
||||
* This typically unrefs/frees texture buffers after any rendering which uses
|
||||
* them has completed.
|
||||
*/
|
||||
void
|
||||
cell_free_fenced_buffers(struct cell_context *cell,
|
||||
struct cell_buffer_list *list)
|
||||
{
|
||||
if (list->head) {
|
||||
/*struct pipe_screen *ps = cell->pipe.screen;*/
|
||||
struct cell_buffer_node *node;
|
||||
|
||||
cell_fence_finish(cell, &list->fence);
|
||||
|
||||
/* traverse the list, unreferencing buffers, freeing nodes */
|
||||
node = list->head;
|
||||
while (node) {
|
||||
struct cell_buffer_node *next = node->next;
|
||||
assert(node->buffer);
|
||||
/* XXX need this? pipe_buffer_unmap(ps, node->buffer);*/
|
||||
#if 0
|
||||
printf("Unref buffer %p\n", node->buffer);
|
||||
if (node->buffer->reference.count == 1)
|
||||
printf(" Delete!\n");
|
||||
#endif
|
||||
pipe_resource_reference(&node->buffer, NULL);
|
||||
FREE(node);
|
||||
node = next;
|
||||
}
|
||||
list->head = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This should be called for each render command.
|
||||
* Any texture buffers that are current bound will be added to a fenced
|
||||
* list to be freed later when the fence is executed/signalled.
|
||||
*/
|
||||
void
|
||||
cell_add_fenced_textures(struct cell_context *cell)
|
||||
{
|
||||
/*struct cell_buffer_list *list = &cell->fenced_buffers[cell->cur_batch];*/
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < cell->num_textures; i++) {
|
||||
struct cell_resource *ct = cell->texture[i];
|
||||
if (ct) {
|
||||
#if 0
|
||||
printf("Adding texture %p buffer %p to list\n",
|
||||
ct, ct->tiled_buffer[level]);
|
||||
#endif
|
||||
#if 00
|
||||
/* XXX this needs to be fixed/restored!
|
||||
* Maybe keep pointers to textures, not buffers.
|
||||
*/
|
||||
if (ct->base.buffer)
|
||||
cell_add_buffer_to_list(cell, list, ct->buffer);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_FENCE_H
|
||||
#define CELL_FENCE_H
|
||||
|
||||
|
||||
extern void
|
||||
cell_fence_init(struct cell_fence *fence);
|
||||
|
||||
|
||||
extern boolean
|
||||
cell_fence_signalled(const struct cell_context *cell,
|
||||
const struct cell_fence *fence,
|
||||
unsigned flags);
|
||||
|
||||
|
||||
extern boolean
|
||||
cell_fence_finish(const struct cell_context *cell,
|
||||
const struct cell_fence *fence,
|
||||
unsigned flags,
|
||||
uint64_t timeout);
|
||||
|
||||
|
||||
|
||||
extern void
|
||||
cell_free_fenced_buffers(struct cell_context *cell,
|
||||
struct cell_buffer_list *list);
|
||||
|
||||
|
||||
extern void
|
||||
cell_add_fenced_textures(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_FENCE_H */
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "cell_batch.h"
|
||||
#include "cell_flush.h"
|
||||
#include "cell_spu.h"
|
||||
#include "cell_render.h"
|
||||
#include "draw/draw_context.h"
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->flush()
|
||||
*/
|
||||
void
|
||||
cell_flush(struct pipe_context *pipe,
|
||||
struct pipe_fence_handle **fence)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
if (fence) {
|
||||
*fence = NULL;
|
||||
}
|
||||
|
||||
flags |= CELL_FLUSH_WAIT;
|
||||
|
||||
draw_flush( cell->draw );
|
||||
cell_flush_int(cell, flags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cell internal flush function. Send the current batch buffer to all SPUs.
|
||||
* If flags & CELL_FLUSH_WAIT, do not return until the SPUs are idle.
|
||||
* \param flags bitmask of flags CELL_FLUSH_WAIT, or zero
|
||||
*/
|
||||
void
|
||||
cell_flush_int(struct cell_context *cell, unsigned flags)
|
||||
{
|
||||
static boolean flushing = FALSE; /* recursion catcher */
|
||||
uint i;
|
||||
|
||||
ASSERT(!flushing);
|
||||
flushing = TRUE;
|
||||
|
||||
if (flags & CELL_FLUSH_WAIT) {
|
||||
STATIC_ASSERT(sizeof(opcode_t) % 16 == 0);
|
||||
opcode_t *cmd = (opcode_t*) cell_batch_alloc16(cell, sizeof(opcode_t));
|
||||
*cmd[0] = CELL_CMD_FINISH;
|
||||
}
|
||||
|
||||
cell_batch_flush(cell);
|
||||
|
||||
#if 0
|
||||
/* Send CMD_FINISH to all SPUs */
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_FINISH);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags & CELL_FLUSH_WAIT) {
|
||||
/* Wait for ack */
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
uint k = wait_mbox_message(cell_global.spe_contexts[i]);
|
||||
assert(k == CELL_CMD_FINISH);
|
||||
}
|
||||
}
|
||||
|
||||
flushing = FALSE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cell_flush_buffer_range(struct cell_context *cell, void *ptr,
|
||||
unsigned size)
|
||||
{
|
||||
STATIC_ASSERT((sizeof(opcode_t) + sizeof(struct cell_buffer_range)) % 16 == 0);
|
||||
uint32_t *batch = (uint32_t*)cell_batch_alloc16(cell,
|
||||
sizeof(opcode_t) + sizeof(struct cell_buffer_range));
|
||||
struct cell_buffer_range *br = (struct cell_buffer_range *) &batch[4];
|
||||
batch[0] = CELL_CMD_FLUSH_BUFFER_RANGE;
|
||||
br->base = (uintptr_t) ptr;
|
||||
br->size = size;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_FLUSH
|
||||
#define CELL_FLUSH
|
||||
|
||||
#define CELL_FLUSH_WAIT 0x80000000
|
||||
|
||||
extern void
|
||||
cell_flush(struct pipe_context *pipe, unsigned flags,
|
||||
struct pipe_fence_handle **fence);
|
||||
|
||||
extern void
|
||||
cell_flush_int(struct cell_context *cell, unsigned flags);
|
||||
|
||||
extern void
|
||||
cell_flush_buffer_range(struct cell_context *cell, void *ptr,
|
||||
unsigned size);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,42 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CELL_GEN_FP_H
|
||||
#define CELL_GEN_FP_H
|
||||
|
||||
|
||||
|
||||
extern boolean
|
||||
cell_gen_fragment_program(struct cell_context *cell,
|
||||
const struct tgsi_token *tokens,
|
||||
struct spe_function *f);
|
||||
|
||||
|
||||
#endif /* CELL_GEN_FP_H */
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,38 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_GEN_FRAGMENT_H
|
||||
#define CELL_GEN_FRAGMENT_H
|
||||
|
||||
|
||||
extern void
|
||||
cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct spe_function *f);
|
||||
|
||||
|
||||
#endif /* CELL_GEN_FRAGMENT_H */
|
||||
|
||||
|
|
@ -1,473 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_flush.h"
|
||||
#include "cell_pipe_state.h"
|
||||
#include "cell_state.h"
|
||||
#include "cell_texture.h"
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
cell_create_blend_state(struct pipe_context *pipe,
|
||||
const struct pipe_blend_state *blend)
|
||||
{
|
||||
return mem_dup(blend, sizeof(*blend));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_bind_blend_state(struct pipe_context *pipe, void *blend)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
cell->blend = (struct pipe_blend_state *) blend;
|
||||
cell->dirty |= CELL_NEW_BLEND;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_delete_blend_state(struct pipe_context *pipe, void *blend)
|
||||
{
|
||||
FREE(blend);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_blend_color(struct pipe_context *pipe,
|
||||
const struct pipe_blend_color *blend_color)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
cell->blend_color = *blend_color;
|
||||
|
||||
cell->dirty |= CELL_NEW_BLEND;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
cell_create_depth_stencil_alpha_state(struct pipe_context *pipe,
|
||||
const struct pipe_depth_stencil_alpha_state *dsa)
|
||||
{
|
||||
return mem_dup(dsa, sizeof(*dsa));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe,
|
||||
void *dsa)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
cell->depth_stencil = (struct pipe_depth_stencil_alpha_state *) dsa;
|
||||
cell->dirty |= CELL_NEW_DEPTH_STENCIL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *dsa)
|
||||
{
|
||||
FREE(dsa);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_stencil_ref(struct pipe_context *pipe,
|
||||
const struct pipe_stencil_ref *stencil_ref)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
cell->stencil_ref = *stencil_ref;
|
||||
|
||||
cell->dirty |= CELL_NEW_DEPTH_STENCIL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_clip_state(struct pipe_context *pipe,
|
||||
const struct pipe_clip_state *clip)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
/* pass the clip state to the draw module */
|
||||
draw_set_clip_state(cell->draw, clip);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_sample_mask(struct pipe_context *pipe,
|
||||
unsigned sample_mask)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Called when driver state tracker notices changes to the viewport
|
||||
* matrix:
|
||||
*/
|
||||
static void
|
||||
cell_set_viewport_state( struct pipe_context *pipe,
|
||||
const struct pipe_viewport_state *viewport )
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
cell->viewport = *viewport; /* struct copy */
|
||||
cell->dirty |= CELL_NEW_VIEWPORT;
|
||||
|
||||
/* pass the viewport info to the draw module */
|
||||
draw_set_viewport_state(cell->draw, viewport);
|
||||
|
||||
/* Using tnl/ and vf/ modules is temporary while getting started.
|
||||
* Full pipe will have vertex shader, vertex fetch of its own.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_scissor_state( struct pipe_context *pipe,
|
||||
const struct pipe_scissor_state *scissor )
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
memcpy( &cell->scissor, scissor, sizeof(*scissor) );
|
||||
cell->dirty |= CELL_NEW_SCISSOR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_polygon_stipple( struct pipe_context *pipe,
|
||||
const struct pipe_poly_stipple *stipple )
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
memcpy( &cell->poly_stipple, stipple, sizeof(*stipple) );
|
||||
cell->dirty |= CELL_NEW_STIPPLE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
cell_create_rasterizer_state(struct pipe_context *pipe,
|
||||
const struct pipe_rasterizer_state *rasterizer)
|
||||
{
|
||||
return mem_dup(rasterizer, sizeof(*rasterizer));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_bind_rasterizer_state(struct pipe_context *pipe, void *rast)
|
||||
{
|
||||
struct pipe_rasterizer_state *rasterizer =
|
||||
(struct pipe_rasterizer_state *) rast;
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
/* pass-through to draw module */
|
||||
draw_set_rasterizer_state(cell->draw, rasterizer, rast);
|
||||
|
||||
cell->rasterizer = rasterizer;
|
||||
|
||||
cell->dirty |= CELL_NEW_RASTERIZER;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer)
|
||||
{
|
||||
FREE(rasterizer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
cell_create_sampler_state(struct pipe_context *pipe,
|
||||
const struct pipe_sampler_state *sampler)
|
||||
{
|
||||
return mem_dup(sampler, sizeof(*sampler));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_bind_sampler_states(struct pipe_context *pipe,
|
||||
unsigned num, void **samplers)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
uint i, changed = 0x0;
|
||||
|
||||
assert(num <= CELL_MAX_SAMPLERS);
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
|
||||
struct pipe_sampler_state *new_samp = i < num ? samplers[i] : NULL;
|
||||
if (cell->sampler[i] != new_samp) {
|
||||
cell->sampler[i] = new_samp;
|
||||
changed |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
cell->dirty |= CELL_NEW_SAMPLER;
|
||||
cell->dirty_samplers |= changed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_delete_sampler_state(struct pipe_context *pipe,
|
||||
void *sampler)
|
||||
{
|
||||
FREE( sampler );
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
cell_set_fragment_sampler_views(struct pipe_context *pipe,
|
||||
unsigned num,
|
||||
struct pipe_sampler_view **views)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
uint i, changed = 0x0;
|
||||
|
||||
assert(num <= CELL_MAX_SAMPLERS);
|
||||
|
||||
for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
|
||||
struct pipe_sampler_view *new_view = i < num ? views[i] : NULL;
|
||||
struct pipe_sampler_view *old_view = cell->fragment_sampler_views[i];
|
||||
|
||||
if (old_view != new_view) {
|
||||
struct pipe_resource *new_tex = new_view ? new_view->texture : NULL;
|
||||
|
||||
pipe_sampler_view_reference(&cell->fragment_sampler_views[i],
|
||||
new_view);
|
||||
pipe_resource_reference((struct pipe_resource **) &cell->texture[i],
|
||||
(struct pipe_resource *) new_tex);
|
||||
|
||||
changed |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
cell->num_textures = num;
|
||||
|
||||
if (changed) {
|
||||
cell->dirty |= CELL_NEW_TEXTURE;
|
||||
cell->dirty_textures |= changed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct pipe_sampler_view *
|
||||
cell_create_sampler_view(struct pipe_context *pipe,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_sampler_view *templ)
|
||||
{
|
||||
struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
|
||||
|
||||
if (view) {
|
||||
*view = *templ;
|
||||
view->reference.count = 1;
|
||||
view->texture = NULL;
|
||||
pipe_resource_reference(&view->texture, texture);
|
||||
view->context = pipe;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_sampler_view_destroy(struct pipe_context *pipe,
|
||||
struct pipe_sampler_view *view)
|
||||
{
|
||||
pipe_resource_reference(&view->texture, NULL);
|
||||
FREE(view);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map color and z/stencil framebuffer surfaces.
|
||||
*/
|
||||
static void
|
||||
cell_map_surfaces(struct cell_context *cell)
|
||||
{
|
||||
#if 0
|
||||
struct pipe_screen *screen = cell->pipe.screen;
|
||||
#endif
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < 1; i++) {
|
||||
struct pipe_surface *ps = cell->framebuffer.cbufs[i];
|
||||
if (ps) {
|
||||
struct cell_resource *ct = cell_resource(ps->texture);
|
||||
#if 0
|
||||
cell->cbuf_map[i] = screen->buffer_map(screen,
|
||||
ct->buffer,
|
||||
(PIPE_BUFFER_USAGE_GPU_READ |
|
||||
PIPE_BUFFER_USAGE_GPU_WRITE));
|
||||
#else
|
||||
cell->cbuf_map[i] = ct->data;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct pipe_surface *ps = cell->framebuffer.zsbuf;
|
||||
if (ps) {
|
||||
struct cell_resource *ct = cell_resource(ps->texture);
|
||||
#if 0
|
||||
cell->zsbuf_map = screen->buffer_map(screen,
|
||||
ct->buffer,
|
||||
(PIPE_BUFFER_USAGE_GPU_READ |
|
||||
PIPE_BUFFER_USAGE_GPU_WRITE));
|
||||
#else
|
||||
cell->zsbuf_map = ct->data;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unmap color and z/stencil framebuffer surfaces.
|
||||
*/
|
||||
static void
|
||||
cell_unmap_surfaces(struct cell_context *cell)
|
||||
{
|
||||
/*struct pipe_screen *screen = cell->pipe.screen;*/
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
|
||||
struct pipe_surface *ps = cell->framebuffer.cbufs[i];
|
||||
if (ps && cell->cbuf_map[i]) {
|
||||
/*struct cell_resource *ct = cell_resource(ps->texture);*/
|
||||
assert(ps->texture);
|
||||
/*assert(ct->buffer);*/
|
||||
|
||||
/*screen->buffer_unmap(screen, ct->buffer);*/
|
||||
cell->cbuf_map[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct pipe_surface *ps = cell->framebuffer.zsbuf;
|
||||
if (ps && cell->zsbuf_map) {
|
||||
/*struct cell_resource *ct = cell_resource(ps->texture);*/
|
||||
/*screen->buffer_unmap(screen, ct->buffer);*/
|
||||
cell->zsbuf_map = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_framebuffer_state(struct pipe_context *pipe,
|
||||
const struct pipe_framebuffer_state *fb)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
if (1 /*memcmp(&cell->framebuffer, fb, sizeof(*fb))*/) {
|
||||
uint i;
|
||||
|
||||
/* unmap old surfaces */
|
||||
cell_unmap_surfaces(cell);
|
||||
|
||||
/* Finish any pending rendering to the current surface before
|
||||
* installing a new surface!
|
||||
*/
|
||||
cell_flush_int(cell, CELL_FLUSH_WAIT);
|
||||
|
||||
/* update my state
|
||||
* (this is also where old surfaces will finally get freed)
|
||||
*/
|
||||
cell->framebuffer.width = fb->width;
|
||||
cell->framebuffer.height = fb->height;
|
||||
cell->framebuffer.nr_cbufs = fb->nr_cbufs;
|
||||
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
|
||||
pipe_surface_reference(&cell->framebuffer.cbufs[i], fb->cbufs[i]);
|
||||
}
|
||||
pipe_surface_reference(&cell->framebuffer.zsbuf, fb->zsbuf);
|
||||
|
||||
/* map new surfaces */
|
||||
cell_map_surfaces(cell);
|
||||
|
||||
cell->dirty |= CELL_NEW_FRAMEBUFFER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cell_init_state_functions(struct cell_context *cell)
|
||||
{
|
||||
cell->pipe.create_blend_state = cell_create_blend_state;
|
||||
cell->pipe.bind_blend_state = cell_bind_blend_state;
|
||||
cell->pipe.delete_blend_state = cell_delete_blend_state;
|
||||
|
||||
cell->pipe.create_sampler_state = cell_create_sampler_state;
|
||||
cell->pipe.bind_fragment_sampler_states = cell_bind_sampler_states;
|
||||
cell->pipe.delete_sampler_state = cell_delete_sampler_state;
|
||||
|
||||
cell->pipe.set_fragment_sampler_views = cell_set_fragment_sampler_views;
|
||||
cell->pipe.create_sampler_view = cell_create_sampler_view;
|
||||
cell->pipe.sampler_view_destroy = cell_sampler_view_destroy;
|
||||
|
||||
cell->pipe.create_depth_stencil_alpha_state = cell_create_depth_stencil_alpha_state;
|
||||
cell->pipe.bind_depth_stencil_alpha_state = cell_bind_depth_stencil_alpha_state;
|
||||
cell->pipe.delete_depth_stencil_alpha_state = cell_delete_depth_stencil_alpha_state;
|
||||
|
||||
cell->pipe.create_rasterizer_state = cell_create_rasterizer_state;
|
||||
cell->pipe.bind_rasterizer_state = cell_bind_rasterizer_state;
|
||||
cell->pipe.delete_rasterizer_state = cell_delete_rasterizer_state;
|
||||
|
||||
cell->pipe.set_blend_color = cell_set_blend_color;
|
||||
cell->pipe.set_stencil_ref = cell_set_stencil_ref;
|
||||
cell->pipe.set_clip_state = cell_set_clip_state;
|
||||
cell->pipe.set_sample_mask = cell_set_sample_mask;
|
||||
|
||||
cell->pipe.set_framebuffer_state = cell_set_framebuffer_state;
|
||||
|
||||
cell->pipe.set_polygon_stipple = cell_set_polygon_stipple;
|
||||
cell->pipe.set_scissor_state = cell_set_scissor_state;
|
||||
cell->pipe.set_viewport_state = cell_set_viewport_state;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_PIPE_STATE_H
|
||||
#define CELL_PIPE_STATE_H
|
||||
|
||||
|
||||
struct cell_context;
|
||||
|
||||
extern void
|
||||
cell_init_state_functions(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_PIPE_STATE_H */
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef CELL_PUBLIC_H
|
||||
#define CELL_PUBLIC_H
|
||||
|
||||
struct pipe_screen;
|
||||
struct sw_winsys;
|
||||
|
||||
struct pipe_screen *
|
||||
cell_create_screen(struct sw_winsys *winsys);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* \brief Last stage of 'draw' pipeline: send tris to SPUs.
|
||||
* \author Brian Paul
|
||||
*/
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "cell_render.h"
|
||||
#include "cell_spu.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "draw/draw_private.h"
|
||||
|
||||
|
||||
struct render_stage {
|
||||
struct draw_stage stage; /**< This must be first (base class) */
|
||||
|
||||
struct cell_context *cell;
|
||||
};
|
||||
|
||||
|
||||
static INLINE struct render_stage *
|
||||
render_stage(struct draw_stage *stage)
|
||||
{
|
||||
return (struct render_stage *) stage;
|
||||
}
|
||||
|
||||
|
||||
static void render_begin( struct draw_stage *stage )
|
||||
{
|
||||
#if 0
|
||||
struct render_stage *render = render_stage(stage);
|
||||
struct cell_context *sp = render->cell;
|
||||
const struct pipe_shader_state *fs = &render->cell->fs->shader;
|
||||
render->quad.nr_attrs = render->cell->nr_frag_attrs;
|
||||
|
||||
render->firstFpInput = fs->input_semantic_name[0];
|
||||
|
||||
sp->quad.first->begin(sp->quad.first);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void render_end( struct draw_stage *stage )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void reset_stipple_counter( struct draw_stage *stage )
|
||||
{
|
||||
struct render_stage *render = render_stage(stage);
|
||||
/*render->cell->line_stipple_counter = 0;*/
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
render_point(struct draw_stage *stage, struct prim_header *prim)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
render_line(struct draw_stage *stage, struct prim_header *prim)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/** Write a vertex into the prim buffer */
|
||||
static void
|
||||
save_vertex(struct cell_prim_buffer *buf, uint pos,
|
||||
const struct vertex_header *vert)
|
||||
{
|
||||
uint attr, j;
|
||||
|
||||
for (attr = 0; attr < 2; attr++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
buf->vertex[pos][attr][j] = vert->data[attr][j];
|
||||
}
|
||||
}
|
||||
|
||||
/* update bounding box */
|
||||
if (vert->data[0][0] < buf->xmin)
|
||||
buf->xmin = vert->data[0][0];
|
||||
if (vert->data[0][0] > buf->xmax)
|
||||
buf->xmax = vert->data[0][0];
|
||||
if (vert->data[0][1] < buf->ymin)
|
||||
buf->ymin = vert->data[0][1];
|
||||
if (vert->data[0][1] > buf->ymax)
|
||||
buf->ymax = vert->data[0][1];
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
render_tri(struct draw_stage *stage, struct prim_header *prim)
|
||||
{
|
||||
struct render_stage *rs = render_stage(stage);
|
||||
struct cell_context *cell = rs->cell;
|
||||
struct cell_prim_buffer *buf = &cell->prim_buffer;
|
||||
uint i;
|
||||
|
||||
if (buf->num_verts + 3 > CELL_MAX_VERTS) {
|
||||
cell_flush_prim_buffer(cell);
|
||||
}
|
||||
|
||||
i = buf->num_verts;
|
||||
assert(i+2 <= CELL_MAX_VERTS);
|
||||
save_vertex(buf, i+0, prim->v[0]);
|
||||
save_vertex(buf, i+1, prim->v[1]);
|
||||
save_vertex(buf, i+2, prim->v[2]);
|
||||
buf->num_verts += 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send the a RENDER command to all SPUs to have them render the prims
|
||||
* in the current prim_buffer.
|
||||
*/
|
||||
void
|
||||
cell_flush_prim_buffer(struct cell_context *cell)
|
||||
{
|
||||
uint i;
|
||||
|
||||
if (cell->prim_buffer.num_verts == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
struct cell_command_render *render = &cell_global.command[i].render;
|
||||
render->prim_type = PIPE_PRIM_TRIANGLES;
|
||||
render->num_verts = cell->prim_buffer.num_verts;
|
||||
render->front_ccw = cell->rasterizer->front_ccw;
|
||||
render->vertex_size = cell->vertex_info->size * 4;
|
||||
render->xmin = cell->prim_buffer.xmin;
|
||||
render->ymin = cell->prim_buffer.ymin;
|
||||
render->xmax = cell->prim_buffer.xmax;
|
||||
render->ymax = cell->prim_buffer.ymax;
|
||||
render->vertex_data = &cell->prim_buffer.vertex;
|
||||
ASSERT_ALIGN16(render->vertex_data);
|
||||
send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_RENDER);
|
||||
}
|
||||
|
||||
cell->prim_buffer.num_verts = 0;
|
||||
|
||||
cell->prim_buffer.xmin = 1e100;
|
||||
cell->prim_buffer.ymin = 1e100;
|
||||
cell->prim_buffer.xmax = -1e100;
|
||||
cell->prim_buffer.ymax = -1e100;
|
||||
|
||||
/* XXX temporary, need to double-buffer the prim buffer until we get
|
||||
* a real command buffer/list system.
|
||||
*/
|
||||
cell_flush(&cell->pipe, 0x0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void render_destroy( struct draw_stage *stage )
|
||||
{
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new draw/render stage. This will be plugged into the
|
||||
* draw module as the last pipeline stage.
|
||||
*/
|
||||
struct draw_stage *cell_draw_render_stage( struct cell_context *cell )
|
||||
{
|
||||
struct render_stage *render = CALLOC_STRUCT(render_stage);
|
||||
|
||||
render->cell = cell;
|
||||
render->stage.draw = cell->draw;
|
||||
render->stage.begin = render_begin;
|
||||
render->stage.point = render_point;
|
||||
render->stage.line = render_line;
|
||||
render->stage.tri = render_tri;
|
||||
render->stage.end = render_end;
|
||||
render->stage.reset_stipple_counter = reset_stipple_counter;
|
||||
render->stage.destroy = render_destroy;
|
||||
|
||||
/*
|
||||
render->quad.coef = render->coef;
|
||||
render->quad.posCoef = &render->posCoef;
|
||||
*/
|
||||
|
||||
return &render->stage;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CELL_RENDER_H
|
||||
#define CELL_RENDER_H
|
||||
|
||||
struct cell_context;
|
||||
struct draw_stage;
|
||||
|
||||
extern void
|
||||
cell_flush_prim_buffer(struct cell_context *cell);
|
||||
|
||||
extern struct draw_stage *cell_draw_render_stage( struct cell_context *cell );
|
||||
|
||||
#endif /* CELL_RENDER_H */
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_simple_screen.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_screen.h"
|
||||
|
||||
#include "cell/common.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_screen.h"
|
||||
#include "cell_texture.h"
|
||||
#include "cell_public.h"
|
||||
|
||||
#include "state_tracker/sw_winsys.h"
|
||||
|
||||
|
||||
static const char *
|
||||
cell_get_vendor(struct pipe_screen *screen)
|
||||
{
|
||||
return "VMware, Inc.";
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
cell_get_name(struct pipe_screen *screen)
|
||||
{
|
||||
return "Cell";
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cell_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
||||
{
|
||||
switch (param) {
|
||||
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
|
||||
return CELL_MAX_SAMPLERS;
|
||||
case PIPE_CAP_NPOT_TEXTURES:
|
||||
return 1;
|
||||
case PIPE_CAP_TWO_SIDED_STENCIL:
|
||||
return 1;
|
||||
case PIPE_CAP_ANISOTROPIC_FILTER:
|
||||
return 0;
|
||||
case PIPE_CAP_POINT_SPRITE:
|
||||
return 1;
|
||||
case PIPE_CAP_MAX_RENDER_TARGETS:
|
||||
return 1;
|
||||
case PIPE_CAP_OCCLUSION_QUERY:
|
||||
return 1;
|
||||
case PIPE_CAP_TIMER_QUERY:
|
||||
return 0;
|
||||
case PIPE_CAP_TEXTURE_SHADOW_MAP:
|
||||
return 10;
|
||||
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
|
||||
return CELL_MAX_TEXTURE_LEVELS;
|
||||
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
|
||||
return 8; /* max 128x128x128 */
|
||||
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
|
||||
return CELL_MAX_TEXTURE_LEVELS;
|
||||
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
|
||||
return 0; /* XXX to do */
|
||||
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
|
||||
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
|
||||
return 1;
|
||||
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
|
||||
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
|
||||
return 0;
|
||||
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
cell_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
|
||||
{
|
||||
switch(shader)
|
||||
{
|
||||
case PIPE_SHADER_FRAGMENT:
|
||||
switch (param) {
|
||||
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
|
||||
return CELL_MAX_SAMPLERS;
|
||||
default:
|
||||
return tgsi_exec_get_shader_param(param);
|
||||
}
|
||||
case PIPE_SHADER_VERTEX:
|
||||
case PIPE_SHADER_GEOMETRY:
|
||||
return draw_get_shader_param(shader, param);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static float
|
||||
cell_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
|
||||
{
|
||||
switch (param) {
|
||||
case PIPE_CAPF_MAX_LINE_WIDTH:
|
||||
/* fall-through */
|
||||
case PIPE_CAPF_MAX_LINE_WIDTH_AA:
|
||||
return 255.0; /* arbitrary */
|
||||
|
||||
case PIPE_CAPF_MAX_POINT_WIDTH:
|
||||
/* fall-through */
|
||||
case PIPE_CAPF_MAX_POINT_WIDTH_AA:
|
||||
return 255.0; /* arbitrary */
|
||||
|
||||
case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
|
||||
return 0.0;
|
||||
|
||||
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
|
||||
return 16.0; /* arbitrary */
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static boolean
|
||||
cell_is_format_supported( struct pipe_screen *screen,
|
||||
enum pipe_format format,
|
||||
enum pipe_texture_target target,
|
||||
unsigned sample_count,
|
||||
unsigned tex_usage)
|
||||
{
|
||||
struct sw_winsys *winsys = cell_screen(screen)->winsys;
|
||||
|
||||
if (sample_count > 1)
|
||||
return FALSE;
|
||||
|
||||
if (tex_usage & (PIPE_BIND_DISPLAY_TARGET |
|
||||
PIPE_BIND_SCANOUT |
|
||||
PIPE_BIND_SHARED)) {
|
||||
if (!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* only a few formats are known to work at this time */
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
case PIPE_FORMAT_B8G8R8A8_UNORM:
|
||||
case PIPE_FORMAT_I8_UNORM:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_destroy_screen( struct pipe_screen *screen )
|
||||
{
|
||||
struct cell_screen *sp_screen = cell_screen(screen);
|
||||
struct sw_winsys *winsys = sp_screen->winsys;
|
||||
|
||||
if(winsys->destroy)
|
||||
winsys->destroy(winsys);
|
||||
|
||||
FREE(screen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new pipe_screen object
|
||||
* Note: we're not presently subclassing pipe_screen (no cell_screen) but
|
||||
* that would be the place to put SPU thread/context info...
|
||||
*/
|
||||
struct pipe_screen *
|
||||
cell_create_screen(struct sw_winsys *winsys)
|
||||
{
|
||||
struct cell_screen *screen = CALLOC_STRUCT(cell_screen);
|
||||
|
||||
if (!screen)
|
||||
return NULL;
|
||||
|
||||
screen->winsys = winsys;
|
||||
screen->base.winsys = NULL;
|
||||
|
||||
screen->base.destroy = cell_destroy_screen;
|
||||
|
||||
screen->base.get_name = cell_get_name;
|
||||
screen->base.get_vendor = cell_get_vendor;
|
||||
screen->base.get_param = cell_get_param;
|
||||
screen->base.get_shader_param = cell_get_shader_param;
|
||||
screen->base.get_paramf = cell_get_paramf;
|
||||
screen->base.is_format_supported = cell_is_format_supported;
|
||||
screen->base.context_create = cell_create_context;
|
||||
|
||||
cell_init_screen_texture_funcs(&screen->base);
|
||||
|
||||
return &screen->base;
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_SCREEN_H
|
||||
#define CELL_SCREEN_H
|
||||
|
||||
|
||||
#include "pipe/p_screen.h"
|
||||
|
||||
struct sw_winsys;
|
||||
|
||||
struct cell_screen {
|
||||
struct pipe_screen base;
|
||||
|
||||
struct sw_winsys *winsys;
|
||||
|
||||
/* Increments whenever textures are modified. Contexts can track
|
||||
* this.
|
||||
*/
|
||||
unsigned timestamp;
|
||||
};
|
||||
|
||||
static INLINE struct cell_screen *
|
||||
cell_screen( struct pipe_screen *pipe )
|
||||
{
|
||||
return (struct cell_screen *)pipe;
|
||||
}
|
||||
|
||||
|
||||
#endif /* CELL_SCREEN_H */
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Utility/wrappers for communicating with the SPUs.
|
||||
*/
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "cell_spu.h"
|
||||
#include "pipe/p_format.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "cell/common.h"
|
||||
|
||||
|
||||
/*
|
||||
helpful headers:
|
||||
/opt/ibm/cell-sdk/prototype/src/include/ppu/cbe_mfc.h
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Cell/SPU info that's not per-context.
|
||||
*/
|
||||
struct cell_global_info cell_global;
|
||||
|
||||
|
||||
/**
|
||||
* Scan /proc/cpuinfo to determine the timebase for the system.
|
||||
* This is used by the SPUs to convert 'decrementer' ticks to seconds.
|
||||
* There may be a better way to get this value...
|
||||
*/
|
||||
static unsigned
|
||||
get_timebase(void)
|
||||
{
|
||||
FILE *f = fopen("/proc/cpuinfo", "r");
|
||||
unsigned timebase;
|
||||
|
||||
assert(f);
|
||||
while (!feof(f)) {
|
||||
char line[80];
|
||||
fgets(line, sizeof(line), f);
|
||||
if (strncmp(line, "timebase", 8) == 0) {
|
||||
char *colon = strchr(line, ':');
|
||||
if (colon) {
|
||||
timebase = atoi(colon + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return timebase;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write a 1-word message to the given SPE mailbox.
|
||||
*/
|
||||
void
|
||||
send_mbox_message(spe_context_ptr_t ctx, unsigned int msg)
|
||||
{
|
||||
spe_in_mbox_write(ctx, &msg, 1, SPE_MBOX_ALL_BLOCKING);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wait for a 1-word message to arrive in given mailbox.
|
||||
*/
|
||||
uint
|
||||
wait_mbox_message(spe_context_ptr_t ctx)
|
||||
{
|
||||
do {
|
||||
unsigned data;
|
||||
int count = spe_out_mbox_read(ctx, &data, 1);
|
||||
|
||||
if (count == 1) {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (count < 0) {
|
||||
/* error */ ;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by pthread_create() to spawn an SPU thread.
|
||||
*/
|
||||
static void *
|
||||
cell_thread_function(void *arg)
|
||||
{
|
||||
struct cell_init_info *init = (struct cell_init_info *) arg;
|
||||
unsigned entry = SPE_DEFAULT_ENTRY;
|
||||
|
||||
ASSERT_ALIGN16(init);
|
||||
|
||||
if (spe_context_run(cell_global.spe_contexts[init->id], &entry, 0,
|
||||
init, NULL, NULL) < 0) {
|
||||
fprintf(stderr, "spe_context_run() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the SPU threads. This is done once during driver initialization.
|
||||
* This involves setting the "init" message which is sent to each SPU.
|
||||
* The init message specifies an SPU id, total number of SPUs, location
|
||||
* and number of batch buffers, etc.
|
||||
*/
|
||||
void
|
||||
cell_start_spus(struct cell_context *cell)
|
||||
{
|
||||
static boolean one_time_init = FALSE;
|
||||
uint i, j;
|
||||
uint timebase = get_timebase();
|
||||
|
||||
if (one_time_init) {
|
||||
fprintf(stderr, "PPU: Multiple rendering contexts not yet supported "
|
||||
"on Cell.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
one_time_init = TRUE;
|
||||
|
||||
assert(cell->num_spus <= CELL_MAX_SPUS);
|
||||
|
||||
ASSERT_ALIGN16(&cell_global.inits[0]);
|
||||
ASSERT_ALIGN16(&cell_global.inits[1]);
|
||||
|
||||
/*
|
||||
* Initialize the global 'inits' structure for each SPU.
|
||||
* A pointer to the init struct will be passed to each SPU.
|
||||
* The SPUs will then each grab their init info with mfc_get().
|
||||
*/
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
cell_global.inits[i].id = i;
|
||||
cell_global.inits[i].num_spus = cell->num_spus;
|
||||
cell_global.inits[i].debug_flags = cell->debug_flags;
|
||||
cell_global.inits[i].inv_timebase = 1000.0f / timebase;
|
||||
|
||||
for (j = 0; j < CELL_NUM_BUFFERS; j++) {
|
||||
cell_global.inits[i].buffers[j] = cell->buffer[j];
|
||||
}
|
||||
cell_global.inits[i].buffer_status = &cell->buffer_status[0][0][0];
|
||||
|
||||
cell_global.inits[i].spu_functions = &cell->spu_functions;
|
||||
|
||||
cell_global.spe_contexts[i] = spe_context_create(0, NULL);
|
||||
if (!cell_global.spe_contexts[i]) {
|
||||
fprintf(stderr, "spe_context_create() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (spe_program_load(cell_global.spe_contexts[i], &g3d_spu)) {
|
||||
fprintf(stderr, "spe_program_load() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_create(&cell_global.spe_threads[i], /* returned thread handle */
|
||||
NULL, /* pthread attribs */
|
||||
&cell_thread_function, /* start routine */
|
||||
&cell_global.inits[i]); /* thread argument */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tell all the SPUs to stop/exit.
|
||||
* This is done when the driver's exiting / cleaning up.
|
||||
*/
|
||||
void
|
||||
cell_spu_exit(struct cell_context *cell)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_EXIT);
|
||||
}
|
||||
|
||||
/* wait for threads to exit */
|
||||
for (i = 0; i < cell->num_spus; i++) {
|
||||
void *value;
|
||||
pthread_join(cell_global.spe_threads[i], &value);
|
||||
cell_global.spe_threads[i] = 0;
|
||||
cell_global.spe_contexts[i] = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CELL_SPU
|
||||
#define CELL_SPU
|
||||
|
||||
|
||||
#include <libspe2.h>
|
||||
#include <pthread.h>
|
||||
#include "cell/common.h"
|
||||
|
||||
#include "cell_context.h"
|
||||
|
||||
|
||||
/**
|
||||
* Global vars, for now anyway.
|
||||
*/
|
||||
struct cell_global_info
|
||||
{
|
||||
/**
|
||||
* SPU/SPE handles, etc
|
||||
*/
|
||||
spe_context_ptr_t spe_contexts[CELL_MAX_SPUS];
|
||||
pthread_t spe_threads[CELL_MAX_SPUS];
|
||||
|
||||
/**
|
||||
* Data sent to SPUs at start-up
|
||||
*/
|
||||
struct cell_init_info inits[CELL_MAX_SPUS];
|
||||
};
|
||||
|
||||
|
||||
extern struct cell_global_info cell_global;
|
||||
|
||||
|
||||
/** This is the handle for the actual SPE code */
|
||||
extern spe_program_handle_t g3d_spu;
|
||||
|
||||
|
||||
extern void
|
||||
send_mbox_message(spe_context_ptr_t ctx, unsigned int msg);
|
||||
|
||||
extern uint
|
||||
wait_mbox_message(spe_context_ptr_t ctx);
|
||||
|
||||
|
||||
extern void
|
||||
cell_start_spus(struct cell_context *cell);
|
||||
|
||||
|
||||
extern void
|
||||
cell_spu_exit(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_SPU */
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CELL_STATE_H
|
||||
#define CELL_STATE_H
|
||||
|
||||
|
||||
#define CELL_NEW_VIEWPORT 0x1
|
||||
#define CELL_NEW_RASTERIZER 0x2
|
||||
#define CELL_NEW_FS 0x4
|
||||
#define CELL_NEW_BLEND 0x8
|
||||
#define CELL_NEW_CLIP 0x10
|
||||
#define CELL_NEW_SCISSOR 0x20
|
||||
#define CELL_NEW_STIPPLE 0x40
|
||||
#define CELL_NEW_FRAMEBUFFER 0x80
|
||||
#define CELL_NEW_ALPHA_TEST 0x100
|
||||
#define CELL_NEW_DEPTH_STENCIL 0x200
|
||||
#define CELL_NEW_SAMPLER 0x400
|
||||
#define CELL_NEW_TEXTURE 0x800
|
||||
#define CELL_NEW_VERTEX 0x1000
|
||||
#define CELL_NEW_VS 0x2000
|
||||
#define CELL_NEW_VS_CONSTANTS 0x4000
|
||||
#define CELL_NEW_FS_CONSTANTS 0x8000
|
||||
#define CELL_NEW_VERTEX_INFO 0x10000
|
||||
|
||||
|
||||
extern void
|
||||
cell_update_derived( struct cell_context *cell );
|
||||
|
||||
|
||||
extern void
|
||||
cell_init_shader_functions(struct cell_context *cell);
|
||||
|
||||
|
||||
extern void
|
||||
cell_init_vertex_functions(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_STATE_H */
|
||||
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_vertex.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_batch.h"
|
||||
#include "cell_state.h"
|
||||
#include "cell_state_emit.h"
|
||||
|
||||
|
||||
/**
|
||||
* Determine how to map vertex program outputs to fragment program inputs.
|
||||
* Basically, this will be used when computing the triangle interpolation
|
||||
* coefficients from the post-transform vertex attributes.
|
||||
*/
|
||||
static void
|
||||
calculate_vertex_layout( struct cell_context *cell )
|
||||
{
|
||||
const struct cell_fragment_shader_state *fs = cell->fs;
|
||||
const enum interp_mode colorInterp
|
||||
= cell->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
|
||||
struct vertex_info *vinfo = &cell->vertex_info;
|
||||
uint i;
|
||||
int src;
|
||||
|
||||
#if 0
|
||||
if (cell->vbuf) {
|
||||
/* if using the post-transform vertex buffer, tell draw_vbuf to
|
||||
* simply emit the whole post-xform vertex as-is:
|
||||
*/
|
||||
struct vertex_info *vinfo_vbuf = &cell->vertex_info_vbuf;
|
||||
vinfo_vbuf->num_attribs = 0;
|
||||
draw_emit_vertex_attr(vinfo_vbuf, EMIT_ALL, INTERP_NONE, 0);
|
||||
vinfo_vbuf->size = 4 * vs->num_outputs + sizeof(struct vertex_header)/4;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* reset vinfo */
|
||||
vinfo->num_attribs = 0;
|
||||
|
||||
/* we always want to emit vertex pos */
|
||||
src = draw_find_shader_output(cell->draw, TGSI_SEMANTIC_POSITION, 0);
|
||||
assert(src >= 0);
|
||||
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_POS, src);
|
||||
|
||||
|
||||
/*
|
||||
* Loop over fragment shader inputs, searching for the matching output
|
||||
* from the vertex shader.
|
||||
*/
|
||||
for (i = 0; i < fs->info.num_inputs; i++) {
|
||||
switch (fs->info.input_semantic_name[i]) {
|
||||
case TGSI_SEMANTIC_POSITION:
|
||||
/* already done above */
|
||||
break;
|
||||
|
||||
case TGSI_SEMANTIC_COLOR:
|
||||
src = draw_find_shader_output(cell->draw, TGSI_SEMANTIC_COLOR,
|
||||
fs->info.input_semantic_index[i]);
|
||||
assert(src >= 0);
|
||||
draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
|
||||
break;
|
||||
|
||||
case TGSI_SEMANTIC_FOG:
|
||||
src = draw_find_shader_output(cell->draw, TGSI_SEMANTIC_FOG, 0);
|
||||
#if 1
|
||||
if (src < 0) /* XXX temp hack, try demos/fogcoord.c with this */
|
||||
src = 0;
|
||||
#endif
|
||||
assert(src >= 0);
|
||||
draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
|
||||
break;
|
||||
|
||||
case TGSI_SEMANTIC_GENERIC:
|
||||
/* this includes texcoords and varying vars */
|
||||
src = draw_find_shader_output(cell->draw, TGSI_SEMANTIC_GENERIC,
|
||||
fs->info.input_semantic_index[i]);
|
||||
assert(src >= 0);
|
||||
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
draw_compute_vertex_size(vinfo);
|
||||
|
||||
/* XXX only signal this if format really changes */
|
||||
cell->dirty |= CELL_NEW_VERTEX_INFO;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Recompute cliprect from scissor bounds, scissor enable and surface size.
|
||||
*/
|
||||
static void
|
||||
compute_cliprect(struct cell_context *sp)
|
||||
{
|
||||
uint surfWidth = sp->framebuffer.width;
|
||||
uint surfHeight = sp->framebuffer.height;
|
||||
|
||||
if (sp->rasterizer->scissor) {
|
||||
/* clip to scissor rect */
|
||||
sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
|
||||
sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
|
||||
sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
|
||||
sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
|
||||
}
|
||||
else {
|
||||
/* clip to surface bounds */
|
||||
sp->cliprect.minx = 0;
|
||||
sp->cliprect.miny = 0;
|
||||
sp->cliprect.maxx = surfWidth;
|
||||
sp->cliprect.maxy = surfHeight;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update derived state, send current state to SPUs prior to rendering.
|
||||
*/
|
||||
void cell_update_derived( struct cell_context *cell )
|
||||
{
|
||||
if (cell->dirty & (CELL_NEW_RASTERIZER |
|
||||
CELL_NEW_FS |
|
||||
CELL_NEW_VS))
|
||||
calculate_vertex_layout( cell );
|
||||
|
||||
#if 0
|
||||
if (cell->dirty & (CELL_NEW_SCISSOR |
|
||||
CELL_NEW_DEPTH_STENCIL_ALPHA |
|
||||
CELL_NEW_FRAMEBUFFER))
|
||||
compute_cliprect(cell);
|
||||
#endif
|
||||
|
||||
cell_emit_state(cell);
|
||||
|
||||
cell->dirty = 0;
|
||||
}
|
||||
|
|
@ -1,343 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_format.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_gen_fragment.h"
|
||||
#include "cell_state.h"
|
||||
#include "cell_state_emit.h"
|
||||
#include "cell_batch.h"
|
||||
#include "cell_texture.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_private.h"
|
||||
|
||||
|
||||
/**
|
||||
* Find/create a cell_command_fragment_ops object corresponding to the
|
||||
* current blend/stencil/z/colormask/etc. state.
|
||||
*/
|
||||
static struct cell_command_fragment_ops *
|
||||
lookup_fragment_ops(struct cell_context *cell)
|
||||
{
|
||||
struct cell_fragment_ops_key key;
|
||||
struct cell_command_fragment_ops *ops;
|
||||
|
||||
/*
|
||||
* Build key
|
||||
*/
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.blend = *cell->blend;
|
||||
key.blend_color = cell->blend_color;
|
||||
key.dsa = *cell->depth_stencil;
|
||||
|
||||
if (cell->framebuffer.cbufs[0])
|
||||
key.color_format = cell->framebuffer.cbufs[0]->format;
|
||||
else
|
||||
key.color_format = PIPE_FORMAT_NONE;
|
||||
|
||||
if (cell->framebuffer.zsbuf)
|
||||
key.zs_format = cell->framebuffer.zsbuf->format;
|
||||
else
|
||||
key.zs_format = PIPE_FORMAT_NONE;
|
||||
|
||||
/*
|
||||
* Look up key in cache.
|
||||
*/
|
||||
ops = (struct cell_command_fragment_ops *)
|
||||
util_keymap_lookup(cell->fragment_ops_cache, &key);
|
||||
|
||||
/*
|
||||
* If not found, create/save new fragment ops command.
|
||||
*/
|
||||
if (!ops) {
|
||||
struct spe_function spe_code_front, spe_code_back;
|
||||
unsigned int facing_dependent, total_code_size;
|
||||
|
||||
if (0)
|
||||
debug_printf("**** Create New Fragment Ops\n");
|
||||
|
||||
/* Prepare the buffer that will hold the generated code. The
|
||||
* "0" passed in for the size means that the SPE code will
|
||||
* use a default size.
|
||||
*/
|
||||
spe_init_func(&spe_code_front, 0);
|
||||
spe_init_func(&spe_code_back, 0);
|
||||
|
||||
/* Generate new code. Always generate new code for both front-facing
|
||||
* and back-facing fragments, even if it's the same code in both
|
||||
* cases.
|
||||
*/
|
||||
cell_gen_fragment_function(cell, CELL_FACING_FRONT, &spe_code_front);
|
||||
cell_gen_fragment_function(cell, CELL_FACING_BACK, &spe_code_back);
|
||||
|
||||
/* Make sure the code is a multiple of 8 bytes long; this is
|
||||
* required to ensure that the dual pipe instruction alignment
|
||||
* is correct. It's also important for the SPU unpacking,
|
||||
* which assumes 8-byte boundaries.
|
||||
*/
|
||||
unsigned int front_code_size = spe_code_size(&spe_code_front);
|
||||
while (front_code_size % 8 != 0) {
|
||||
spe_lnop(&spe_code_front);
|
||||
front_code_size = spe_code_size(&spe_code_front);
|
||||
}
|
||||
unsigned int back_code_size = spe_code_size(&spe_code_back);
|
||||
while (back_code_size % 8 != 0) {
|
||||
spe_lnop(&spe_code_back);
|
||||
back_code_size = spe_code_size(&spe_code_back);
|
||||
}
|
||||
|
||||
/* Determine whether the code we generated is facing-dependent, by
|
||||
* determining whether the generated code is different for the front-
|
||||
* and back-facing fragments.
|
||||
*/
|
||||
if (front_code_size == back_code_size && memcmp(spe_code_front.store, spe_code_back.store, front_code_size) == 0) {
|
||||
/* Code is identical; only need one copy. */
|
||||
facing_dependent = 0;
|
||||
total_code_size = front_code_size;
|
||||
}
|
||||
else {
|
||||
/* Code is different for front-facing and back-facing fragments.
|
||||
* Need to send both copies.
|
||||
*/
|
||||
facing_dependent = 1;
|
||||
total_code_size = front_code_size + back_code_size;
|
||||
}
|
||||
|
||||
/* alloc new fragment ops command. Note that this structure
|
||||
* has variant length based on the total code size required.
|
||||
*/
|
||||
ops = CALLOC_VARIANT_LENGTH_STRUCT(cell_command_fragment_ops, total_code_size);
|
||||
/* populate the new cell_command_fragment_ops object */
|
||||
ops->opcode[0] = CELL_CMD_STATE_FRAGMENT_OPS;
|
||||
ops->total_code_size = total_code_size;
|
||||
ops->front_code_index = 0;
|
||||
memcpy(ops->code, spe_code_front.store, front_code_size);
|
||||
if (facing_dependent) {
|
||||
/* We have separate front- and back-facing code. Append the
|
||||
* back-facing code to the buffer. Be careful because the code
|
||||
* size is in bytes, but the buffer is of unsigned elements.
|
||||
*/
|
||||
ops->back_code_index = front_code_size / sizeof(spe_code_front.store[0]);
|
||||
memcpy(ops->code + ops->back_code_index, spe_code_back.store, back_code_size);
|
||||
}
|
||||
else {
|
||||
/* Use the same code for front- and back-facing fragments */
|
||||
ops->back_code_index = ops->front_code_index;
|
||||
}
|
||||
|
||||
/* Set the fields for the fallback case. Note that these fields
|
||||
* (and the whole fallback case) will eventually go away.
|
||||
*/
|
||||
ops->dsa = *cell->depth_stencil;
|
||||
ops->blend = *cell->blend;
|
||||
ops->blend_color = cell->blend_color;
|
||||
|
||||
/* insert cell_command_fragment_ops object into keymap/cache */
|
||||
util_keymap_insert(cell->fragment_ops_cache, &key, ops, NULL);
|
||||
|
||||
/* release rtasm buffer */
|
||||
spe_release_func(&spe_code_front);
|
||||
spe_release_func(&spe_code_back);
|
||||
}
|
||||
else {
|
||||
if (0)
|
||||
debug_printf("**** Re-use Fragment Ops\n");
|
||||
}
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
emit_state_cmd(struct cell_context *cell, uint cmd,
|
||||
const void *state, uint state_size)
|
||||
{
|
||||
uint32_t *dst = (uint32_t *)
|
||||
cell_batch_alloc16(cell, ROUNDUP16(sizeof(opcode_t) + state_size));
|
||||
*dst = cmd;
|
||||
memcpy(dst + 4, state, state_size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For state marked as 'dirty', construct a state-update command block
|
||||
* and insert it into the current batch buffer.
|
||||
*/
|
||||
void
|
||||
cell_emit_state(struct cell_context *cell)
|
||||
{
|
||||
if (cell->dirty & CELL_NEW_FRAMEBUFFER) {
|
||||
struct pipe_surface *cbuf = cell->framebuffer.cbufs[0];
|
||||
struct pipe_surface *zbuf = cell->framebuffer.zsbuf;
|
||||
STATIC_ASSERT(sizeof(struct cell_command_framebuffer) % 16 == 0);
|
||||
struct cell_command_framebuffer *fb
|
||||
= cell_batch_alloc16(cell, sizeof(*fb));
|
||||
fb->opcode[0] = CELL_CMD_STATE_FRAMEBUFFER;
|
||||
fb->color_start = cell->cbuf_map[0];
|
||||
fb->color_format = cbuf->format;
|
||||
fb->depth_start = cell->zsbuf_map;
|
||||
fb->depth_format = zbuf ? zbuf->format : PIPE_FORMAT_NONE;
|
||||
fb->width = cell->framebuffer.width;
|
||||
fb->height = cell->framebuffer.height;
|
||||
#if 0
|
||||
printf("EMIT color format %s\n", util_format_name(fb->color_format));
|
||||
printf("EMIT depth format %s\n", util_format_name(fb->depth_format));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cell->dirty & (CELL_NEW_RASTERIZER)) {
|
||||
STATIC_ASSERT(sizeof(struct cell_command_rasterizer) % 16 == 0);
|
||||
struct cell_command_rasterizer *rast =
|
||||
cell_batch_alloc16(cell, sizeof(*rast));
|
||||
rast->opcode[0] = CELL_CMD_STATE_RASTERIZER;
|
||||
rast->rasterizer = *cell->rasterizer;
|
||||
}
|
||||
|
||||
if (cell->dirty & (CELL_NEW_FS)) {
|
||||
/* Send new fragment program to SPUs */
|
||||
STATIC_ASSERT(sizeof(struct cell_command_fragment_program) % 16 == 0);
|
||||
struct cell_command_fragment_program *fp
|
||||
= cell_batch_alloc16(cell, sizeof(*fp));
|
||||
fp->opcode[0] = CELL_CMD_STATE_FRAGMENT_PROGRAM;
|
||||
fp->num_inst = cell->fs->code.num_inst;
|
||||
memcpy(&fp->code, cell->fs->code.store,
|
||||
SPU_MAX_FRAGMENT_PROGRAM_INSTS * SPE_INST_SIZE);
|
||||
if (0) {
|
||||
int i;
|
||||
printf("PPU Emit CELL_CMD_STATE_FRAGMENT_PROGRAM:\n");
|
||||
for (i = 0; i < fp->num_inst; i++) {
|
||||
printf(" %3d: 0x%08x\n", i, fp->code[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->dirty & (CELL_NEW_FS_CONSTANTS)) {
|
||||
const uint shader = PIPE_SHADER_FRAGMENT;
|
||||
const uint num_const = cell->constants[shader]->width0 / sizeof(float);
|
||||
uint i, j;
|
||||
float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float)));
|
||||
uint32_t *ibuf = (uint32_t *) buf;
|
||||
const float *constants = cell->mapped_constants[shader];
|
||||
ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS;
|
||||
ibuf[4] = num_const;
|
||||
j = 8;
|
||||
for (i = 0; i < num_const; i++) {
|
||||
buf[j++] = constants[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->dirty & (CELL_NEW_FRAMEBUFFER |
|
||||
CELL_NEW_DEPTH_STENCIL |
|
||||
CELL_NEW_BLEND)) {
|
||||
struct cell_command_fragment_ops *fops, *fops_cmd;
|
||||
/* Note that cell_command_fragment_ops is a variant-sized record */
|
||||
fops = lookup_fragment_ops(cell);
|
||||
fops_cmd = cell_batch_alloc16(cell, ROUNDUP16(sizeof(*fops_cmd) + fops->total_code_size));
|
||||
memcpy(fops_cmd, fops, sizeof(*fops) + fops->total_code_size);
|
||||
}
|
||||
|
||||
if (cell->dirty & CELL_NEW_SAMPLER) {
|
||||
uint i;
|
||||
for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
|
||||
if (cell->dirty_samplers & (1 << i)) {
|
||||
if (cell->sampler[i]) {
|
||||
STATIC_ASSERT(sizeof(struct cell_command_sampler) % 16 == 0);
|
||||
struct cell_command_sampler *sampler
|
||||
= cell_batch_alloc16(cell, sizeof(*sampler));
|
||||
sampler->opcode[0] = CELL_CMD_STATE_SAMPLER;
|
||||
sampler->unit = i;
|
||||
sampler->state = *cell->sampler[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
cell->dirty_samplers = 0x0;
|
||||
}
|
||||
|
||||
if (cell->dirty & CELL_NEW_TEXTURE) {
|
||||
uint i;
|
||||
for (i = 0;i < CELL_MAX_SAMPLERS; i++) {
|
||||
if (cell->dirty_textures & (1 << i)) {
|
||||
STATIC_ASSERT(sizeof(struct cell_command_texture) % 16 == 0);
|
||||
struct cell_command_texture *texture =
|
||||
(struct cell_command_texture *)
|
||||
cell_batch_alloc16(cell, sizeof(*texture));
|
||||
|
||||
texture->opcode[0] = CELL_CMD_STATE_TEXTURE;
|
||||
texture->unit = i;
|
||||
if (cell->texture[i]) {
|
||||
struct cell_resource *ct = cell->texture[i];
|
||||
uint level;
|
||||
for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
|
||||
texture->start[level] = (ct->mapped +
|
||||
ct->level_offset[level]);
|
||||
texture->width[level] = u_minify(ct->base.width0, level);
|
||||
texture->height[level] = u_minify(ct->base.height0, level);
|
||||
texture->depth[level] = u_minify(ct->base.depth0, level);
|
||||
}
|
||||
texture->target = ct->base.target;
|
||||
}
|
||||
else {
|
||||
uint level;
|
||||
for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
|
||||
texture->start[level] = NULL;
|
||||
texture->width[level] = 0;
|
||||
texture->height[level] = 0;
|
||||
texture->depth[level] = 0;
|
||||
}
|
||||
texture->target = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
cell->dirty_textures = 0x0;
|
||||
}
|
||||
|
||||
if (cell->dirty & CELL_NEW_VERTEX_INFO) {
|
||||
emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO,
|
||||
&cell->vertex_info, sizeof(struct vertex_info));
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (cell->dirty & CELL_NEW_VS) {
|
||||
const struct draw_context *const draw = cell->draw;
|
||||
struct cell_shader_info info;
|
||||
|
||||
info.num_outputs = draw_num_shader_outputs(draw);
|
||||
info.declarations = (uintptr_t) draw->vs.machine.Declarations;
|
||||
info.num_declarations = draw->vs.machine.NumDeclarations;
|
||||
info.instructions = (uintptr_t) draw->vs.machine.Instructions;
|
||||
info.num_instructions = draw->vs.machine.NumInstructions;
|
||||
info.immediates = (uintptr_t) draw->vs.machine.Imms;
|
||||
info.num_immediates = draw->vs.machine.ImmLimit / 4;
|
||||
|
||||
emit_state_cmd(cell, CELL_CMD_STATE_BIND_VS, &info, sizeof(info));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CELL_STATE_EMIT_H
|
||||
#define CELL_STATE_EMIT_H
|
||||
|
||||
|
||||
extern void
|
||||
cell_emit_state(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_STATE_EMIT_H */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright IBM Corporation 2008
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR 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.
|
||||
*/
|
||||
|
||||
#ifndef CELL_STATE_PER_FRAGMENT_H
|
||||
#define CELL_STATE_PER_FRAGMENT_H
|
||||
|
||||
extern void
|
||||
cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa);
|
||||
|
||||
extern void
|
||||
cell_generate_alpha_blend(struct cell_blend_state *cb);
|
||||
|
||||
extern void
|
||||
cell_generate_logic_op(struct spe_function *f,
|
||||
const struct pipe_blend_state *blend,
|
||||
struct pipe_surface *surf);
|
||||
|
||||
#endif /* CELL_STATE_PER_FRAGMENT_H */
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "cell_state.h"
|
||||
#include "cell_gen_fp.h"
|
||||
#include "cell_texture.h"
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static INLINE struct cell_fragment_shader_state *
|
||||
cell_fragment_shader_state(void *shader)
|
||||
{
|
||||
return (struct cell_fragment_shader_state *) shader;
|
||||
}
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static INLINE struct cell_vertex_shader_state *
|
||||
cell_vertex_shader_state(void *shader)
|
||||
{
|
||||
return (struct cell_vertex_shader_state *) shader;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create fragment shader state.
|
||||
* Called via pipe->create_fs_state()
|
||||
*/
|
||||
static void *
|
||||
cell_create_fs_state(struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
struct cell_fragment_shader_state *cfs;
|
||||
|
||||
cfs = CALLOC_STRUCT(cell_fragment_shader_state);
|
||||
if (!cfs)
|
||||
return NULL;
|
||||
|
||||
cfs->shader.tokens = tgsi_dup_tokens(templ->tokens);
|
||||
if (!cfs->shader.tokens) {
|
||||
FREE(cfs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tgsi_scan_shader(templ->tokens, &cfs->info);
|
||||
|
||||
cell_gen_fragment_program(cell, cfs->shader.tokens, &cfs->code);
|
||||
|
||||
return cfs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->bind_fs_state()
|
||||
*/
|
||||
static void
|
||||
cell_bind_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
cell->fs = cell_fragment_shader_state(fs);
|
||||
|
||||
cell->dirty |= CELL_NEW_FS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->delete_fs_state()
|
||||
*/
|
||||
static void
|
||||
cell_delete_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct cell_fragment_shader_state *cfs = cell_fragment_shader_state(fs);
|
||||
|
||||
spe_release_func(&cfs->code);
|
||||
|
||||
FREE((void *) cfs->shader.tokens);
|
||||
FREE(cfs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create vertex shader state.
|
||||
* Called via pipe->create_vs_state()
|
||||
*/
|
||||
static void *
|
||||
cell_create_vs_state(struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
struct cell_vertex_shader_state *cvs;
|
||||
|
||||
cvs = CALLOC_STRUCT(cell_vertex_shader_state);
|
||||
if (!cvs)
|
||||
return NULL;
|
||||
|
||||
cvs->shader.tokens = tgsi_dup_tokens(templ->tokens);
|
||||
if (!cvs->shader.tokens) {
|
||||
FREE(cvs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tgsi_scan_shader(templ->tokens, &cvs->info);
|
||||
|
||||
cvs->draw_data = draw_create_vertex_shader(cell->draw, &cvs->shader);
|
||||
if (cvs->draw_data == NULL) {
|
||||
FREE( (void *) cvs->shader.tokens );
|
||||
FREE( cvs );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cvs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->bind_vs_state()
|
||||
*/
|
||||
static void
|
||||
cell_bind_vs_state(struct pipe_context *pipe, void *vs)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
cell->vs = cell_vertex_shader_state(vs);
|
||||
|
||||
draw_bind_vertex_shader(cell->draw,
|
||||
(cell->vs ? cell->vs->draw_data : NULL));
|
||||
|
||||
cell->dirty |= CELL_NEW_VS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->delete_vs_state()
|
||||
*/
|
||||
static void
|
||||
cell_delete_vs_state(struct pipe_context *pipe, void *vs)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
struct cell_vertex_shader_state *cvs = cell_vertex_shader_state(vs);
|
||||
|
||||
draw_delete_vertex_shader(cell->draw, cvs->draw_data);
|
||||
FREE( (void *) cvs->shader.tokens );
|
||||
FREE( cvs );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->set_constant_buffer()
|
||||
*/
|
||||
static void
|
||||
cell_set_constant_buffer(struct pipe_context *pipe,
|
||||
uint shader, uint index,
|
||||
struct pipe_resource *constants)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
unsigned size = constants ? constants->width0 : 0;
|
||||
const void *data = constants ? cell_resource(constants)->data : NULL;
|
||||
|
||||
assert(shader < PIPE_SHADER_TYPES);
|
||||
assert(index == 0);
|
||||
|
||||
if (cell->constants[shader] == constants)
|
||||
return;
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
/* note: reference counting */
|
||||
pipe_resource_reference(&cell->constants[shader], constants);
|
||||
|
||||
if(shader == PIPE_SHADER_VERTEX) {
|
||||
draw_set_mapped_constant_buffer(cell->draw, PIPE_SHADER_VERTEX, 0,
|
||||
data, size);
|
||||
}
|
||||
|
||||
cell->mapped_constants[shader] = data;
|
||||
|
||||
if (shader == PIPE_SHADER_VERTEX)
|
||||
cell->dirty |= CELL_NEW_VS_CONSTANTS;
|
||||
else if (shader == PIPE_SHADER_FRAGMENT)
|
||||
cell->dirty |= CELL_NEW_FS_CONSTANTS;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cell_init_shader_functions(struct cell_context *cell)
|
||||
{
|
||||
cell->pipe.create_fs_state = cell_create_fs_state;
|
||||
cell->pipe.bind_fs_state = cell_bind_fs_state;
|
||||
cell->pipe.delete_fs_state = cell_delete_fs_state;
|
||||
|
||||
cell->pipe.create_vs_state = cell_create_vs_state;
|
||||
cell->pipe.bind_vs_state = cell_bind_vs_state;
|
||||
cell->pipe.delete_vs_state = cell_delete_vs_state;
|
||||
|
||||
cell->pipe.set_constant_buffer = cell_set_constant_buffer;
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "cell_state.h"
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_transfer.h"
|
||||
#include "draw/draw_context.h"
|
||||
|
||||
|
||||
static void *
|
||||
cell_create_vertex_elements_state(struct pipe_context *pipe,
|
||||
unsigned count,
|
||||
const struct pipe_vertex_element *attribs)
|
||||
{
|
||||
struct cell_velems_state *velems;
|
||||
assert(count <= PIPE_MAX_ATTRIBS);
|
||||
velems = (struct cell_velems_state *) MALLOC(sizeof(struct cell_velems_state));
|
||||
if (velems) {
|
||||
velems->count = count;
|
||||
memcpy(velems->velem, attribs, sizeof(*attribs) * count);
|
||||
}
|
||||
return velems;
|
||||
}
|
||||
|
||||
static void
|
||||
cell_bind_vertex_elements_state(struct pipe_context *pipe,
|
||||
void *velems)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
struct cell_velems_state *cell_velems = (struct cell_velems_state *) velems;
|
||||
|
||||
cell->velems = cell_velems;
|
||||
|
||||
cell->dirty |= CELL_NEW_VERTEX;
|
||||
|
||||
if (cell_velems)
|
||||
draw_set_vertex_elements(cell->draw, cell_velems->count, cell_velems->velem);
|
||||
}
|
||||
|
||||
static void
|
||||
cell_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
|
||||
{
|
||||
FREE( velems );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_vertex_buffers(struct pipe_context *pipe,
|
||||
unsigned count,
|
||||
const struct pipe_vertex_buffer *buffers)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
assert(count <= PIPE_MAX_ATTRIBS);
|
||||
|
||||
util_copy_vertex_buffers(cell->vertex_buffer,
|
||||
&cell->num_vertex_buffers,
|
||||
buffers, count);
|
||||
|
||||
cell->dirty |= CELL_NEW_VERTEX;
|
||||
|
||||
draw_set_vertex_buffers(cell->draw, count, buffers);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_set_index_buffer(struct pipe_context *pipe,
|
||||
const struct pipe_index_buffer *ib)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
if (ib)
|
||||
memcpy(&cell->index_buffer, ib, sizeof(cell->index_buffer));
|
||||
else
|
||||
memset(&cell->index_buffer, 0, sizeof(cell->index_buffer));
|
||||
|
||||
draw_set_index_buffer(cell->draw, ib);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cell_init_vertex_functions(struct cell_context *cell)
|
||||
{
|
||||
cell->pipe.set_vertex_buffers = cell_set_vertex_buffers;
|
||||
cell->pipe.set_index_buffer = cell_set_index_buffer;
|
||||
cell->pipe.create_vertex_elements_state = cell_create_vertex_elements_state;
|
||||
cell->pipe.bind_vertex_elements_state = cell_bind_vertex_elements_state;
|
||||
cell->pipe.delete_vertex_elements_state = cell_delete_vertex_elements_state;
|
||||
cell->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "util/u_surface.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_surface.h"
|
||||
|
||||
|
||||
void
|
||||
cell_init_surface_functions(struct cell_context *cell)
|
||||
{
|
||||
cell->pipe.resource_copy_region = util_resource_copy_region;
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#ifndef CELL_SURFACE_H
|
||||
#define CELL_SURFACE_H
|
||||
|
||||
|
||||
struct cell_context;
|
||||
|
||||
|
||||
extern void
|
||||
cell_init_surface_functions(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* SP_SURFACE_H */
|
||||
|
|
@ -1,644 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Michel Dänzer <michel@tungstengraphics.com>
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_transfer.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "cell_screen.h"
|
||||
#include "cell_state.h"
|
||||
#include "cell_texture.h"
|
||||
|
||||
#include "state_tracker/sw_winsys.h"
|
||||
|
||||
|
||||
|
||||
static boolean
|
||||
cell_resource_layout(struct pipe_screen *screen,
|
||||
struct cell_resource *ct)
|
||||
{
|
||||
struct pipe_resource *pt = &ct->base;
|
||||
unsigned level;
|
||||
unsigned width = pt->width0;
|
||||
unsigned height = pt->height0;
|
||||
unsigned depth = pt->depth0;
|
||||
|
||||
ct->buffer_size = 0;
|
||||
|
||||
for (level = 0; level <= pt->last_level; level++) {
|
||||
unsigned size;
|
||||
unsigned w_tile, h_tile;
|
||||
|
||||
assert(level < CELL_MAX_TEXTURE_LEVELS);
|
||||
|
||||
/* width, height, rounded up to tile size */
|
||||
w_tile = align(width, TILE_SIZE);
|
||||
h_tile = align(height, TILE_SIZE);
|
||||
|
||||
ct->stride[level] = util_format_get_stride(pt->format, w_tile);
|
||||
|
||||
ct->level_offset[level] = ct->buffer_size;
|
||||
|
||||
size = ct->stride[level] * util_format_get_nblocksy(pt->format, h_tile);
|
||||
if (pt->target == PIPE_TEXTURE_CUBE)
|
||||
size *= 6;
|
||||
else
|
||||
size *= depth;
|
||||
|
||||
ct->buffer_size += size;
|
||||
|
||||
width = u_minify(width, 1);
|
||||
height = u_minify(height, 1);
|
||||
depth = u_minify(depth, 1);
|
||||
}
|
||||
|
||||
ct->data = align_malloc(ct->buffer_size, 16);
|
||||
|
||||
return ct->data != NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Texture layout for simple color buffers.
|
||||
*/
|
||||
static boolean
|
||||
cell_displaytarget_layout(struct pipe_screen *screen,
|
||||
struct cell_resource * ct)
|
||||
{
|
||||
struct sw_winsys *winsys = cell_screen(screen)->winsys;
|
||||
|
||||
/* Round up the surface size to a multiple of the tile size?
|
||||
*/
|
||||
ct->dt = winsys->displaytarget_create(winsys,
|
||||
ct->base.bind,
|
||||
ct->base.format,
|
||||
ct->base.width0,
|
||||
ct->base.height0,
|
||||
16,
|
||||
&ct->dt_stride );
|
||||
|
||||
return ct->dt != NULL;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
cell_resource_create(struct pipe_screen *screen,
|
||||
const struct pipe_resource *templat)
|
||||
{
|
||||
struct cell_resource *ct = CALLOC_STRUCT(cell_resource);
|
||||
if (!ct)
|
||||
return NULL;
|
||||
|
||||
ct->base = *templat;
|
||||
pipe_reference_init(&ct->base.reference, 1);
|
||||
ct->base.screen = screen;
|
||||
|
||||
/* Create both a displaytarget (linear) and regular texture
|
||||
* (twiddled). Convert twiddled->linear at flush_frontbuffer time.
|
||||
*/
|
||||
if (ct->base.bind & (PIPE_BIND_DISPLAY_TARGET |
|
||||
PIPE_BIND_SCANOUT |
|
||||
PIPE_BIND_SHARED)) {
|
||||
if (!cell_displaytarget_layout(screen, ct))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!cell_resource_layout(screen, ct))
|
||||
goto fail;
|
||||
|
||||
return &ct->base;
|
||||
|
||||
fail:
|
||||
if (ct->dt) {
|
||||
struct sw_winsys *winsys = cell_screen(screen)->winsys;
|
||||
winsys->displaytarget_destroy(winsys, ct->dt);
|
||||
}
|
||||
|
||||
FREE(ct);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_resource_destroy(struct pipe_screen *scrn, struct pipe_resource *pt)
|
||||
{
|
||||
struct cell_screen *screen = cell_screen(scrn);
|
||||
struct sw_winsys *winsys = screen->winsys;
|
||||
struct cell_resource *ct = cell_resource(pt);
|
||||
|
||||
if (ct->dt) {
|
||||
/* display target */
|
||||
winsys->displaytarget_destroy(winsys, ct->dt);
|
||||
}
|
||||
else if (!ct->userBuffer) {
|
||||
align_free(ct->data);
|
||||
}
|
||||
|
||||
FREE(ct);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert image from linear layout to tiled layout. 4-byte pixels.
|
||||
*/
|
||||
static void
|
||||
twiddle_image_uint(uint w, uint h, uint tile_size, uint *dst,
|
||||
uint src_stride, const uint *src)
|
||||
{
|
||||
const uint tile_size2 = tile_size * tile_size;
|
||||
const uint h_t = (h + tile_size - 1) / tile_size;
|
||||
const uint w_t = (w + tile_size - 1) / tile_size;
|
||||
|
||||
uint it, jt; /* tile counters */
|
||||
uint i, j; /* intra-tile counters */
|
||||
|
||||
src_stride /= 4; /* convert from bytes to pixels */
|
||||
|
||||
/* loop over dest tiles */
|
||||
for (it = 0; it < h_t; it++) {
|
||||
for (jt = 0; jt < w_t; jt++) {
|
||||
/* start of dest tile: */
|
||||
uint *tdst = dst + (it * w_t + jt) * tile_size2;
|
||||
|
||||
/* compute size of this tile (may be smaller than tile_size) */
|
||||
/* XXX note: a compiler bug was found here. That's why the code
|
||||
* looks as it does.
|
||||
*/
|
||||
uint tile_width = w - jt * tile_size;
|
||||
tile_width = MIN2(tile_width, tile_size);
|
||||
uint tile_height = h - it * tile_size;
|
||||
tile_height = MIN2(tile_height, tile_size);
|
||||
|
||||
/* loop over texels in the tile */
|
||||
for (i = 0; i < tile_height; i++) {
|
||||
for (j = 0; j < tile_width; j++) {
|
||||
const uint srci = it * tile_size + i;
|
||||
const uint srcj = jt * tile_size + j;
|
||||
ASSERT(srci < h);
|
||||
ASSERT(srcj < w);
|
||||
tdst[i * tile_size + j] = src[srci * src_stride + srcj];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For Cell. Basically, rearrange the pixels/quads from this layout:
|
||||
* +--+--+--+--+
|
||||
* |p0|p1|p2|p3|....
|
||||
* +--+--+--+--+
|
||||
*
|
||||
* to this layout:
|
||||
* +--+--+
|
||||
* |p0|p1|....
|
||||
* +--+--+
|
||||
* |p2|p3|
|
||||
* +--+--+
|
||||
*/
|
||||
static void
|
||||
twiddle_tile(const uint *tileIn, uint *tileOut)
|
||||
{
|
||||
int y, x;
|
||||
|
||||
for (y = 0; y < TILE_SIZE; y+=2) {
|
||||
for (x = 0; x < TILE_SIZE; x+=2) {
|
||||
int k = 4 * (y/2 * TILE_SIZE/2 + x/2);
|
||||
tileOut[y * TILE_SIZE + (x + 0)] = tileIn[k];
|
||||
tileOut[y * TILE_SIZE + (x + 1)] = tileIn[k+1];
|
||||
tileOut[(y + 1) * TILE_SIZE + (x + 0)] = tileIn[k+2];
|
||||
tileOut[(y + 1) * TILE_SIZE + (x + 1)] = tileIn[k+3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert image from tiled layout to linear layout. 4-byte pixels.
|
||||
*/
|
||||
static void
|
||||
untwiddle_image_uint(uint w, uint h, uint tile_size, uint *dst,
|
||||
uint dst_stride, const uint *src)
|
||||
{
|
||||
const uint tile_size2 = tile_size * tile_size;
|
||||
const uint h_t = (h + tile_size - 1) / tile_size;
|
||||
const uint w_t = (w + tile_size - 1) / tile_size;
|
||||
uint *tile_buf;
|
||||
uint it, jt; /* tile counters */
|
||||
uint i, j; /* intra-tile counters */
|
||||
|
||||
dst_stride /= 4; /* convert from bytes to pixels */
|
||||
|
||||
tile_buf = align_malloc(tile_size * tile_size * 4, 16);
|
||||
|
||||
/* loop over src tiles */
|
||||
for (it = 0; it < h_t; it++) {
|
||||
for (jt = 0; jt < w_t; jt++) {
|
||||
/* start of src tile: */
|
||||
const uint *tsrc = src + (it * w_t + jt) * tile_size2;
|
||||
|
||||
twiddle_tile(tsrc, tile_buf);
|
||||
tsrc = tile_buf;
|
||||
|
||||
/* compute size of this tile (may be smaller than tile_size) */
|
||||
/* XXX note: a compiler bug was found here. That's why the code
|
||||
* looks as it does.
|
||||
*/
|
||||
uint tile_width = w - jt * tile_size;
|
||||
tile_width = MIN2(tile_width, tile_size);
|
||||
uint tile_height = h - it * tile_size;
|
||||
tile_height = MIN2(tile_height, tile_size);
|
||||
|
||||
/* loop over texels in the tile */
|
||||
for (i = 0; i < tile_height; i++) {
|
||||
for (j = 0; j < tile_width; j++) {
|
||||
uint dsti = it * tile_size + i;
|
||||
uint dstj = jt * tile_size + j;
|
||||
ASSERT(dsti < h);
|
||||
ASSERT(dstj < w);
|
||||
dst[dsti * dst_stride + dstj] = tsrc[i * tile_size + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
align_free(tile_buf);
|
||||
}
|
||||
|
||||
|
||||
static struct pipe_surface *
|
||||
cell_create_surface(struct pipe_context *ctx,
|
||||
struct pipe_resource *pt,
|
||||
const struct pipe_surface *surf_tmpl)
|
||||
{
|
||||
struct cell_resource *ct = cell_resource(pt);
|
||||
struct pipe_surface *ps;
|
||||
|
||||
assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
|
||||
ps = CALLOC_STRUCT(pipe_surface);
|
||||
if (ps) {
|
||||
pipe_reference_init(&ps->reference, 1);
|
||||
pipe_resource_reference(&ps->texture, pt);
|
||||
ps->format = surf_tmpl->format;
|
||||
ps->context = ctx;
|
||||
ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
|
||||
ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
|
||||
/* XXX may need to override usage flags (see sp_texture.c) */
|
||||
ps->usage = surf_tmpl->usage;
|
||||
ps->u.tex.level = surf_tmpl->u.tex.level;
|
||||
ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
|
||||
ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
|
||||
}
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_surface_destroy(struct pipe_context *ctx, struct pipe_surface *surf)
|
||||
{
|
||||
pipe_resource_reference(&surf->texture, NULL);
|
||||
FREE(surf);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create new pipe_transfer object.
|
||||
* This is used by the user to put tex data into a texture (and get it
|
||||
* back out for glGetTexImage).
|
||||
*/
|
||||
static struct pipe_transfer *
|
||||
cell_get_transfer(struct pipe_context *ctx,
|
||||
struct pipe_resource *resource,
|
||||
unsigned level,
|
||||
unsigned usage,
|
||||
const struct pipe_box *box)
|
||||
{
|
||||
struct cell_resource *ct = cell_resource(resource);
|
||||
struct cell_transfer *ctrans;
|
||||
enum pipe_format format = resource->format;
|
||||
|
||||
assert(resource);
|
||||
assert(level <= resource->last_level);
|
||||
|
||||
/* make sure the requested region is in the image bounds */
|
||||
assert(box->x + box->width <= u_minify(resource->width0, level));
|
||||
assert(box->y + box->height <= u_minify(resource->height0, level));
|
||||
assert(box->z + box->depth <= (u_minify(resource->depth0, level) + resource->array_size - 1));
|
||||
|
||||
ctrans = CALLOC_STRUCT(cell_transfer);
|
||||
if (ctrans) {
|
||||
struct pipe_transfer *pt = &ctrans->base;
|
||||
pipe_resource_reference(&pt->resource, resource);
|
||||
pt->level = level;
|
||||
pt->usage = usage;
|
||||
pt->box = *box;
|
||||
pt->stride = ct->stride[level];
|
||||
|
||||
ctrans->offset = ct->level_offset[level];
|
||||
|
||||
if (resource->target == PIPE_TEXTURE_CUBE || resource->target == PIPE_TEXTURE_3D) {
|
||||
unsigned h_tile = align(u_minify(resource->height0, level), TILE_SIZE);
|
||||
ctrans->offset += box->z * util_format_get_nblocksy(format, h_tile) * pt->stride;
|
||||
}
|
||||
else {
|
||||
assert(box->z == 0);
|
||||
}
|
||||
|
||||
return pt;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_transfer_destroy(struct pipe_context *ctx, struct pipe_transfer *t)
|
||||
{
|
||||
struct cell_transfer *transfer = cell_transfer(t);
|
||||
/* Effectively do the texture_update work here - if texture images
|
||||
* needed post-processing to put them into hardware layout, this is
|
||||
* where it would happen. For cell, nothing to do.
|
||||
*/
|
||||
assert (transfer->base.resource);
|
||||
pipe_resource_reference(&transfer->base.resource, NULL);
|
||||
FREE(transfer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return pointer to texture image data in linear layout.
|
||||
*/
|
||||
static void *
|
||||
cell_transfer_map(struct pipe_context *ctx, struct pipe_transfer *transfer)
|
||||
{
|
||||
struct cell_transfer *ctrans = cell_transfer(transfer);
|
||||
struct pipe_resource *pt = transfer->resource;
|
||||
struct cell_resource *ct = cell_resource(pt);
|
||||
|
||||
assert(transfer->resource);
|
||||
|
||||
if (ct->mapped == NULL) {
|
||||
ct->mapped = ct->data;
|
||||
}
|
||||
|
||||
|
||||
/* Better test would be resource->is_linear
|
||||
*/
|
||||
if (transfer->resource->target != PIPE_BUFFER) {
|
||||
const uint level = ctrans->base.level;
|
||||
const uint texWidth = u_minify(pt->width0, level);
|
||||
const uint texHeight = u_minify(pt->height0, level);
|
||||
unsigned size;
|
||||
|
||||
|
||||
/*
|
||||
* Create a buffer of ordinary memory for the linear texture.
|
||||
* This is the memory that the user will read/write.
|
||||
*/
|
||||
size = (util_format_get_stride(pt->format, align(texWidth, TILE_SIZE)) *
|
||||
util_format_get_nblocksy(pt->format, align(texHeight, TILE_SIZE)));
|
||||
|
||||
ctrans->map = align_malloc(size, 16);
|
||||
if (!ctrans->map)
|
||||
return NULL; /* out of memory */
|
||||
|
||||
if (transfer->usage & PIPE_TRANSFER_READ) {
|
||||
/* Textures always stored twiddled, need to untwiddle the
|
||||
* texture to make a linear version.
|
||||
*/
|
||||
const uint bpp = util_format_get_blocksize(ct->base.format);
|
||||
if (bpp == 4) {
|
||||
const uint *src = (uint *) (ct->mapped + ctrans->offset);
|
||||
uint *dst = ctrans->map;
|
||||
untwiddle_image_uint(texWidth, texHeight, TILE_SIZE,
|
||||
dst, transfer->stride, src);
|
||||
}
|
||||
else {
|
||||
// xxx fix
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned stride = transfer->stride;
|
||||
enum pipe_format format = pt->format;
|
||||
unsigned blocksize = util_format_get_blocksize(format);
|
||||
|
||||
ctrans->map = (ct->mapped +
|
||||
ctrans->offset +
|
||||
ctrans->base.box.y / util_format_get_blockheight(format) * stride +
|
||||
ctrans->base.box.x / util_format_get_blockwidth(format) * blocksize);
|
||||
}
|
||||
|
||||
|
||||
return ctrans->map;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when user is done reading/writing texture data.
|
||||
* If new data was written, this is where we convert the linear data
|
||||
* to tiled data.
|
||||
*/
|
||||
static void
|
||||
cell_transfer_unmap(struct pipe_context *ctx,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct cell_transfer *ctrans = cell_transfer(transfer);
|
||||
struct pipe_resource *pt = transfer->resource;
|
||||
struct cell_resource *ct = cell_resource(pt);
|
||||
const uint level = ctrans->base.level;
|
||||
const uint texWidth = u_minify(pt->width0, level);
|
||||
const uint texHeight = u_minify(pt->height0, level);
|
||||
const uint stride = ct->stride[level];
|
||||
|
||||
if (!ct->mapped) {
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pt->target != PIPE_BUFFER) {
|
||||
if (transfer->usage & PIPE_TRANSFER_WRITE) {
|
||||
/* The user wrote new texture data into the mapped buffer.
|
||||
* We need to convert the new linear data into the twiddled/tiled format.
|
||||
*/
|
||||
const uint bpp = util_format_get_blocksize(ct->base.format);
|
||||
if (bpp == 4) {
|
||||
const uint *src = ctrans->map;
|
||||
uint *dst = (uint *) (ct->mapped + ctrans->offset);
|
||||
twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, stride, src);
|
||||
}
|
||||
else {
|
||||
// xxx fix
|
||||
}
|
||||
}
|
||||
|
||||
align_free(ctrans->map);
|
||||
}
|
||||
else {
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
ctrans->map = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This used to be overriden by the co-state tracker, but really needs
|
||||
* to be active with sw_winsys.
|
||||
*
|
||||
* Contrasting with llvmpipe and softpipe, this is the only place
|
||||
* where we use the ct->dt display target in any real sense.
|
||||
*
|
||||
* Basically just untwiddle our local data into the linear
|
||||
* displaytarget.
|
||||
*/
|
||||
static void
|
||||
cell_flush_frontbuffer(struct pipe_screen *_screen,
|
||||
struct pipe_resource *resource,
|
||||
unsigned level, unsigned layer,
|
||||
void *context_private)
|
||||
{
|
||||
struct cell_screen *screen = cell_screen(_screen);
|
||||
struct sw_winsys *winsys = screen->winsys;
|
||||
struct cell_resource *ct = cell_resource(resource);
|
||||
|
||||
if (!ct->dt)
|
||||
return;
|
||||
|
||||
/* Need to untwiddle from our internal representation here:
|
||||
*/
|
||||
{
|
||||
unsigned *map = winsys->displaytarget_map(winsys, ct->dt,
|
||||
(PIPE_TRANSFER_READ |
|
||||
PIPE_TRANSFER_WRITE));
|
||||
unsigned *src = (unsigned *)(ct->data + ct->level_offset[level]);
|
||||
|
||||
untwiddle_image_uint(u_minify(resource->width0, level),
|
||||
u_minify(resource->height0, level),
|
||||
TILE_SIZE,
|
||||
map,
|
||||
ct->dt_stride,
|
||||
src);
|
||||
|
||||
winsys->displaytarget_unmap(winsys, ct->dt);
|
||||
}
|
||||
|
||||
winsys->displaytarget_display(winsys, ct->dt, context_private);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create buffer which wraps user-space data.
|
||||
*/
|
||||
static struct pipe_resource *
|
||||
cell_user_buffer_create(struct pipe_screen *screen,
|
||||
void *ptr,
|
||||
unsigned bytes,
|
||||
unsigned bind_flags)
|
||||
{
|
||||
struct cell_resource *buffer;
|
||||
|
||||
buffer = CALLOC_STRUCT(cell_resource);
|
||||
if(!buffer)
|
||||
return NULL;
|
||||
|
||||
pipe_reference_init(&buffer->base.reference, 1);
|
||||
buffer->base.screen = screen;
|
||||
buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
|
||||
buffer->base.bind = PIPE_BIND_TRANSFER_READ | bind_flags;
|
||||
buffer->base.usage = PIPE_USAGE_IMMUTABLE;
|
||||
buffer->base.flags = 0;
|
||||
buffer->base.width0 = bytes;
|
||||
buffer->base.height0 = 1;
|
||||
buffer->base.depth0 = 1;
|
||||
buffer->base.array_size = 1;
|
||||
buffer->userBuffer = TRUE;
|
||||
buffer->data = ptr;
|
||||
|
||||
return &buffer->base;
|
||||
}
|
||||
|
||||
|
||||
static struct pipe_resource *
|
||||
cell_resource_from_handle(struct pipe_screen *screen,
|
||||
const struct pipe_resource *templat,
|
||||
struct winsys_handle *handle)
|
||||
{
|
||||
/* XXX todo */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static boolean
|
||||
cell_resource_get_handle(struct pipe_screen *scree,
|
||||
struct pipe_resource *tex,
|
||||
struct winsys_handle *handle)
|
||||
{
|
||||
/* XXX todo */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cell_init_screen_texture_funcs(struct pipe_screen *screen)
|
||||
{
|
||||
screen->resource_create = cell_resource_create;
|
||||
screen->resource_destroy = cell_resource_destroy;
|
||||
screen->resource_from_handle = cell_resource_from_handle;
|
||||
screen->resource_get_handle = cell_resource_get_handle;
|
||||
screen->user_buffer_create = cell_user_buffer_create;
|
||||
|
||||
screen->flush_frontbuffer = cell_flush_frontbuffer;
|
||||
}
|
||||
|
||||
void
|
||||
cell_init_texture_transfer_funcs(struct cell_context *cell)
|
||||
{
|
||||
cell->pipe.get_transfer = cell_get_transfer;
|
||||
cell->pipe.transfer_destroy = cell_transfer_destroy;
|
||||
cell->pipe.transfer_map = cell_transfer_map;
|
||||
cell->pipe.transfer_unmap = cell_transfer_unmap;
|
||||
|
||||
cell->pipe.transfer_flush_region = u_default_transfer_flush_region;
|
||||
cell->pipe.transfer_inline_write = u_default_transfer_inline_write;
|
||||
|
||||
cell->pipe.create_surface = cell_create_surface;
|
||||
cell->pipe.surface_destroy = cell_surface_destroy;
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CELL_TEXTURE_H
|
||||
#define CELL_TEXTURE_H
|
||||
|
||||
#include "cell/common.h"
|
||||
|
||||
struct cell_context;
|
||||
struct pipe_resource;
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of pipe_resource
|
||||
*/
|
||||
struct cell_resource
|
||||
{
|
||||
struct pipe_resource base;
|
||||
|
||||
unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS];
|
||||
unsigned long stride[CELL_MAX_TEXTURE_LEVELS];
|
||||
|
||||
/**
|
||||
* Display target, for textures with the PIPE_BIND_DISPLAY_TARGET
|
||||
* usage.
|
||||
*/
|
||||
struct sw_displaytarget *dt;
|
||||
unsigned dt_stride;
|
||||
|
||||
/**
|
||||
* Malloc'ed data for regular textures, or a mapping to dt above.
|
||||
*/
|
||||
void *data;
|
||||
boolean userBuffer;
|
||||
|
||||
/* Size of the linear buffer??
|
||||
*/
|
||||
unsigned long buffer_size;
|
||||
|
||||
/** The buffer above, mapped. This is the memory from which the
|
||||
* SPUs will fetch texels. This texture data is in the tiled layout.
|
||||
*/
|
||||
ubyte *mapped;
|
||||
};
|
||||
|
||||
|
||||
struct cell_transfer
|
||||
{
|
||||
struct pipe_transfer base;
|
||||
|
||||
unsigned long offset;
|
||||
void *map;
|
||||
};
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static INLINE struct cell_resource *
|
||||
cell_resource(struct pipe_resource *pt)
|
||||
{
|
||||
return (struct cell_resource *) pt;
|
||||
}
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static INLINE struct cell_transfer *
|
||||
cell_transfer(struct pipe_transfer *pt)
|
||||
{
|
||||
return (struct cell_transfer *) pt;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
cell_init_screen_texture_funcs(struct pipe_screen *screen);
|
||||
|
||||
extern void
|
||||
cell_init_texture_transfer_funcs(struct cell_context *cell);
|
||||
|
||||
#endif /* CELL_TEXTURE_H */
|
||||
|
|
@ -1,332 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Vertex buffer code. The draw module transforms vertices to window
|
||||
* coords, etc. and emits the vertices into buffer supplied by this module.
|
||||
* When a vertex buffer is full, or we flush, we'll send the vertex data
|
||||
* to the SPUs.
|
||||
*
|
||||
* Authors
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include "cell_batch.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_fence.h"
|
||||
#include "cell_flush.h"
|
||||
#include "cell_spu.h"
|
||||
#include "cell_vbuf.h"
|
||||
#include "draw/draw_vbuf.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
|
||||
/** Allow vertex data to be inlined after RENDER command */
|
||||
#define ALLOW_INLINE_VERTS 1
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of vbuf_render because we need a cell_context pointer in
|
||||
* a few places.
|
||||
*/
|
||||
struct cell_vbuf_render
|
||||
{
|
||||
struct vbuf_render base;
|
||||
struct cell_context *cell;
|
||||
uint prim; /**< PIPE_PRIM_x */
|
||||
uint vertex_size; /**< in bytes */
|
||||
void *vertex_buffer; /**< just for debug, really */
|
||||
uint vertex_buf; /**< in [0, CELL_NUM_BUFFERS-1] */
|
||||
uint vertex_buffer_size; /**< size in bytes */
|
||||
};
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static struct cell_vbuf_render *
|
||||
cell_vbuf_render(struct vbuf_render *vbr)
|
||||
{
|
||||
return (struct cell_vbuf_render *) vbr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const struct vertex_info *
|
||||
cell_vbuf_get_vertex_info(struct vbuf_render *vbr)
|
||||
{
|
||||
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
|
||||
return &cvbr->cell->vertex_info;
|
||||
}
|
||||
|
||||
|
||||
static boolean
|
||||
cell_vbuf_allocate_vertices(struct vbuf_render *vbr,
|
||||
ushort vertex_size, ushort nr_vertices)
|
||||
{
|
||||
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
|
||||
unsigned size = vertex_size * nr_vertices;
|
||||
/*printf("Alloc verts %u * %u\n", vertex_size, nr_vertices);*/
|
||||
|
||||
assert(cvbr->vertex_buf == ~0);
|
||||
cvbr->vertex_buf = cell_get_empty_buffer(cvbr->cell);
|
||||
cvbr->vertex_buffer = cvbr->cell->buffer[cvbr->vertex_buf];
|
||||
cvbr->vertex_buffer_size = size;
|
||||
cvbr->vertex_size = vertex_size;
|
||||
|
||||
return cvbr->vertex_buffer != NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_vbuf_release_vertices(struct vbuf_render *vbr)
|
||||
{
|
||||
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
|
||||
struct cell_context *cell = cvbr->cell;
|
||||
|
||||
/*
|
||||
printf("%s vertex_buf = %u count = %u\n",
|
||||
__FUNCTION__, cvbr->vertex_buf, vertices_used);
|
||||
*/
|
||||
|
||||
/* Make sure texture buffers aren't released until we're done rendering
|
||||
* with them.
|
||||
*/
|
||||
cell_add_fenced_textures(cell);
|
||||
|
||||
/* Tell SPUs they can release the vert buf */
|
||||
if (cvbr->vertex_buf != ~0U) {
|
||||
STATIC_ASSERT(sizeof(struct cell_command_release_verts) % 16 == 0);
|
||||
struct cell_command_release_verts *release
|
||||
= (struct cell_command_release_verts *)
|
||||
cell_batch_alloc16(cell, sizeof(struct cell_command_release_verts));
|
||||
release->opcode[0] = CELL_CMD_RELEASE_VERTS;
|
||||
release->vertex_buf = cvbr->vertex_buf;
|
||||
}
|
||||
|
||||
cvbr->vertex_buf = ~0;
|
||||
cell_flush_int(cell, 0x0);
|
||||
|
||||
cvbr->vertex_buffer = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
cell_vbuf_map_vertices(struct vbuf_render *vbr)
|
||||
{
|
||||
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
|
||||
return cvbr->vertex_buffer;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_vbuf_unmap_vertices(struct vbuf_render *vbr,
|
||||
ushort min_index,
|
||||
ushort max_index )
|
||||
{
|
||||
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
|
||||
assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static boolean
|
||||
cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
|
||||
{
|
||||
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
|
||||
cvbr->prim = prim;
|
||||
/*printf("cell_set_prim %u\n", prim);*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_vbuf_draw_elements(struct vbuf_render *vbr,
|
||||
const ushort *indices,
|
||||
uint nr_indices)
|
||||
{
|
||||
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
|
||||
struct cell_context *cell = cvbr->cell;
|
||||
float xmin, ymin, xmax, ymax;
|
||||
uint i;
|
||||
uint nr_vertices = 0, min_index = ~0;
|
||||
const void *vertices = cvbr->vertex_buffer;
|
||||
const uint vertex_size = cvbr->vertex_size;
|
||||
|
||||
for (i = 0; i < nr_indices; i++) {
|
||||
if (indices[i] > nr_vertices)
|
||||
nr_vertices = indices[i];
|
||||
if (indices[i] < min_index)
|
||||
min_index = indices[i];
|
||||
}
|
||||
nr_vertices++;
|
||||
|
||||
#if 0
|
||||
/*if (min_index > 0)*/
|
||||
printf("%s min_index = %u\n", __FUNCTION__, min_index);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
printf("cell_vbuf_draw() nr_indices = %u nr_verts = %u\n",
|
||||
nr_indices, nr_vertices);
|
||||
printf(" ");
|
||||
for (i = 0; i < nr_indices; i += 3) {
|
||||
printf("%u %u %u, ", indices[i+0], indices[i+1], indices[i+2]);
|
||||
}
|
||||
printf("\n");
|
||||
#elif 0
|
||||
printf("cell_vbuf_draw() nr_indices = %u nr_verts = %u indexes = [%u %u %u ...]\n",
|
||||
nr_indices, nr_vertices,
|
||||
indices[0], indices[1], indices[2]);
|
||||
printf("ind space = %u, vert space = %u, space = %u\n",
|
||||
nr_indices * 2,
|
||||
nr_vertices * 4 * cell->vertex_info.size,
|
||||
cell_batch_free_space(cell));
|
||||
#endif
|
||||
|
||||
/* compute x/y bounding box */
|
||||
xmin = ymin = 1e50;
|
||||
xmax = ymax = -1e50;
|
||||
for (i = min_index; i < nr_vertices; i++) {
|
||||
const float *v = (float *) ((ubyte *) vertices + i * vertex_size);
|
||||
if (v[0] < xmin)
|
||||
xmin = v[0];
|
||||
if (v[0] > xmax)
|
||||
xmax = v[0];
|
||||
if (v[1] < ymin)
|
||||
ymin = v[1];
|
||||
if (v[1] > ymax)
|
||||
ymax = v[1];
|
||||
}
|
||||
#if 0
|
||||
printf("PPU Bounds %g, %g .. %g, %g\n", xmin, ymin, xmax, ymax);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
if (cvbr->prim != PIPE_PRIM_TRIANGLES)
|
||||
return; /* only render tris for now */
|
||||
|
||||
/* build/insert batch RENDER command */
|
||||
{
|
||||
const uint index_bytes = ROUNDUP16(nr_indices * 2);
|
||||
const uint vertex_bytes = ROUNDUP16(nr_vertices * 4 * cell->vertex_info.size);
|
||||
STATIC_ASSERT(sizeof(struct cell_command_render) % 16 == 0);
|
||||
const uint batch_size = sizeof(struct cell_command_render) + index_bytes;
|
||||
|
||||
struct cell_command_render *render
|
||||
= (struct cell_command_render *)
|
||||
cell_batch_alloc16(cell, batch_size);
|
||||
|
||||
render->opcode[0] = CELL_CMD_RENDER;
|
||||
render->prim_type = cvbr->prim;
|
||||
|
||||
render->num_indexes = nr_indices;
|
||||
render->min_index = min_index;
|
||||
|
||||
/* append indices after render command */
|
||||
memcpy(render + 1, indices, nr_indices * 2);
|
||||
|
||||
/* if there's room, append vertices after the indices, else leave
|
||||
* vertices in the original/separate buffer.
|
||||
*/
|
||||
render->vertex_size = 4 * cell->vertex_info.size;
|
||||
render->num_verts = nr_vertices;
|
||||
if (ALLOW_INLINE_VERTS &&
|
||||
min_index == 0 &&
|
||||
vertex_bytes + 16 <= cell_batch_free_space(cell)) {
|
||||
/* vertex data inlined, after indices, at 16-byte boundary */
|
||||
void *dst = cell_batch_alloc16(cell, vertex_bytes);
|
||||
memcpy(dst, vertices, vertex_bytes);
|
||||
render->inline_verts = TRUE;
|
||||
render->vertex_buf = ~0;
|
||||
}
|
||||
else {
|
||||
/* vertex data in separate buffer */
|
||||
render->inline_verts = FALSE;
|
||||
ASSERT(cvbr->vertex_buf >= 0);
|
||||
render->vertex_buf = cvbr->vertex_buf;
|
||||
}
|
||||
|
||||
render->xmin = xmin;
|
||||
render->ymin = ymin;
|
||||
render->xmax = xmax;
|
||||
render->ymax = ymax;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* helpful for debug */
|
||||
cell_flush_int(cell, CELL_FLUSH_WAIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_vbuf_destroy(struct vbuf_render *vbr)
|
||||
{
|
||||
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
|
||||
cvbr->cell->vbuf_render = NULL;
|
||||
FREE(cvbr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the post-transform vertex buffer information for the given
|
||||
* context.
|
||||
*/
|
||||
void
|
||||
cell_init_vbuf(struct cell_context *cell)
|
||||
{
|
||||
assert(cell->draw);
|
||||
|
||||
cell->vbuf_render = CALLOC_STRUCT(cell_vbuf_render);
|
||||
|
||||
/* The max number of indexes is what can fix into a batch buffer,
|
||||
* minus the render and release-verts commands.
|
||||
*/
|
||||
cell->vbuf_render->base.max_indices
|
||||
= (CELL_BUFFER_SIZE
|
||||
- sizeof(struct cell_command_render)
|
||||
- sizeof(struct cell_command_release_verts))
|
||||
/ sizeof(ushort);
|
||||
cell->vbuf_render->base.max_vertex_buffer_bytes = CELL_BUFFER_SIZE;
|
||||
|
||||
cell->vbuf_render->base.get_vertex_info = cell_vbuf_get_vertex_info;
|
||||
cell->vbuf_render->base.allocate_vertices = cell_vbuf_allocate_vertices;
|
||||
cell->vbuf_render->base.map_vertices = cell_vbuf_map_vertices;
|
||||
cell->vbuf_render->base.unmap_vertices = cell_vbuf_unmap_vertices;
|
||||
cell->vbuf_render->base.set_primitive = cell_vbuf_set_primitive;
|
||||
cell->vbuf_render->base.draw_elements = cell_vbuf_draw_elements;
|
||||
cell->vbuf_render->base.release_vertices = cell_vbuf_release_vertices;
|
||||
cell->vbuf_render->base.destroy = cell_vbuf_destroy;
|
||||
|
||||
cell->vbuf_render->cell = cell;
|
||||
#if 1
|
||||
cell->vbuf_render->vertex_buf = ~0;
|
||||
#endif
|
||||
|
||||
cell->vbuf = draw_vbuf_stage(cell->draw, &cell->vbuf_render->base);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CELL_VBUF_H
|
||||
#define CELL_VBUF_H
|
||||
|
||||
|
||||
struct cell_context;
|
||||
|
||||
extern void
|
||||
cell_init_vbuf(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_VBUF_H */
|
||||
|
|
@ -1,346 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright IBM Corporation 2008
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_format.h"
|
||||
|
||||
#include "../auxiliary/draw/draw_context.h"
|
||||
#include "../auxiliary/draw/draw_private.h"
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "rtasm/rtasm_ppc_spe.h"
|
||||
|
||||
|
||||
/**
|
||||
* Emit a 4x4 matrix transpose operation
|
||||
*
|
||||
* \param p Function that the transpose operation is to be appended to
|
||||
* \param row0 Register containing row 0 of the source matrix
|
||||
* \param row1 Register containing row 1 of the source matrix
|
||||
* \param row2 Register containing row 2 of the source matrix
|
||||
* \param row3 Register containing row 3 of the source matrix
|
||||
* \param dest_ptr Register containing the address of the destination matrix
|
||||
* \param shuf_ptr Register containing the address of the shuffled data
|
||||
* \param count Number of colums to actually be written to the destination
|
||||
*
|
||||
* \note
|
||||
* This function assumes that the registers named by \c row0, \c row1,
|
||||
* \c row2, and \c row3 are scratch and can be modified by the generated code.
|
||||
* Furthermore, these registers will be released, via calls to
|
||||
* \c release_register, by this function.
|
||||
*
|
||||
* \note
|
||||
* This function requires that four temporary are available on entry.
|
||||
*/
|
||||
static void
|
||||
emit_matrix_transpose(struct spe_function *p,
|
||||
unsigned row0, unsigned row1, unsigned row2,
|
||||
unsigned row3, unsigned dest_ptr,
|
||||
unsigned shuf_ptr, unsigned count)
|
||||
{
|
||||
int shuf_hi = spe_allocate_available_register(p);
|
||||
int shuf_lo = spe_allocate_available_register(p);
|
||||
int t1 = spe_allocate_available_register(p);
|
||||
int t2 = spe_allocate_available_register(p);
|
||||
int t3;
|
||||
int t4;
|
||||
int col0;
|
||||
int col1;
|
||||
int col2;
|
||||
int col3;
|
||||
|
||||
|
||||
spe_lqd(p, shuf_hi, shuf_ptr, 3*16);
|
||||
spe_lqd(p, shuf_lo, shuf_ptr, 4*16);
|
||||
spe_shufb(p, t1, row0, row2, shuf_hi);
|
||||
spe_shufb(p, t2, row0, row2, shuf_lo);
|
||||
|
||||
|
||||
/* row0 and row2 are now no longer needed. Re-use those registers as
|
||||
* temporaries.
|
||||
*/
|
||||
t3 = row0;
|
||||
t4 = row2;
|
||||
|
||||
spe_shufb(p, t3, row1, row3, shuf_hi);
|
||||
spe_shufb(p, t4, row1, row3, shuf_lo);
|
||||
|
||||
|
||||
/* row1 and row3 are now no longer needed. Re-use those registers as
|
||||
* temporaries.
|
||||
*/
|
||||
col0 = row1;
|
||||
col1 = row3;
|
||||
|
||||
spe_shufb(p, col0, t1, t3, shuf_hi);
|
||||
if (count > 1) {
|
||||
spe_shufb(p, col1, t1, t3, shuf_lo);
|
||||
}
|
||||
|
||||
/* t1 and t3 are now no longer needed. Re-use those registers as
|
||||
* temporaries.
|
||||
*/
|
||||
col2 = t1;
|
||||
col3 = t3;
|
||||
|
||||
if (count > 2) {
|
||||
spe_shufb(p, col2, t2, t4, shuf_hi);
|
||||
}
|
||||
|
||||
if (count > 3) {
|
||||
spe_shufb(p, col3, t2, t4, shuf_lo);
|
||||
}
|
||||
|
||||
|
||||
/* Store the results. Remember that the stqd instruction is encoded using
|
||||
* the qword offset (stand-alone assemblers to the byte-offset to
|
||||
* qword-offset conversion for you), so the byte-offset needs be divided by
|
||||
* 16.
|
||||
*/
|
||||
switch (count) {
|
||||
case 4:
|
||||
spe_stqd(p, col3, dest_ptr, 3 * 16);
|
||||
case 3:
|
||||
spe_stqd(p, col2, dest_ptr, 2 * 16);
|
||||
case 2:
|
||||
spe_stqd(p, col1, dest_ptr, 1 * 16);
|
||||
case 1:
|
||||
spe_stqd(p, col0, dest_ptr, 0 * 16);
|
||||
}
|
||||
|
||||
|
||||
/* Release all of the temporary registers used.
|
||||
*/
|
||||
spe_release_register(p, col0);
|
||||
spe_release_register(p, col1);
|
||||
spe_release_register(p, col2);
|
||||
spe_release_register(p, col3);
|
||||
spe_release_register(p, shuf_hi);
|
||||
spe_release_register(p, shuf_lo);
|
||||
spe_release_register(p, t2);
|
||||
spe_release_register(p, t4);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* This appears to not be used currently */
|
||||
static void
|
||||
emit_fetch(struct spe_function *p,
|
||||
unsigned in_ptr, unsigned *offset,
|
||||
unsigned out_ptr, unsigned shuf_ptr,
|
||||
enum pipe_format format)
|
||||
{
|
||||
const unsigned count = (pf_size_x(format) != 0) + (pf_size_y(format) != 0)
|
||||
+ (pf_size_z(format) != 0) + (pf_size_w(format) != 0);
|
||||
const unsigned type = pf_type(format);
|
||||
const unsigned bytes = pf_size_x(format);
|
||||
|
||||
int v0 = spe_allocate_available_register(p);
|
||||
int v1 = spe_allocate_available_register(p);
|
||||
int v2 = spe_allocate_available_register(p);
|
||||
int v3 = spe_allocate_available_register(p);
|
||||
int tmp = spe_allocate_available_register(p);
|
||||
int float_zero = -1;
|
||||
int float_one = -1;
|
||||
float scale_signed = 0.0;
|
||||
float scale_unsigned = 0.0;
|
||||
|
||||
spe_lqd(p, v0, in_ptr, (0 + offset[0]) * 16);
|
||||
spe_lqd(p, v1, in_ptr, (1 + offset[0]) * 16);
|
||||
spe_lqd(p, v2, in_ptr, (2 + offset[0]) * 16);
|
||||
spe_lqd(p, v3, in_ptr, (3 + offset[0]) * 16);
|
||||
offset[0] += 4;
|
||||
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
scale_signed = 1.0f / 127.0f;
|
||||
scale_unsigned = 1.0f / 255.0f;
|
||||
spe_lqd(p, tmp, shuf_ptr, 1 * 16);
|
||||
spe_shufb(p, v0, v0, v0, tmp);
|
||||
spe_shufb(p, v1, v1, v1, tmp);
|
||||
spe_shufb(p, v2, v2, v2, tmp);
|
||||
spe_shufb(p, v3, v3, v3, tmp);
|
||||
break;
|
||||
case 2:
|
||||
scale_signed = 1.0f / 32767.0f;
|
||||
scale_unsigned = 1.0f / 65535.0f;
|
||||
spe_lqd(p, tmp, shuf_ptr, 2 * 16);
|
||||
spe_shufb(p, v0, v0, v0, tmp);
|
||||
spe_shufb(p, v1, v1, v1, tmp);
|
||||
spe_shufb(p, v2, v2, v2, tmp);
|
||||
spe_shufb(p, v3, v3, v3, tmp);
|
||||
break;
|
||||
case 4:
|
||||
scale_signed = 1.0f / 2147483647.0f;
|
||||
scale_unsigned = 1.0f / 4294967295.0f;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case PIPE_FORMAT_TYPE_FLOAT:
|
||||
break;
|
||||
case PIPE_FORMAT_TYPE_UNORM:
|
||||
spe_ilhu(p, tmp, ((unsigned) scale_unsigned) >> 16);
|
||||
spe_iohl(p, tmp, ((unsigned) scale_unsigned) & 0x0ffff);
|
||||
spe_cuflt(p, v0, v0, 0);
|
||||
spe_fm(p, v0, v0, tmp);
|
||||
break;
|
||||
case PIPE_FORMAT_TYPE_SNORM:
|
||||
spe_ilhu(p, tmp, ((unsigned) scale_signed) >> 16);
|
||||
spe_iohl(p, tmp, ((unsigned) scale_signed) & 0x0ffff);
|
||||
spe_csflt(p, v0, v0, 0);
|
||||
spe_fm(p, v0, v0, tmp);
|
||||
break;
|
||||
case PIPE_FORMAT_TYPE_USCALED:
|
||||
spe_cuflt(p, v0, v0, 0);
|
||||
break;
|
||||
case PIPE_FORMAT_TYPE_SSCALED:
|
||||
spe_csflt(p, v0, v0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (count < 4) {
|
||||
float_one = spe_allocate_available_register(p);
|
||||
spe_il(p, float_one, 1);
|
||||
spe_cuflt(p, float_one, float_one, 0);
|
||||
|
||||
if (count < 3) {
|
||||
float_zero = spe_allocate_available_register(p);
|
||||
spe_il(p, float_zero, 0);
|
||||
}
|
||||
}
|
||||
|
||||
spe_release_register(p, tmp);
|
||||
|
||||
emit_matrix_transpose(p, v0, v1, v2, v3, out_ptr, shuf_ptr, count);
|
||||
|
||||
switch (count) {
|
||||
case 1:
|
||||
spe_stqd(p, float_zero, out_ptr, 1 * 16);
|
||||
case 2:
|
||||
spe_stqd(p, float_zero, out_ptr, 2 * 16);
|
||||
case 3:
|
||||
spe_stqd(p, float_one, out_ptr, 3 * 16);
|
||||
}
|
||||
|
||||
if (float_zero != -1) {
|
||||
spe_release_register(p, float_zero);
|
||||
}
|
||||
|
||||
if (float_one != -1) {
|
||||
spe_release_register(p, float_one);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void cell_update_vertex_fetch(struct draw_context *draw)
|
||||
{
|
||||
#if 0
|
||||
struct cell_context *const cell =
|
||||
(struct cell_context *) draw->driver_private;
|
||||
struct spe_function *p = &cell->attrib_fetch;
|
||||
unsigned function_index[PIPE_MAX_ATTRIBS];
|
||||
unsigned unique_attr_formats;
|
||||
int out_ptr;
|
||||
int in_ptr;
|
||||
int shuf_ptr;
|
||||
unsigned i;
|
||||
unsigned j;
|
||||
|
||||
|
||||
/* Determine how many unique input attribute formats there are. At the
|
||||
* same time, store the index of the lowest numbered attribute that has
|
||||
* the same format as any non-unique format.
|
||||
*/
|
||||
unique_attr_formats = 1;
|
||||
function_index[0] = 0;
|
||||
for (i = 1; i < draw->vertex_fetch.nr_attrs; i++) {
|
||||
const enum pipe_format curr_fmt = draw->vertex_element[i].src_format;
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
if (curr_fmt == draw->vertex_element[j].src_format) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == i) {
|
||||
unique_attr_formats++;
|
||||
}
|
||||
|
||||
function_index[i] = j;
|
||||
}
|
||||
|
||||
|
||||
/* Each fetch function can be a maximum of 34 instructions (note: this is
|
||||
* actually a slight over-estimate).
|
||||
*/
|
||||
spe_init_func(p, 34 * SPE_INST_SIZE * unique_attr_formats);
|
||||
|
||||
|
||||
/* Allocate registers for the function's input parameters.
|
||||
*/
|
||||
out_ptr = spe_allocate_register(p, 3);
|
||||
in_ptr = spe_allocate_register(p, 4);
|
||||
shuf_ptr = spe_allocate_register(p, 5);
|
||||
|
||||
|
||||
/* Generate code for the individual attribute fetch functions.
|
||||
*/
|
||||
for (i = 0; i < draw->vertex_fetch.nr_attrs; i++) {
|
||||
unsigned offset;
|
||||
|
||||
if (function_index[i] == i) {
|
||||
cell->attrib_fetch_offsets[i] = (unsigned) ((void *) p->csr
|
||||
- (void *) p->store);
|
||||
|
||||
offset = 0;
|
||||
emit_fetch(p, in_ptr, &offset, out_ptr, shuf_ptr,
|
||||
draw->vertex_element[i].src_format);
|
||||
spe_bi(p, 0, 0, 0);
|
||||
|
||||
/* Round up to the next 16-byte boundary.
|
||||
*/
|
||||
if ((((unsigned) p->store) & 0x0f) != 0) {
|
||||
const unsigned align = ((unsigned) p->store) & 0x0f;
|
||||
p->store = (uint32_t *) (((void *) p->store) + align);
|
||||
}
|
||||
} else {
|
||||
/* Use the same function entry-point as a previously seen attribute
|
||||
* with the same format.
|
||||
*/
|
||||
cell->attrib_fetch_offsets[i] =
|
||||
cell->attrib_fetch_offsets[function_index[i]];
|
||||
}
|
||||
}
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright IBM Corporation 2008
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file cell_vertex_shader.c
|
||||
* Vertex shader interface routines for Cell.
|
||||
*
|
||||
* \author Ian Romanick <idr@us.ibm.com>
|
||||
*/
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "cell_context.h"
|
||||
#include "cell_draw_arrays.h"
|
||||
#include "cell_flush.h"
|
||||
#include "cell_spu.h"
|
||||
#include "cell_batch.h"
|
||||
|
||||
#include "cell/common.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_private.h"
|
||||
|
||||
/**
|
||||
* Run the vertex shader on all vertices in the vertex queue.
|
||||
* Called by the draw module when the vertx cache needs to be flushed.
|
||||
*/
|
||||
void
|
||||
cell_vertex_shader_queue_flush(struct draw_context *draw)
|
||||
{
|
||||
#if 0
|
||||
struct cell_context *const cell =
|
||||
(struct cell_context *) draw->driver_private;
|
||||
struct cell_command_vs *const vs = &cell_global.command[0].vs;
|
||||
uint64_t *batch;
|
||||
struct cell_array_info *array_info;
|
||||
unsigned i, j;
|
||||
struct cell_attribute_fetch_code *cf;
|
||||
|
||||
assert(draw->vs.queue_nr != 0);
|
||||
|
||||
/* XXX: do this on statechange:
|
||||
*/
|
||||
draw_update_vertex_fetch(draw);
|
||||
cell_update_vertex_fetch(draw);
|
||||
|
||||
|
||||
batch = cell_batch_alloc(cell, sizeof(batch[0]) + sizeof(*cf));
|
||||
batch[0] = CELL_CMD_STATE_ATTRIB_FETCH;
|
||||
cf = (struct cell_attribute_fetch_code *) (&batch[1]);
|
||||
cf->base = (uint64_t) cell->attrib_fetch.store;
|
||||
cf->size = ROUNDUP16((unsigned)((void *) cell->attrib_fetch.csr
|
||||
- (void *) cell->attrib_fetch.store));
|
||||
|
||||
|
||||
for (i = 0; i < draw->vertex_fetch.nr_attrs; i++) {
|
||||
const enum pipe_format format = draw->vertex_element[i].src_format;
|
||||
const unsigned count = ((pf_size_x(format) != 0)
|
||||
+ (pf_size_y(format) != 0)
|
||||
+ (pf_size_z(format) != 0)
|
||||
+ (pf_size_w(format) != 0));
|
||||
const unsigned size = pf_size_x(format) * count;
|
||||
|
||||
batch = cell_batch_alloc(cell, sizeof(batch[0]) + sizeof(*array_info));
|
||||
|
||||
batch[0] = CELL_CMD_STATE_VS_ARRAY_INFO;
|
||||
|
||||
array_info = (struct cell_array_info *) &batch[1];
|
||||
assert(draw->vertex_fetch.src_ptr[i] != NULL);
|
||||
array_info->base = (uintptr_t) draw->vertex_fetch.src_ptr[i];
|
||||
array_info->attr = i;
|
||||
array_info->pitch = draw->vertex_fetch.pitch[i];
|
||||
array_info->size = size;
|
||||
array_info->function_offset = cell->attrib_fetch_offsets[i];
|
||||
}
|
||||
|
||||
batch = cell_batch_alloc(cell, sizeof(batch[0])
|
||||
+ sizeof(struct pipe_viewport_state));
|
||||
batch[0] = CELL_CMD_STATE_VIEWPORT;
|
||||
(void) memcpy(&batch[1], &draw->viewport,
|
||||
sizeof(struct pipe_viewport_state));
|
||||
|
||||
{
|
||||
uint64_t uniforms = (uintptr_t) draw->user.constants;
|
||||
|
||||
batch = cell_batch_alloc(cell, 2 *sizeof(batch[0]));
|
||||
batch[0] = CELL_CMD_STATE_UNIFORMS;
|
||||
batch[1] = uniforms;
|
||||
}
|
||||
|
||||
cell_batch_flush(cell);
|
||||
|
||||
vs->opcode = CELL_CMD_VS_EXECUTE;
|
||||
vs->nr_attrs = draw->vertex_fetch.nr_attrs;
|
||||
|
||||
(void) memcpy(vs->plane, draw->plane, sizeof(draw->plane));
|
||||
vs->nr_planes = draw->nr_planes;
|
||||
|
||||
for (i = 0; i < draw->vs.queue_nr; i += SPU_VERTS_PER_BATCH) {
|
||||
const unsigned n = MIN2(SPU_VERTS_PER_BATCH, draw->vs.queue_nr - i);
|
||||
|
||||
for (j = 0; j < n; j++) {
|
||||
vs->elts[j] = draw->vs.queue[i + j].elt;
|
||||
vs->vOut[j] = (uintptr_t) draw->vs.queue[i + j].vertex;
|
||||
}
|
||||
|
||||
for (/* empty */; j < SPU_VERTS_PER_BATCH; j++) {
|
||||
vs->elts[j] = vs->elts[0];
|
||||
vs->vOut[j] = (uintptr_t) draw->vs.queue[i + j].vertex;
|
||||
}
|
||||
|
||||
vs->num_elts = n;
|
||||
send_mbox_message(cell_global.spe_contexts[0], CELL_CMD_VS_EXECUTE);
|
||||
|
||||
cell_flush_int(cell, CELL_FLUSH_WAIT);
|
||||
}
|
||||
|
||||
draw->vs.post_nr = draw->vs.queue_nr;
|
||||
draw->vs.queue_nr = 0;
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
1
src/gallium/drivers/cell/spu/.gitignore
vendored
1
src/gallium/drivers/cell/spu/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
g3d_spu
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
# Gallium3D Cell driver: SPU code
|
||||
|
||||
# This makefile builds the g3d_spu.a file that's linked into the
|
||||
# PPU code/library.
|
||||
|
||||
|
||||
TOP = ../../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
PROG = g3d
|
||||
|
||||
PROG_SPU = $(PROG)_spu
|
||||
PROG_SPU_A = $(PROG)_spu.a
|
||||
PROG_SPU_EMBED_O = $(PROG)_spu-embed.o
|
||||
|
||||
|
||||
SOURCES = \
|
||||
spu_command.c \
|
||||
spu_dcache.c \
|
||||
spu_funcs.c \
|
||||
spu_main.c \
|
||||
spu_per_fragment_op.c \
|
||||
spu_render.c \
|
||||
spu_texture.c \
|
||||
spu_tile.c \
|
||||
spu_tri.c
|
||||
|
||||
OLD_SOURCES = \
|
||||
spu_exec.c \
|
||||
spu_util.c \
|
||||
spu_vertex_fetch.c \
|
||||
spu_vertex_shader.c
|
||||
|
||||
|
||||
SPU_OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
SPU_ASM_OUT = $(SOURCES:.c=.s)
|
||||
|
||||
|
||||
INCLUDE_DIRS = \
|
||||
-I$(TOP)/src/mesa \
|
||||
-I$(TOP)/src/gallium/include \
|
||||
-I$(TOP)/src/gallium/auxiliary \
|
||||
-I$(TOP)/src/gallium/drivers
|
||||
|
||||
|
||||
.c.o:
|
||||
$(SPU_CC) $(SPU_CFLAGS) -c $<
|
||||
|
||||
.c.s:
|
||||
$(SPU_CC) $(SPU_CFLAGS) -O3 -S $<
|
||||
|
||||
|
||||
# The .a file will be linked into the main/PPU executable
|
||||
default: $(PROG_SPU_A)
|
||||
|
||||
$(PROG_SPU_A): $(PROG_SPU_EMBED_O)
|
||||
$(SPU_AR) $(SPU_AR_FLAGS) $(PROG_SPU_A) $(PROG_SPU_EMBED_O)
|
||||
|
||||
$(PROG_SPU_EMBED_O): $(PROG_SPU)
|
||||
$(SPU_EMBED) $(SPU_EMBED_FLAGS) $(PROG_SPU) $(PROG_SPU) $(PROG_SPU_EMBED_O)
|
||||
|
||||
$(PROG_SPU): $(SPU_OBJECTS)
|
||||
$(SPU_CC) -o $(PROG_SPU) $(SPU_OBJECTS) $(SPU_LFLAGS)
|
||||
|
||||
|
||||
|
||||
asmfiles: $(SPU_ASM_OUT)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o *.a *.d *.s $(PROG_SPU)
|
||||
|
||||
|
||||
|
||||
depend: $(SOURCES)
|
||||
rm -f depend
|
||||
touch depend
|
||||
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(SOURCES) 2> /dev/null
|
||||
|
||||
include depend
|
||||
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef SPU_COLORPACK_H
|
||||
#define SPU_COLORPACK_H
|
||||
|
||||
|
||||
#include <transpose_matrix4x4.h>
|
||||
#include <spu_intrinsics.h>
|
||||
|
||||
|
||||
static INLINE unsigned int
|
||||
spu_pack_R8G8B8A8(vector float rgba)
|
||||
{
|
||||
vector unsigned int out = spu_convtu(rgba, 32);
|
||||
|
||||
out = spu_shuffle(out, out, ((vector unsigned char) {
|
||||
0, 4, 8, 12, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 }) );
|
||||
|
||||
return spu_extract(out, 0);
|
||||
}
|
||||
|
||||
|
||||
static INLINE unsigned int
|
||||
spu_pack_A8R8G8B8(vector float rgba)
|
||||
{
|
||||
vector unsigned int out = spu_convtu(rgba, 32);
|
||||
out = spu_shuffle(out, out, ((vector unsigned char) {
|
||||
12, 0, 4, 8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0}) );
|
||||
return spu_extract(out, 0);
|
||||
}
|
||||
|
||||
|
||||
static INLINE unsigned int
|
||||
spu_pack_B8G8R8A8(vector float rgba)
|
||||
{
|
||||
vector unsigned int out = spu_convtu(rgba, 32);
|
||||
out = spu_shuffle(out, out, ((vector unsigned char) {
|
||||
8, 4, 0, 12, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0}) );
|
||||
return spu_extract(out, 0);
|
||||
}
|
||||
|
||||
|
||||
static INLINE unsigned int
|
||||
spu_pack_color_shuffle(vector float rgba, vector unsigned char shuffle)
|
||||
{
|
||||
vector unsigned int out = spu_convtu(rgba, 32);
|
||||
out = spu_shuffle(out, out, shuffle);
|
||||
return spu_extract(out, 0);
|
||||
}
|
||||
|
||||
|
||||
static INLINE vector float
|
||||
spu_unpack_B8G8R8A8(uint color)
|
||||
{
|
||||
vector unsigned int color_u4 = spu_splats(color);
|
||||
color_u4 = spu_shuffle(color_u4, color_u4,
|
||||
((vector unsigned char) {
|
||||
2, 2, 2, 2,
|
||||
1, 1, 1, 1,
|
||||
0, 0, 0, 0,
|
||||
3, 3, 3, 3}) );
|
||||
return spu_convtf(color_u4, 32);
|
||||
}
|
||||
|
||||
|
||||
static INLINE vector float
|
||||
spu_unpack_A8R8G8B8(uint color)
|
||||
{
|
||||
vector unsigned int color_u4 = spu_splats(color);
|
||||
color_u4 = spu_shuffle(color_u4, color_u4,
|
||||
((vector unsigned char) {
|
||||
1, 1, 1, 1,
|
||||
2, 2, 2, 2,
|
||||
3, 3, 3, 3,
|
||||
0, 0, 0, 0}) );
|
||||
return spu_convtf(color_u4, 32);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \param color_in - array of 32-bit packed ARGB colors
|
||||
* \param color_out - returns float colors in RRRR, GGGG, BBBB, AAAA order
|
||||
*/
|
||||
static INLINE void
|
||||
spu_unpack_A8R8G8B8_transpose4(const vector unsigned int color_in[4],
|
||||
vector float color_out[4])
|
||||
{
|
||||
vector unsigned int c0;
|
||||
|
||||
c0 = spu_shuffle(color_in[0], color_in[0],
|
||||
((vector unsigned char) {
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0}) );
|
||||
color_out[0] = spu_convtf(c0, 32);
|
||||
|
||||
c0 = spu_shuffle(color_in[1], color_in[1],
|
||||
((vector unsigned char) {
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0}) );
|
||||
color_out[1] = spu_convtf(c0, 32);
|
||||
|
||||
c0 = spu_shuffle(color_in[2], color_in[2],
|
||||
((vector unsigned char) {
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0}) );
|
||||
color_out[2] = spu_convtf(c0, 32);
|
||||
|
||||
c0 = spu_shuffle(color_in[3], color_in[3],
|
||||
((vector unsigned char) {
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0}) );
|
||||
color_out[3] = spu_convtf(c0, 32);
|
||||
|
||||
_transpose_matrix4x4(color_out, color_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* SPU_COLORPACK_H */
|
||||
|
|
@ -1,810 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* SPU command processing code
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <libmisc.h>
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#include "spu_command.h"
|
||||
#include "spu_main.h"
|
||||
#include "spu_render.h"
|
||||
#include "spu_per_fragment_op.h"
|
||||
#include "spu_texture.h"
|
||||
#include "spu_tile.h"
|
||||
#include "spu_vertex_shader.h"
|
||||
#include "spu_dcache.h"
|
||||
#include "cell/common.h"
|
||||
|
||||
|
||||
struct spu_vs_context draw;
|
||||
|
||||
|
||||
/**
|
||||
* Buffers containing dynamically generated SPU code:
|
||||
*/
|
||||
PIPE_ALIGN_VAR(16) static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS];
|
||||
|
||||
|
||||
|
||||
static INLINE int
|
||||
align(int value, int alignment)
|
||||
{
|
||||
return (value + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tell the PPU that this SPU has finished copying a buffer to
|
||||
* local store and that it may be reused by the PPU.
|
||||
* This is done by writting a 16-byte batch-buffer-status block back into
|
||||
* main memory (in cell_context->buffer_status[]).
|
||||
*/
|
||||
static void
|
||||
release_buffer(uint buffer)
|
||||
{
|
||||
/* Evidently, using less than a 16-byte status doesn't work reliably */
|
||||
static const vector unsigned int status = {CELL_BUFFER_STATUS_FREE,
|
||||
CELL_BUFFER_STATUS_FREE,
|
||||
CELL_BUFFER_STATUS_FREE,
|
||||
CELL_BUFFER_STATUS_FREE};
|
||||
const uint index = 4 * (spu.init.id * CELL_NUM_BUFFERS + buffer);
|
||||
uint *dst = spu.init.buffer_status + index;
|
||||
|
||||
ASSERT(buffer < CELL_NUM_BUFFERS);
|
||||
|
||||
mfc_put((void *) &status, /* src in local memory */
|
||||
(unsigned int) dst, /* dst in main memory */
|
||||
sizeof(status), /* size */
|
||||
TAG_MISC, /* tag is unimportant */
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write CELL_FENCE_SIGNALLED back to the fence status qword in main memory.
|
||||
* There's a qword of status per SPU.
|
||||
*/
|
||||
static void
|
||||
cmd_fence(struct cell_command_fence *fence_cmd)
|
||||
{
|
||||
static const vector unsigned int status = {CELL_FENCE_SIGNALLED,
|
||||
CELL_FENCE_SIGNALLED,
|
||||
CELL_FENCE_SIGNALLED,
|
||||
CELL_FENCE_SIGNALLED};
|
||||
uint *dst = (uint *) fence_cmd->fence;
|
||||
dst += 4 * spu.init.id; /* main store/memory address, not local store */
|
||||
ASSERT_ALIGN16(dst);
|
||||
mfc_put((void *) &status, /* src in local memory */
|
||||
(unsigned int) dst, /* dst in main memory */
|
||||
sizeof(status), /* size */
|
||||
TAG_FENCE, /* tag */
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_clear_surface(const struct cell_command_clear_surface *clear)
|
||||
{
|
||||
D_PRINTF(CELL_DEBUG_CMD, "CLEAR SURF %u to 0x%08x\n", clear->surface, clear->value);
|
||||
|
||||
if (clear->surface == 0) {
|
||||
spu.fb.color_clear_value = clear->value;
|
||||
if (spu.init.debug_flags & CELL_DEBUG_CHECKER) {
|
||||
uint x = (spu.init.id << 4) | (spu.init.id << 12) |
|
||||
(spu.init.id << 20) | (spu.init.id << 28);
|
||||
spu.fb.color_clear_value ^= x;
|
||||
}
|
||||
}
|
||||
else {
|
||||
spu.fb.depth_clear_value = clear->value;
|
||||
}
|
||||
|
||||
#define CLEAR_OPT 1
|
||||
#if CLEAR_OPT
|
||||
|
||||
/* Simply set all tiles' status to CLEAR.
|
||||
* When we actually begin rendering into a tile, we'll initialize it to
|
||||
* the clear value. If any tiles go untouched during the frame,
|
||||
* really_clear_tiles() will set them to the clear value.
|
||||
*/
|
||||
if (clear->surface == 0) {
|
||||
memset(spu.ctile_status, TILE_STATUS_CLEAR, sizeof(spu.ctile_status));
|
||||
}
|
||||
else {
|
||||
memset(spu.ztile_status, TILE_STATUS_CLEAR, sizeof(spu.ztile_status));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* This path clears the whole framebuffer to the clear color right now.
|
||||
*/
|
||||
|
||||
/*
|
||||
printf("SPU: %s num=%d w=%d h=%d\n",
|
||||
__FUNCTION__, num_tiles, spu.fb.width_tiles, spu.fb.height_tiles);
|
||||
*/
|
||||
|
||||
/* init a single tile to the clear value */
|
||||
if (clear->surface == 0) {
|
||||
clear_c_tile(&spu.ctile);
|
||||
}
|
||||
else {
|
||||
clear_z_tile(&spu.ztile);
|
||||
}
|
||||
|
||||
/* walk over my tiles, writing the 'clear' tile's data */
|
||||
{
|
||||
const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
|
||||
uint i;
|
||||
for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
|
||||
uint tx = i % spu.fb.width_tiles;
|
||||
uint ty = i / spu.fb.width_tiles;
|
||||
if (clear->surface == 0)
|
||||
put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
|
||||
else
|
||||
put_tile(tx, ty, &spu.ztile, TAG_SURFACE_CLEAR, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (spu.init.debug_flags & CELL_DEBUG_SYNC) {
|
||||
wait_on_mask(1 << TAG_SURFACE_CLEAR);
|
||||
}
|
||||
|
||||
#endif /* CLEAR_OPT */
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "CLEAR SURF done\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_release_verts(const struct cell_command_release_verts *release)
|
||||
{
|
||||
D_PRINTF(CELL_DEBUG_CMD, "RELEASE VERTS %u\n", release->vertex_buf);
|
||||
ASSERT(release->vertex_buf != ~0U);
|
||||
release_buffer(release->vertex_buf);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process a CELL_CMD_STATE_FRAGMENT_OPS command.
|
||||
* This involves installing new fragment ops SPU code.
|
||||
* If this function is never called, we'll use a regular C fallback function
|
||||
* for fragment processing.
|
||||
*/
|
||||
static void
|
||||
cmd_state_fragment_ops(const struct cell_command_fragment_ops *fops)
|
||||
{
|
||||
D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FRAGMENT_OPS\n");
|
||||
|
||||
/* Copy state info (for fallback case only - this will eventually
|
||||
* go away when the fallback case goes away)
|
||||
*/
|
||||
memcpy(&spu.depth_stencil_alpha, &fops->dsa, sizeof(fops->dsa));
|
||||
memcpy(&spu.blend, &fops->blend, sizeof(fops->blend));
|
||||
memcpy(&spu.blend_color, &fops->blend_color, sizeof(fops->blend_color));
|
||||
|
||||
/* Make sure the SPU knows which buffers it's expected to read when
|
||||
* it's told to pull tiles.
|
||||
*/
|
||||
spu.read_depth_stencil = (spu.depth_stencil_alpha.depth.enabled || spu.depth_stencil_alpha.stencil[0].enabled);
|
||||
|
||||
/* If we're forcing the fallback code to be used (for debug purposes),
|
||||
* install that. Otherwise install the incoming SPU code.
|
||||
*/
|
||||
if ((spu.init.debug_flags & CELL_DEBUG_FRAGMENT_OP_FALLBACK) != 0) {
|
||||
static unsigned int warned = 0;
|
||||
if (!warned) {
|
||||
fprintf(stderr, "Cell Warning: using fallback per-fragment code\n");
|
||||
warned = 1;
|
||||
}
|
||||
/* The following two lines aren't really necessary if you
|
||||
* know the debug flags won't change during a run, and if you
|
||||
* know that the function pointers are initialized correctly.
|
||||
* We set them here to allow a person to change the debug
|
||||
* flags during a run (from inside a debugger).
|
||||
*/
|
||||
spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
|
||||
spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure the SPU code buffer is large enough to hold the incoming code.
|
||||
* Note that we *don't* use align_malloc() and align_free(), because
|
||||
* those utility functions are *not* available in SPU code.
|
||||
* */
|
||||
if (spu.fragment_ops_code_size < fops->total_code_size) {
|
||||
if (spu.fragment_ops_code != NULL) {
|
||||
free(spu.fragment_ops_code);
|
||||
}
|
||||
spu.fragment_ops_code_size = fops->total_code_size;
|
||||
spu.fragment_ops_code = malloc(fops->total_code_size);
|
||||
if (spu.fragment_ops_code == NULL) {
|
||||
/* Whoops. */
|
||||
fprintf(stderr, "CELL Warning: failed to allocate fragment ops code (%d bytes) - using fallback\n", fops->total_code_size);
|
||||
spu.fragment_ops_code = NULL;
|
||||
spu.fragment_ops_code_size = 0;
|
||||
spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
|
||||
spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the SPU code from the command buffer to the spu buffer */
|
||||
memcpy(spu.fragment_ops_code, fops->code, fops->total_code_size);
|
||||
|
||||
/* Set the pointers for the front-facing and back-facing fragments
|
||||
* to the specified offsets within the code. Note that if the
|
||||
* front-facing and back-facing code are the same, they'll have
|
||||
* the same offset.
|
||||
*/
|
||||
spu.fragment_ops[CELL_FACING_FRONT] = (spu_fragment_ops_func) &spu.fragment_ops_code[fops->front_code_index];
|
||||
spu.fragment_ops[CELL_FACING_BACK] = (spu_fragment_ops_func) &spu.fragment_ops_code[fops->back_code_index];
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_state_fragment_program(const struct cell_command_fragment_program *fp)
|
||||
{
|
||||
D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FRAGMENT_PROGRAM\n");
|
||||
/* Copy SPU code from batch buffer to spu buffer */
|
||||
memcpy(spu.fragment_program_code, fp->code,
|
||||
SPU_MAX_FRAGMENT_PROGRAM_INSTS * 4);
|
||||
#if 01
|
||||
/* Point function pointer at new code */
|
||||
spu.fragment_program = (spu_fragment_program_func)spu.fragment_program_code;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static uint
|
||||
cmd_state_fs_constants(const qword *buffer, uint pos)
|
||||
{
|
||||
const uint num_const = spu_extract((vector unsigned int)buffer[pos+1], 0);
|
||||
const float *constants = (const float *) &buffer[pos+2];
|
||||
uint i;
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FS_CONSTANTS (%u)\n", num_const);
|
||||
|
||||
/* Expand each float to float[4] for SOA execution */
|
||||
for (i = 0; i < num_const; i++) {
|
||||
D_PRINTF(CELL_DEBUG_CMD, " const[%u] = %f\n", i, constants[i]);
|
||||
spu.constants[i] = spu_splats(constants[i]);
|
||||
}
|
||||
|
||||
/* return new buffer pos (in 16-byte words) */
|
||||
return pos + 2 + (ROUNDUP16(num_const * sizeof(float)) / 16);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
|
||||
{
|
||||
D_PRINTF(CELL_DEBUG_CMD, "FRAMEBUFFER: %d x %d at %p, cformat 0x%x zformat 0x%x\n",
|
||||
cmd->width,
|
||||
cmd->height,
|
||||
cmd->color_start,
|
||||
cmd->color_format,
|
||||
cmd->depth_format);
|
||||
|
||||
ASSERT_ALIGN16(cmd->color_start);
|
||||
ASSERT_ALIGN16(cmd->depth_start);
|
||||
|
||||
spu.fb.color_start = cmd->color_start;
|
||||
spu.fb.depth_start = cmd->depth_start;
|
||||
spu.fb.color_format = cmd->color_format;
|
||||
spu.fb.depth_format = cmd->depth_format;
|
||||
spu.fb.width = cmd->width;
|
||||
spu.fb.height = cmd->height;
|
||||
spu.fb.width_tiles = (spu.fb.width + TILE_SIZE - 1) / TILE_SIZE;
|
||||
spu.fb.height_tiles = (spu.fb.height + TILE_SIZE - 1) / TILE_SIZE;
|
||||
|
||||
switch (spu.fb.depth_format) {
|
||||
case PIPE_FORMAT_Z32_UNORM:
|
||||
spu.fb.zsize = 4;
|
||||
spu.fb.zscale = (float) 0xffffffffu;
|
||||
break;
|
||||
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
|
||||
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
spu.fb.zsize = 4;
|
||||
spu.fb.zscale = (float) 0x00ffffffu;
|
||||
break;
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
spu.fb.zsize = 2;
|
||||
spu.fb.zscale = (float) 0xffffu;
|
||||
break;
|
||||
default:
|
||||
spu.fb.zsize = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tex texture mask_s/t and scale_s/t fields depend on the texture size and
|
||||
* sampler wrap modes.
|
||||
*/
|
||||
static void
|
||||
update_tex_masks(struct spu_texture *texture,
|
||||
const struct pipe_sampler_state *sampler)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
|
||||
int width = texture->level[i].width;
|
||||
int height = texture->level[i].height;
|
||||
|
||||
if (sampler->wrap_s == PIPE_TEX_WRAP_REPEAT)
|
||||
texture->level[i].mask_s = spu_splats(width - 1);
|
||||
else
|
||||
texture->level[i].mask_s = spu_splats(~0);
|
||||
|
||||
if (sampler->wrap_t == PIPE_TEX_WRAP_REPEAT)
|
||||
texture->level[i].mask_t = spu_splats(height - 1);
|
||||
else
|
||||
texture->level[i].mask_t = spu_splats(~0);
|
||||
|
||||
if (sampler->normalized_coords) {
|
||||
texture->level[i].scale_s = spu_splats((float) width);
|
||||
texture->level[i].scale_t = spu_splats((float) height);
|
||||
}
|
||||
else {
|
||||
texture->level[i].scale_s = spu_splats(1.0f);
|
||||
texture->level[i].scale_t = spu_splats(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_state_sampler(const struct cell_command_sampler *sampler)
|
||||
{
|
||||
uint unit = sampler->unit;
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "SAMPLER [%u]\n", unit);
|
||||
|
||||
spu.sampler[unit] = sampler->state;
|
||||
|
||||
switch (spu.sampler[unit].min_img_filter) {
|
||||
case PIPE_TEX_FILTER_LINEAR:
|
||||
spu.min_sample_texture_2d[unit] = sample_texture_2d_bilinear;
|
||||
break;
|
||||
case PIPE_TEX_FILTER_NEAREST:
|
||||
spu.min_sample_texture_2d[unit] = sample_texture_2d_nearest;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
switch (spu.sampler[sampler->unit].mag_img_filter) {
|
||||
case PIPE_TEX_FILTER_LINEAR:
|
||||
spu.mag_sample_texture_2d[unit] = sample_texture_2d_bilinear;
|
||||
break;
|
||||
case PIPE_TEX_FILTER_NEAREST:
|
||||
spu.mag_sample_texture_2d[unit] = sample_texture_2d_nearest;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
switch (spu.sampler[sampler->unit].min_mip_filter) {
|
||||
case PIPE_TEX_MIPFILTER_NEAREST:
|
||||
case PIPE_TEX_MIPFILTER_LINEAR:
|
||||
spu.sample_texture_2d[unit] = sample_texture_2d_lod;
|
||||
break;
|
||||
case PIPE_TEX_MIPFILTER_NONE:
|
||||
spu.sample_texture_2d[unit] = spu.mag_sample_texture_2d[unit];
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
update_tex_masks(&spu.texture[unit], &spu.sampler[unit]);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_state_texture(const struct cell_command_texture *texture)
|
||||
{
|
||||
const uint unit = texture->unit;
|
||||
uint i;
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "TEXTURE [%u]\n", texture->unit);
|
||||
|
||||
spu.texture[unit].max_level = 0;
|
||||
spu.texture[unit].target = texture->target;
|
||||
|
||||
for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
|
||||
uint width = texture->width[i];
|
||||
uint height = texture->height[i];
|
||||
uint depth = texture->depth[i];
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, " LEVEL %u: at %p size[0] %u x %u\n", i,
|
||||
texture->start[i], texture->width[i], texture->height[i]);
|
||||
|
||||
spu.texture[unit].level[i].start = texture->start[i];
|
||||
spu.texture[unit].level[i].width = width;
|
||||
spu.texture[unit].level[i].height = height;
|
||||
spu.texture[unit].level[i].depth = depth;
|
||||
|
||||
spu.texture[unit].level[i].tiles_per_row =
|
||||
(width + TILE_SIZE - 1) / TILE_SIZE;
|
||||
|
||||
spu.texture[unit].level[i].bytes_per_image =
|
||||
4 * align(width, TILE_SIZE) * align(height, TILE_SIZE) * depth;
|
||||
|
||||
spu.texture[unit].level[i].max_s = spu_splats((int) width - 1);
|
||||
spu.texture[unit].level[i].max_t = spu_splats((int) height - 1);
|
||||
|
||||
if (texture->start[i])
|
||||
spu.texture[unit].max_level = i;
|
||||
}
|
||||
|
||||
update_tex_masks(&spu.texture[unit], &spu.sampler[unit]);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_state_vertex_info(const struct vertex_info *vinfo)
|
||||
{
|
||||
D_PRINTF(CELL_DEBUG_CMD, "VERTEX_INFO num_attribs=%u\n", vinfo->num_attribs);
|
||||
ASSERT(vinfo->num_attribs >= 1);
|
||||
ASSERT(vinfo->num_attribs <= 8);
|
||||
memcpy(&spu.vertex_info, vinfo, sizeof(*vinfo));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_state_vs_array_info(const struct cell_array_info *vs_info)
|
||||
{
|
||||
const unsigned attr = vs_info->attr;
|
||||
|
||||
ASSERT(attr < PIPE_MAX_ATTRIBS);
|
||||
draw.vertex_fetch.src_ptr[attr] = vs_info->base;
|
||||
draw.vertex_fetch.pitch[attr] = vs_info->pitch;
|
||||
draw.vertex_fetch.size[attr] = vs_info->size;
|
||||
draw.vertex_fetch.code_offset[attr] = vs_info->function_offset;
|
||||
draw.vertex_fetch.dirty = 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_state_attrib_fetch(const struct cell_attribute_fetch_code *code)
|
||||
{
|
||||
mfc_get(attribute_fetch_code_buffer,
|
||||
(unsigned int) code->base, /* src */
|
||||
code->size,
|
||||
TAG_BATCH_BUFFER,
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
wait_on_mask(1 << TAG_BATCH_BUFFER);
|
||||
|
||||
draw.vertex_fetch.code = attribute_fetch_code_buffer;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_finish(void)
|
||||
{
|
||||
D_PRINTF(CELL_DEBUG_CMD, "FINISH\n");
|
||||
really_clear_tiles(0);
|
||||
/* wait for all outstanding DMAs to finish */
|
||||
mfc_write_tag_mask(~0);
|
||||
mfc_read_tag_status_all();
|
||||
/* send mbox message to PPU */
|
||||
spu_write_out_mbox(CELL_CMD_FINISH);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a batch of commands which was sent to us by the PPU.
|
||||
* See the cell_emit_state.c code to see where the commands come from.
|
||||
*
|
||||
* The opcode param encodes the location of the buffer and its size.
|
||||
*/
|
||||
static void
|
||||
cmd_batch(uint opcode)
|
||||
{
|
||||
const uint buf = (opcode >> 8) & 0xff;
|
||||
uint size = (opcode >> 16);
|
||||
PIPE_ALIGN_VAR(16) qword buffer[CELL_BUFFER_SIZE / 16];
|
||||
const unsigned usize = ROUNDUP16(size) / sizeof(buffer[0]);
|
||||
uint pos;
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "BATCH buffer %u, len %u, from %p\n",
|
||||
buf, size, spu.init.buffers[buf]);
|
||||
|
||||
ASSERT((opcode & CELL_CMD_OPCODE_MASK) == CELL_CMD_BATCH);
|
||||
|
||||
ASSERT_ALIGN16(spu.init.buffers[buf]);
|
||||
|
||||
size = ROUNDUP16(size);
|
||||
|
||||
ASSERT_ALIGN16(spu.init.buffers[buf]);
|
||||
|
||||
mfc_get(buffer, /* dest */
|
||||
(unsigned int) spu.init.buffers[buf], /* src */
|
||||
size,
|
||||
TAG_BATCH_BUFFER,
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
wait_on_mask(1 << TAG_BATCH_BUFFER);
|
||||
|
||||
/* Tell PPU we're done copying the buffer to local store */
|
||||
D_PRINTF(CELL_DEBUG_CMD, "release batch buf %u\n", buf);
|
||||
release_buffer(buf);
|
||||
|
||||
/*
|
||||
* Loop over commands in the batch buffer
|
||||
*/
|
||||
for (pos = 0; pos < usize; /* no incr */) {
|
||||
switch (si_to_uint(buffer[pos])) {
|
||||
/*
|
||||
* rendering commands
|
||||
*/
|
||||
case CELL_CMD_CLEAR_SURFACE:
|
||||
{
|
||||
struct cell_command_clear_surface *clr
|
||||
= (struct cell_command_clear_surface *) &buffer[pos];
|
||||
cmd_clear_surface(clr);
|
||||
pos += sizeof(*clr) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_RENDER:
|
||||
{
|
||||
struct cell_command_render *render
|
||||
= (struct cell_command_render *) &buffer[pos];
|
||||
uint pos_incr;
|
||||
cmd_render(render, &pos_incr);
|
||||
pos += ((pos_incr+1)&~1) / 2; // should 'fix' cmd_render return
|
||||
}
|
||||
break;
|
||||
/*
|
||||
* state-update commands
|
||||
*/
|
||||
case CELL_CMD_STATE_FRAMEBUFFER:
|
||||
{
|
||||
struct cell_command_framebuffer *fb
|
||||
= (struct cell_command_framebuffer *) &buffer[pos];
|
||||
cmd_state_framebuffer(fb);
|
||||
pos += sizeof(*fb) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_STATE_FRAGMENT_OPS:
|
||||
{
|
||||
struct cell_command_fragment_ops *fops
|
||||
= (struct cell_command_fragment_ops *) &buffer[pos];
|
||||
cmd_state_fragment_ops(fops);
|
||||
/* This is a variant-sized command */
|
||||
pos += ROUNDUP16(sizeof(*fops) + fops->total_code_size) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_STATE_FRAGMENT_PROGRAM:
|
||||
{
|
||||
struct cell_command_fragment_program *fp
|
||||
= (struct cell_command_fragment_program *) &buffer[pos];
|
||||
cmd_state_fragment_program(fp);
|
||||
pos += sizeof(*fp) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_STATE_FS_CONSTANTS:
|
||||
pos = cmd_state_fs_constants(buffer, pos);
|
||||
break;
|
||||
case CELL_CMD_STATE_RASTERIZER:
|
||||
{
|
||||
struct cell_command_rasterizer *rast =
|
||||
(struct cell_command_rasterizer *) &buffer[pos];
|
||||
spu.rasterizer = rast->rasterizer;
|
||||
pos += sizeof(*rast) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_STATE_SAMPLER:
|
||||
{
|
||||
struct cell_command_sampler *sampler
|
||||
= (struct cell_command_sampler *) &buffer[pos];
|
||||
cmd_state_sampler(sampler);
|
||||
pos += sizeof(*sampler) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_STATE_TEXTURE:
|
||||
{
|
||||
struct cell_command_texture *texture
|
||||
= (struct cell_command_texture *) &buffer[pos];
|
||||
cmd_state_texture(texture);
|
||||
pos += sizeof(*texture) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_STATE_VERTEX_INFO:
|
||||
cmd_state_vertex_info((struct vertex_info *) &buffer[pos+1]);
|
||||
pos += 1 + ROUNDUP16(sizeof(struct vertex_info)) / 16;
|
||||
break;
|
||||
case CELL_CMD_STATE_VIEWPORT:
|
||||
(void) memcpy(& draw.viewport, &buffer[pos+1],
|
||||
sizeof(struct pipe_viewport_state));
|
||||
pos += 1 + ROUNDUP16(sizeof(struct pipe_viewport_state)) / 16;
|
||||
break;
|
||||
case CELL_CMD_STATE_UNIFORMS:
|
||||
draw.constants = (const float (*)[4]) (uintptr_t)spu_extract((vector unsigned int)buffer[pos+1],0);
|
||||
pos += 2;
|
||||
break;
|
||||
case CELL_CMD_STATE_VS_ARRAY_INFO:
|
||||
cmd_state_vs_array_info((struct cell_array_info *) &buffer[pos+1]);
|
||||
pos += 1 + ROUNDUP16(sizeof(struct cell_array_info)) / 16;
|
||||
break;
|
||||
case CELL_CMD_STATE_BIND_VS:
|
||||
#if 0
|
||||
spu_bind_vertex_shader(&draw,
|
||||
(struct cell_shader_info *) &buffer[pos+1]);
|
||||
#endif
|
||||
pos += 1 + ROUNDUP16(sizeof(struct cell_shader_info)) / 16;
|
||||
break;
|
||||
case CELL_CMD_STATE_ATTRIB_FETCH:
|
||||
cmd_state_attrib_fetch((struct cell_attribute_fetch_code *)
|
||||
&buffer[pos+1]);
|
||||
pos += 1 + ROUNDUP16(sizeof(struct cell_attribute_fetch_code)) / 16;
|
||||
break;
|
||||
/*
|
||||
* misc commands
|
||||
*/
|
||||
case CELL_CMD_FINISH:
|
||||
cmd_finish();
|
||||
pos += 1;
|
||||
break;
|
||||
case CELL_CMD_FENCE:
|
||||
{
|
||||
struct cell_command_fence *fence_cmd =
|
||||
(struct cell_command_fence *) &buffer[pos];
|
||||
cmd_fence(fence_cmd);
|
||||
pos += sizeof(*fence_cmd) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_RELEASE_VERTS:
|
||||
{
|
||||
struct cell_command_release_verts *release
|
||||
= (struct cell_command_release_verts *) &buffer[pos];
|
||||
cmd_release_verts(release);
|
||||
pos += sizeof(*release) / 16;
|
||||
}
|
||||
break;
|
||||
case CELL_CMD_FLUSH_BUFFER_RANGE: {
|
||||
struct cell_buffer_range *br = (struct cell_buffer_range *)
|
||||
&buffer[pos+1];
|
||||
|
||||
spu_dcache_mark_dirty((unsigned) br->base, br->size);
|
||||
pos += 1 + ROUNDUP16(sizeof(struct cell_buffer_range)) / 16;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("SPU %u: bad opcode: 0x%x\n", spu.init.id, si_to_uint(buffer[pos]));
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "BATCH complete\n");
|
||||
}
|
||||
|
||||
|
||||
#define PERF 0
|
||||
|
||||
|
||||
/**
|
||||
* Main loop for SPEs: Get a command, execute it, repeat.
|
||||
*/
|
||||
void
|
||||
command_loop(void)
|
||||
{
|
||||
int exitFlag = 0;
|
||||
uint t0, t1;
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "Enter command loop\n");
|
||||
|
||||
while (!exitFlag) {
|
||||
unsigned opcode;
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "Wait for cmd...\n");
|
||||
|
||||
if (PERF)
|
||||
spu_write_decrementer(~0);
|
||||
|
||||
/* read/wait from mailbox */
|
||||
opcode = (unsigned int) spu_read_in_mbox();
|
||||
D_PRINTF(CELL_DEBUG_CMD, "got cmd 0x%x\n", opcode);
|
||||
|
||||
if (PERF)
|
||||
t0 = spu_read_decrementer();
|
||||
|
||||
switch (opcode & CELL_CMD_OPCODE_MASK) {
|
||||
case CELL_CMD_EXIT:
|
||||
D_PRINTF(CELL_DEBUG_CMD, "EXIT\n");
|
||||
exitFlag = 1;
|
||||
break;
|
||||
case CELL_CMD_VS_EXECUTE:
|
||||
#if 0
|
||||
spu_execute_vertex_shader(&draw, &cmd.vs);
|
||||
#endif
|
||||
break;
|
||||
case CELL_CMD_BATCH:
|
||||
cmd_batch(opcode);
|
||||
break;
|
||||
default:
|
||||
printf("Bad opcode 0x%x!\n", opcode & CELL_CMD_OPCODE_MASK);
|
||||
}
|
||||
|
||||
if (PERF) {
|
||||
t1 = spu_read_decrementer();
|
||||
printf("wait mbox time: %gms batch time: %gms\n",
|
||||
(~0u - t0) * spu.init.inv_timebase,
|
||||
(t0 - t1) * spu.init.inv_timebase);
|
||||
}
|
||||
}
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "Exit command loop\n");
|
||||
|
||||
if (spu.init.debug_flags & CELL_DEBUG_CACHE)
|
||||
spu_dcache_report();
|
||||
}
|
||||
|
||||
/* Initialize this module; we manage the fragment ops buffer here. */
|
||||
void
|
||||
spu_command_init(void)
|
||||
{
|
||||
/* Install default/fallback fragment processing function.
|
||||
* This will normally be overriden by a code-gen'd function
|
||||
* unless CELL_FORCE_FRAGMENT_OPS_FALLBACK is set.
|
||||
*/
|
||||
spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
|
||||
spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
|
||||
|
||||
/* Set up the basic empty buffer for code-gen'ed fragment ops */
|
||||
spu.fragment_ops_code = NULL;
|
||||
spu.fragment_ops_code_size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
spu_command_close(void)
|
||||
{
|
||||
/* Deallocate the code-gen buffer for fragment ops, and reset the
|
||||
* fragment ops functions to their initial setting (just to leave
|
||||
* things in a good state).
|
||||
*/
|
||||
if (spu.fragment_ops_code != NULL) {
|
||||
free(spu.fragment_ops_code);
|
||||
}
|
||||
spu_command_init();
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
extern void
|
||||
command_loop(void);
|
||||
|
||||
extern void
|
||||
spu_command_init(void);
|
||||
|
||||
extern void
|
||||
spu_command_close(void);
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright IBM Corporation 2008
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cell/common.h"
|
||||
#include "spu_main.h"
|
||||
#include "spu_dcache.h"
|
||||
|
||||
#define CACHELINE_LOG2SIZE 7
|
||||
#define LINE_SIZE (1U << 7)
|
||||
#define ALIGN_MASK (~(LINE_SIZE - 1))
|
||||
|
||||
#define CACHE_NAME data
|
||||
#define CACHED_TYPE qword
|
||||
#define CACHE_TYPE CACHE_TYPE_RO
|
||||
#define CACHE_SET_TAGID(set) (((set) & 0x03) + TAG_DCACHE0)
|
||||
#define CACHE_LOG2NNWAY 2
|
||||
#define CACHE_LOG2NSETS 6
|
||||
#ifdef DEBUG
|
||||
#define CACHE_STATS 1
|
||||
#endif
|
||||
#include <cache-api.h>
|
||||
|
||||
/* Yes folks, this is ugly.
|
||||
*/
|
||||
#undef CACHE_NWAY
|
||||
#undef CACHE_NSETS
|
||||
#define CACHE_NAME data
|
||||
#define CACHE_NWAY 4
|
||||
#define CACHE_NSETS (1U << 6)
|
||||
|
||||
|
||||
/**
|
||||
* Fetch between arbitrary number of bytes from an unaligned address
|
||||
*
|
||||
* \param dst Destination data buffer
|
||||
* \param ea Main memory effective address of source data
|
||||
* \param size Number of bytes to read
|
||||
*
|
||||
* \warning
|
||||
* As is hinted by the type of the \c dst pointer, this function writes
|
||||
* multiples of 16-bytes.
|
||||
*/
|
||||
void
|
||||
spu_dcache_fetch_unaligned(qword *dst, unsigned ea, unsigned size)
|
||||
{
|
||||
const int shift = ea & 0x0f;
|
||||
const unsigned read_size = ROUNDUP16(size + shift);
|
||||
const unsigned last_read = ROUNDUP16(ea + size);
|
||||
const qword *const last_write = dst + (ROUNDUP16(size) / 16);
|
||||
unsigned i;
|
||||
|
||||
|
||||
if (shift == 0) {
|
||||
/* Data is already aligned. Fetch directly into the destination buffer.
|
||||
*/
|
||||
for (i = 0; i < size; i += 16) {
|
||||
*(dst++) = cache_rd(data, ea + i);
|
||||
}
|
||||
} else {
|
||||
qword hi;
|
||||
|
||||
|
||||
/* Please exercise extreme caution when modifying this code. This code
|
||||
* must not read past the end of the page containing the source data,
|
||||
* and it must not write more than ((size + 15) / 16) qwords to the
|
||||
* destination buffer.
|
||||
*/
|
||||
ea &= ~0x0f;
|
||||
hi = cache_rd(data, ea);
|
||||
for (i = 16; i < read_size; i += 16) {
|
||||
qword lo = cache_rd(data, ea + i);
|
||||
|
||||
*(dst++) = si_or((qword) spu_slqwbyte(hi, shift),
|
||||
(qword) spu_rlmaskqwbyte(lo, shift - 16));
|
||||
hi = lo;
|
||||
}
|
||||
|
||||
if (dst != last_write) {
|
||||
*(dst++) = si_or((qword) spu_slqwbyte(hi, shift), si_il(0));
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT((ea + i) == last_read);
|
||||
ASSERT(dst == last_write);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Notify the cache that a range of main memory may have been modified
|
||||
*/
|
||||
void
|
||||
spu_dcache_mark_dirty(unsigned ea, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
const unsigned aligned_start = (ea & ALIGN_MASK);
|
||||
const unsigned aligned_end = (ea + size + (LINE_SIZE - 1))
|
||||
& ALIGN_MASK;
|
||||
|
||||
|
||||
for (i = 0; i < (CACHE_NWAY * CACHE_NSETS); i++) {
|
||||
const unsigned entry = __cache_dir[i];
|
||||
const unsigned addr = entry & ~0x0f;
|
||||
|
||||
__cache_dir[i] = ((addr >= aligned_start) && (addr < aligned_end))
|
||||
? (entry & ~CACHELINE_VALID) : entry;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print cache utilization report
|
||||
*/
|
||||
void
|
||||
spu_dcache_report(void)
|
||||
{
|
||||
#ifdef CACHE_STATS
|
||||
if (spu.init.id == 0) {
|
||||
printf("SPU 0: Texture cache report:\n");
|
||||
cache_pr_stats(data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright IBM Corporation 2008
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR 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.
|
||||
*/
|
||||
|
||||
#ifndef SPU_DCACHE_H
|
||||
#define SPU_DCACHE_H
|
||||
|
||||
extern void
|
||||
spu_dcache_fetch_unaligned(qword *dst, unsigned ea, unsigned size);
|
||||
|
||||
extern void
|
||||
spu_dcache_mark_dirty(unsigned ea, unsigned size);
|
||||
|
||||
extern void
|
||||
spu_dcache_report(void);
|
||||
|
||||
#endif /* SPU_DCACHE_H */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,173 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#if !defined SPU_EXEC_H
|
||||
#define SPU_EXEC_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
#include "spu_tgsi_exec.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Registers may be treated as float, signed int or unsigned int.
|
||||
*/
|
||||
union spu_exec_channel
|
||||
{
|
||||
float f[QUAD_SIZE];
|
||||
int i[QUAD_SIZE];
|
||||
unsigned u[QUAD_SIZE];
|
||||
qword q;
|
||||
};
|
||||
|
||||
/**
|
||||
* A vector[RGBA] of channels[4 pixels]
|
||||
*/
|
||||
struct spu_exec_vector
|
||||
{
|
||||
union spu_exec_channel xyzw[NUM_CHANNELS];
|
||||
};
|
||||
|
||||
/**
|
||||
* For fragment programs, information for computing fragment input
|
||||
* values from plane equation of the triangle/line.
|
||||
*/
|
||||
struct spu_interp_coef
|
||||
{
|
||||
float a0[NUM_CHANNELS]; /* in an xyzw layout */
|
||||
float dadx[NUM_CHANNELS];
|
||||
float dady[NUM_CHANNELS];
|
||||
};
|
||||
|
||||
|
||||
struct softpipe_tile_cache; /**< Opaque to TGSI */
|
||||
|
||||
/**
|
||||
* Information for sampling textures, which must be implemented
|
||||
* by code outside the TGSI executor.
|
||||
*/
|
||||
struct spu_sampler
|
||||
{
|
||||
const struct pipe_sampler_state *state;
|
||||
struct pipe_resource *texture;
|
||||
/** Get samples for four fragments in a quad */
|
||||
void (*get_samples)(struct spu_sampler *sampler,
|
||||
const float s[QUAD_SIZE],
|
||||
const float t[QUAD_SIZE],
|
||||
const float p[QUAD_SIZE],
|
||||
float lodbias,
|
||||
float rgba[NUM_CHANNELS][QUAD_SIZE]);
|
||||
void *pipe; /*XXX temporary*/
|
||||
struct softpipe_tile_cache *cache;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Run-time virtual machine state for executing TGSI shader.
|
||||
*/
|
||||
struct spu_exec_machine
|
||||
{
|
||||
/*
|
||||
* 32 program temporaries
|
||||
* 4 internal temporaries
|
||||
* 1 address
|
||||
*/
|
||||
PIPE_ALIGN_VAR(16)
|
||||
struct spu_exec_vector Temps[TGSI_EXEC_NUM_TEMPS
|
||||
+ TGSI_EXEC_NUM_TEMP_EXTRAS + 1];
|
||||
|
||||
struct spu_exec_vector *Addrs;
|
||||
|
||||
struct spu_sampler *Samplers;
|
||||
|
||||
float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];
|
||||
unsigned ImmLimit;
|
||||
float (*Consts)[4];
|
||||
struct spu_exec_vector *Inputs;
|
||||
struct spu_exec_vector *Outputs;
|
||||
unsigned Processor;
|
||||
|
||||
/* GEOMETRY processor only. */
|
||||
unsigned *Primitives;
|
||||
|
||||
/* FRAGMENT processor only. */
|
||||
const struct spu_interp_coef *InterpCoefs;
|
||||
struct spu_exec_vector QuadPos;
|
||||
|
||||
/* Conditional execution masks */
|
||||
uint CondMask; /**< For IF/ELSE/ENDIF */
|
||||
uint LoopMask; /**< For BGNLOOP/ENDLOOP */
|
||||
uint ContMask; /**< For loop CONT statements */
|
||||
uint FuncMask; /**< For function calls */
|
||||
uint ExecMask; /**< = CondMask & LoopMask */
|
||||
|
||||
/** Condition mask stack (for nested conditionals) */
|
||||
uint CondStack[TGSI_EXEC_MAX_COND_NESTING];
|
||||
int CondStackTop;
|
||||
|
||||
/** Loop mask stack (for nested loops) */
|
||||
uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING];
|
||||
int LoopStackTop;
|
||||
|
||||
/** Loop continue mask stack (see comments in tgsi_exec.c) */
|
||||
uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING];
|
||||
int ContStackTop;
|
||||
|
||||
/** Function execution mask stack (for executing subroutine code) */
|
||||
uint FuncStack[TGSI_EXEC_MAX_CALL_NESTING];
|
||||
int FuncStackTop;
|
||||
|
||||
/** Function call stack for saving/restoring the program counter */
|
||||
uint CallStack[TGSI_EXEC_MAX_CALL_NESTING];
|
||||
int CallStackTop;
|
||||
|
||||
struct tgsi_full_instruction *Instructions;
|
||||
uint NumInstructions;
|
||||
|
||||
struct tgsi_full_declaration *Declarations;
|
||||
uint NumDeclarations;
|
||||
};
|
||||
|
||||
|
||||
extern void
|
||||
spu_exec_machine_init(struct spu_exec_machine *mach,
|
||||
uint numSamplers,
|
||||
struct spu_sampler *samplers,
|
||||
unsigned processor);
|
||||
|
||||
extern uint
|
||||
spu_exec_machine_run( struct spu_exec_machine *mach );
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SPU_EXEC_H */
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* SPU functions accessed by shaders.
|
||||
*
|
||||
* Authors: Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <libmisc.h>
|
||||
#include <math.h>
|
||||
#include <cos14_v.h>
|
||||
#include <sin14_v.h>
|
||||
#include <simdmath/exp2f4.h>
|
||||
#include <simdmath/log2f4.h>
|
||||
#include <simdmath/powf4.h>
|
||||
|
||||
#include "cell/common.h"
|
||||
#include "spu_main.h"
|
||||
#include "spu_funcs.h"
|
||||
#include "spu_texture.h"
|
||||
|
||||
|
||||
/** For "return"-ing four vectors */
|
||||
struct vec_4x4
|
||||
{
|
||||
vector float v[4];
|
||||
};
|
||||
|
||||
|
||||
static vector float
|
||||
spu_cos(vector float x)
|
||||
{
|
||||
return _cos14_v(x);
|
||||
}
|
||||
|
||||
static vector float
|
||||
spu_sin(vector float x)
|
||||
{
|
||||
return _sin14_v(x);
|
||||
}
|
||||
|
||||
static vector float
|
||||
spu_pow(vector float x, vector float y)
|
||||
{
|
||||
return _powf4(x, y);
|
||||
}
|
||||
|
||||
static vector float
|
||||
spu_exp2(vector float x)
|
||||
{
|
||||
return _exp2f4(x);
|
||||
}
|
||||
|
||||
static vector float
|
||||
spu_log2(vector float x)
|
||||
{
|
||||
return _log2f4(x);
|
||||
}
|
||||
|
||||
|
||||
static struct vec_4x4
|
||||
spu_tex_2d(vector float s, vector float t, vector float r, vector float q,
|
||||
unsigned unit)
|
||||
{
|
||||
struct vec_4x4 colors;
|
||||
(void) r;
|
||||
(void) q;
|
||||
spu.sample_texture_2d[unit](s, t, unit, 0, 0, colors.v);
|
||||
return colors;
|
||||
}
|
||||
|
||||
static struct vec_4x4
|
||||
spu_tex_3d(vector float s, vector float t, vector float r, vector float q,
|
||||
unsigned unit)
|
||||
{
|
||||
struct vec_4x4 colors;
|
||||
(void) r;
|
||||
(void) q;
|
||||
spu.sample_texture_2d[unit](s, t, unit, 0, 0, colors.v);
|
||||
return colors;
|
||||
}
|
||||
|
||||
static struct vec_4x4
|
||||
spu_tex_cube(vector float s, vector float t, vector float r, vector float q,
|
||||
unsigned unit)
|
||||
{
|
||||
struct vec_4x4 colors;
|
||||
(void) q;
|
||||
sample_texture_cube(s, t, r, unit, colors.v);
|
||||
return colors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add named function to list of "exported" functions that will be
|
||||
* made available to the PPU-hosted code generator.
|
||||
*/
|
||||
static void
|
||||
export_func(struct cell_spu_function_info *spu_functions,
|
||||
const char *name, void *addr)
|
||||
{
|
||||
uint n = spu_functions->num;
|
||||
ASSERT(strlen(name) < 16);
|
||||
strcpy(spu_functions->names[n], name);
|
||||
spu_functions->addrs[n] = (uint) addr;
|
||||
spu_functions->num++;
|
||||
ASSERT(spu_functions->num <= 16);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return info about the SPU's function to the PPU / main memory.
|
||||
* The PPU needs to know the address of some SPU-side functions so
|
||||
* that we can generate shader code with function calls.
|
||||
*/
|
||||
void
|
||||
return_function_info(void)
|
||||
{
|
||||
PIPE_ALIGN_VAR(16) struct cell_spu_function_info funcs;
|
||||
int tag = TAG_MISC;
|
||||
|
||||
ASSERT(sizeof(funcs) == 256); /* must be multiple of 16 bytes */
|
||||
|
||||
funcs.num = 0;
|
||||
export_func(&funcs, "spu_cos", &spu_cos);
|
||||
export_func(&funcs, "spu_sin", &spu_sin);
|
||||
export_func(&funcs, "spu_pow", &spu_pow);
|
||||
export_func(&funcs, "spu_exp2", &spu_exp2);
|
||||
export_func(&funcs, "spu_log2", &spu_log2);
|
||||
export_func(&funcs, "spu_tex_2d", &spu_tex_2d);
|
||||
export_func(&funcs, "spu_tex_3d", &spu_tex_3d);
|
||||
export_func(&funcs, "spu_tex_cube", &spu_tex_cube);
|
||||
|
||||
/* Send the function info back to the PPU / main memory */
|
||||
mfc_put((void *) &funcs, /* src in local store */
|
||||
(unsigned int) spu.init.spu_functions, /* dst in main memory */
|
||||
sizeof(funcs), /* bytes */
|
||||
tag,
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
wait_on_mask(1 << tag);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SPU_FUNCS_H
|
||||
#define SPU_FUNCS_H
|
||||
|
||||
extern void
|
||||
return_function_info(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/* main() for Cell SPU code */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <libmisc.h>
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#include "spu_funcs.h"
|
||||
#include "spu_command.h"
|
||||
#include "spu_main.h"
|
||||
#include "spu_per_fragment_op.h"
|
||||
#include "spu_texture.h"
|
||||
//#include "spu_test.h"
|
||||
#include "cell/common.h"
|
||||
|
||||
|
||||
/*
|
||||
helpful headers:
|
||||
/usr/lib/gcc/spu/4.1.1/include/spu_mfcio.h
|
||||
/opt/cell/sdk/usr/include/libmisc.h
|
||||
*/
|
||||
|
||||
struct spu_global spu;
|
||||
|
||||
|
||||
static void
|
||||
one_time_init(void)
|
||||
{
|
||||
memset(spu.ctile_status, TILE_STATUS_DEFINED, sizeof(spu.ctile_status));
|
||||
memset(spu.ztile_status, TILE_STATUS_DEFINED, sizeof(spu.ztile_status));
|
||||
invalidate_tex_cache();
|
||||
}
|
||||
|
||||
/* In some versions of the SDK the SPE main takes 'unsigned long' as a
|
||||
* parameter. In others it takes 'unsigned long long'. Use a define to
|
||||
* select between the two.
|
||||
*/
|
||||
#ifdef SPU_MAIN_PARAM_LONG_LONG
|
||||
typedef unsigned long long main_param_t;
|
||||
#else
|
||||
typedef unsigned long main_param_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SPE entrypoint.
|
||||
*/
|
||||
int
|
||||
main(main_param_t speid, main_param_t argp)
|
||||
{
|
||||
int tag = 0;
|
||||
|
||||
(void) speid;
|
||||
|
||||
ASSERT(sizeof(tile_t) == TILE_SIZE * TILE_SIZE * 4);
|
||||
ASSERT(sizeof(struct cell_command_render) % 8 == 0);
|
||||
ASSERT(sizeof(struct cell_command_fragment_ops) % 8 == 0);
|
||||
ASSERT(((unsigned long) &spu.fragment_program_code) % 8 == 0);
|
||||
|
||||
one_time_init();
|
||||
spu_command_init();
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD, "main() speid=%lu\n", (unsigned long) speid);
|
||||
D_PRINTF(CELL_DEBUG_FRAGMENT_OP_FALLBACK, "using fragment op fallback\n");
|
||||
|
||||
/* get initialization data */
|
||||
mfc_get(&spu.init, /* dest */
|
||||
(unsigned int) argp, /* src */
|
||||
sizeof(struct cell_init_info), /* bytes */
|
||||
tag,
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
wait_on_mask( 1 << tag );
|
||||
|
||||
if (spu.init.id == 0) {
|
||||
return_function_info();
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (spu.init.id==0)
|
||||
spu_test_misc(spu.init.id);
|
||||
#endif
|
||||
|
||||
command_loop();
|
||||
|
||||
spu_command_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,269 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SPU_MAIN_H
|
||||
#define SPU_MAIN_H
|
||||
|
||||
|
||||
#include <spu_mfcio.h>
|
||||
|
||||
#include "cell/common.h"
|
||||
#include "draw/draw_vertex.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
|
||||
#if DEBUG
|
||||
/* These debug macros use the unusual construction ", ##__VA_ARGS__"
|
||||
* which expands to the expected comma + args if variadic arguments
|
||||
* are supplied, but swallows the comma if there are no variadic
|
||||
* arguments (which avoids syntax errors that would otherwise occur).
|
||||
*/
|
||||
#define D_PRINTF(flag, format,...) \
|
||||
if (spu.init.debug_flags & (flag)) \
|
||||
printf("SPU %u: " format, spu.init.id, ##__VA_ARGS__)
|
||||
#else
|
||||
#define D_PRINTF(...)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* A tile is basically a TILE_SIZE x TILE_SIZE block of 4-byte pixels.
|
||||
* The data may be addressed through several different types.
|
||||
*/
|
||||
typedef union {
|
||||
ushort us[TILE_SIZE][TILE_SIZE];
|
||||
uint ui[TILE_SIZE][TILE_SIZE];
|
||||
vector unsigned short us8[TILE_SIZE/2][TILE_SIZE/4];
|
||||
vector unsigned int ui4[TILE_SIZE/2][TILE_SIZE/2];
|
||||
} tile_t;
|
||||
|
||||
|
||||
#define TILE_STATUS_CLEAR 1
|
||||
#define TILE_STATUS_DEFINED 2 /**< defined in FB, but not in local store */
|
||||
#define TILE_STATUS_CLEAN 3 /**< in local store, but not changed */
|
||||
#define TILE_STATUS_DIRTY 4 /**< modified locally, but not put back yet */
|
||||
#define TILE_STATUS_GETTING 5 /**< mfc_get() called but not yet arrived */
|
||||
|
||||
|
||||
/** Function for sampling textures */
|
||||
typedef void (*spu_sample_texture_2d_func)(vector float s,
|
||||
vector float t,
|
||||
uint unit, uint level, uint face,
|
||||
vector float colors[4]);
|
||||
|
||||
|
||||
/** Function for performing per-fragment ops */
|
||||
typedef void (*spu_fragment_ops_func)(uint x, uint y,
|
||||
tile_t *colorTile,
|
||||
tile_t *depthStencilTile,
|
||||
vector float fragZ,
|
||||
vector float fragRed,
|
||||
vector float fragGreen,
|
||||
vector float fragBlue,
|
||||
vector float fragAlpha,
|
||||
vector unsigned int mask);
|
||||
|
||||
/** Function for running fragment program */
|
||||
typedef vector unsigned int (*spu_fragment_program_func)(vector float *inputs,
|
||||
vector float *outputs,
|
||||
vector float *constants);
|
||||
|
||||
|
||||
PIPE_ALIGN_TYPE(16,
|
||||
struct spu_framebuffer
|
||||
{
|
||||
void *color_start; /**< addr of color surface in main memory */
|
||||
void *depth_start; /**< addr of depth surface in main memory */
|
||||
enum pipe_format color_format;
|
||||
enum pipe_format depth_format;
|
||||
uint width; /**< width in pixels */
|
||||
uint height; /**< height in pixels */
|
||||
uint width_tiles; /**< width in tiles */
|
||||
uint height_tiles; /**< width in tiles */
|
||||
|
||||
uint color_clear_value;
|
||||
uint depth_clear_value;
|
||||
|
||||
uint zsize; /**< 0, 2 or 4 bytes per Z */
|
||||
float zscale; /**< 65535.0, 2^24-1 or 2^32-1 */
|
||||
});
|
||||
|
||||
|
||||
/** per-texture level info */
|
||||
PIPE_ALIGN_TYPE(16,
|
||||
struct spu_texture_level
|
||||
{
|
||||
void *start;
|
||||
ushort width;
|
||||
ushort height;
|
||||
ushort depth;
|
||||
ushort tiles_per_row;
|
||||
uint bytes_per_image;
|
||||
/** texcoord scale factors */
|
||||
vector float scale_s;
|
||||
vector float scale_t;
|
||||
vector float scale_r;
|
||||
/** texcoord masks (if REPEAT then size-1, else ~0) */
|
||||
vector signed int mask_s;
|
||||
vector signed int mask_t;
|
||||
vector signed int mask_r;
|
||||
/** texcoord clamp limits */
|
||||
vector signed int max_s;
|
||||
vector signed int max_t;
|
||||
vector signed int max_r;
|
||||
});
|
||||
|
||||
|
||||
PIPE_ALIGN_TYPE(16,
|
||||
struct spu_texture
|
||||
{
|
||||
struct spu_texture_level level[CELL_MAX_TEXTURE_LEVELS];
|
||||
uint max_level;
|
||||
uint target; /**< PIPE_TEXTURE_x */
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* All SPU global/context state will be in a singleton object of this type:
|
||||
*/
|
||||
PIPE_ALIGN_TYPE(16,
|
||||
struct spu_global
|
||||
{
|
||||
/** One-time init/constant info */
|
||||
struct cell_init_info init;
|
||||
|
||||
/*
|
||||
* Current state
|
||||
*/
|
||||
struct spu_framebuffer fb;
|
||||
struct pipe_depth_stencil_alpha_state depth_stencil_alpha;
|
||||
struct pipe_blend_state blend;
|
||||
struct pipe_blend_color blend_color;
|
||||
struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS];
|
||||
struct pipe_rasterizer_state rasterizer;
|
||||
struct spu_texture texture[PIPE_MAX_SAMPLERS];
|
||||
struct vertex_info vertex_info;
|
||||
|
||||
/** Current color and Z tiles */
|
||||
PIPE_ALIGN_VAR(16) tile_t ctile;
|
||||
PIPE_ALIGN_VAR(16) tile_t ztile;
|
||||
|
||||
/** Read depth/stencil tiles? */
|
||||
boolean read_depth_stencil;
|
||||
|
||||
/** Current tiles' status */
|
||||
ubyte cur_ctile_status;
|
||||
ubyte cur_ztile_status;
|
||||
|
||||
/** Status of all tiles in framebuffer */
|
||||
PIPE_ALIGN_VAR(16) ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE];
|
||||
PIPE_ALIGN_VAR(16) ubyte ztile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE];
|
||||
|
||||
/** Current fragment ops machine code, at 8-byte boundary */
|
||||
uint *fragment_ops_code;
|
||||
uint fragment_ops_code_size;
|
||||
/** Current fragment ops functions, 0 = frontfacing, 1 = backfacing */
|
||||
spu_fragment_ops_func fragment_ops[2];
|
||||
|
||||
/** Current fragment program machine code, at 8-byte boundary */
|
||||
PIPE_ALIGN_VAR(8) uint fragment_program_code[SPU_MAX_FRAGMENT_PROGRAM_INSTS];
|
||||
/** Current fragment ops function */
|
||||
spu_fragment_program_func fragment_program;
|
||||
|
||||
/** Current texture sampler function */
|
||||
spu_sample_texture_2d_func sample_texture_2d[CELL_MAX_SAMPLERS];
|
||||
spu_sample_texture_2d_func min_sample_texture_2d[CELL_MAX_SAMPLERS];
|
||||
spu_sample_texture_2d_func mag_sample_texture_2d[CELL_MAX_SAMPLERS];
|
||||
|
||||
/** Fragment program constants */
|
||||
vector float constants[4 * CELL_MAX_CONSTANTS];
|
||||
|
||||
});
|
||||
|
||||
|
||||
extern struct spu_global spu;
|
||||
|
||||
|
||||
|
||||
/* DMA TAGS */
|
||||
|
||||
#define TAG_SURFACE_CLEAR 10
|
||||
#define TAG_VERTEX_BUFFER 11
|
||||
#define TAG_READ_TILE_COLOR 12
|
||||
#define TAG_READ_TILE_Z 13
|
||||
#define TAG_WRITE_TILE_COLOR 14
|
||||
#define TAG_WRITE_TILE_Z 15
|
||||
#define TAG_INDEX_BUFFER 16
|
||||
#define TAG_BATCH_BUFFER 17
|
||||
#define TAG_MISC 18
|
||||
#define TAG_DCACHE0 20
|
||||
#define TAG_DCACHE1 21
|
||||
#define TAG_DCACHE2 22
|
||||
#define TAG_DCACHE3 23
|
||||
#define TAG_FENCE 24
|
||||
|
||||
|
||||
static INLINE void
|
||||
wait_on_mask(unsigned tagMask)
|
||||
{
|
||||
mfc_write_tag_mask( tagMask );
|
||||
/* wait for completion of _any_ DMAs specified by tagMask */
|
||||
mfc_read_tag_status_any();
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
wait_on_mask_all(unsigned tagMask)
|
||||
{
|
||||
mfc_write_tag_mask( tagMask );
|
||||
/* wait for completion of _any_ DMAs specified by tagMask */
|
||||
mfc_read_tag_status_all();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static INLINE void
|
||||
memset16(ushort *d, ushort value, uint count)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < count; i++)
|
||||
d[i] = value;
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
memset32(uint *d, uint value, uint count)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < count; i++)
|
||||
d[i] = value;
|
||||
}
|
||||
|
||||
|
||||
#endif /* SPU_MAIN_H */
|
||||
|
|
@ -1,631 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* \author Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include <transpose_matrix4x4.h>
|
||||
#include "pipe/p_format.h"
|
||||
#include "spu_main.h"
|
||||
#include "spu_colorpack.h"
|
||||
#include "spu_per_fragment_op.h"
|
||||
|
||||
|
||||
#define LINEAR_QUAD_LAYOUT 1
|
||||
|
||||
|
||||
static INLINE vector float
|
||||
spu_min(vector float a, vector float b)
|
||||
{
|
||||
vector unsigned int m;
|
||||
m = spu_cmpgt(a, b); /* m = a > b ? ~0 : 0 */
|
||||
return spu_sel(a, b, m);
|
||||
}
|
||||
|
||||
|
||||
static INLINE vector float
|
||||
spu_max(vector float a, vector float b)
|
||||
{
|
||||
vector unsigned int m;
|
||||
m = spu_cmpgt(a, b); /* m = a > b ? ~0 : 0 */
|
||||
return spu_sel(b, a, m);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by rasterizer for each quad after the shader has run. Do
|
||||
* all the per-fragment operations including alpha test, z test,
|
||||
* stencil test, blend, colormask and logicops. This is a
|
||||
* fallback/debug function. In reality we'll use a generated function
|
||||
* produced by the PPU. But this function is useful for
|
||||
* debug/validation.
|
||||
*/
|
||||
void
|
||||
spu_fallback_fragment_ops(uint x, uint y,
|
||||
tile_t *colorTile,
|
||||
tile_t *depthStencilTile,
|
||||
vector float fragZ,
|
||||
vector float fragR,
|
||||
vector float fragG,
|
||||
vector float fragB,
|
||||
vector float fragA,
|
||||
vector unsigned int mask)
|
||||
{
|
||||
vector float frag_aos[4];
|
||||
unsigned int fbc0, fbc1, fbc2, fbc3 ; /* framebuffer/tile colors */
|
||||
unsigned int fragc0, fragc1, fragc2, fragc3; /* fragment colors */
|
||||
|
||||
/*
|
||||
* Do alpha test
|
||||
*/
|
||||
if (spu.depth_stencil_alpha.alpha.enabled) {
|
||||
vector float ref = spu_splats(spu.depth_stencil_alpha.alpha.ref_value);
|
||||
vector unsigned int amask;
|
||||
|
||||
switch (spu.depth_stencil_alpha.alpha.func) {
|
||||
case PIPE_FUNC_LESS:
|
||||
amask = spu_cmpgt(ref, fragA); /* mask = (fragA < ref) */
|
||||
break;
|
||||
case PIPE_FUNC_GREATER:
|
||||
amask = spu_cmpgt(fragA, ref); /* mask = (fragA > ref) */
|
||||
break;
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
amask = spu_cmpgt(ref, fragA);
|
||||
amask = spu_nor(amask, amask);
|
||||
break;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
amask = spu_cmpgt(fragA, ref);
|
||||
amask = spu_nor(amask, amask);
|
||||
break;
|
||||
case PIPE_FUNC_EQUAL:
|
||||
amask = spu_cmpeq(ref, fragA);
|
||||
break;
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
amask = spu_cmpeq(ref, fragA);
|
||||
amask = spu_nor(amask, amask);
|
||||
break;
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
amask = spu_splats(0xffffffffU);
|
||||
break;
|
||||
case PIPE_FUNC_NEVER:
|
||||
amask = spu_splats( 0x0U);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
mask = spu_and(mask, amask);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Z and/or stencil testing...
|
||||
*/
|
||||
if (spu.depth_stencil_alpha.depth.enabled ||
|
||||
spu.depth_stencil_alpha.stencil[0].enabled) {
|
||||
|
||||
/* get four Z/Stencil values from tile */
|
||||
vector unsigned int mask24 = spu_splats((unsigned int)0x00ffffffU);
|
||||
vector unsigned int ifbZS = depthStencilTile->ui4[y/2][x/2];
|
||||
vector unsigned int ifbZ = spu_and(ifbZS, mask24);
|
||||
vector unsigned int ifbS = spu_andc(ifbZS, mask24);
|
||||
|
||||
if (spu.depth_stencil_alpha.stencil[0].enabled) {
|
||||
/* do stencil test */
|
||||
ASSERT(spu.fb.depth_format == PIPE_FORMAT_Z24_UNORM_S8_UINT);
|
||||
|
||||
}
|
||||
else if (spu.depth_stencil_alpha.depth.enabled) {
|
||||
/* do depth test */
|
||||
|
||||
ASSERT(spu.fb.depth_format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
spu.fb.depth_format == PIPE_FORMAT_Z24X8_UNORM);
|
||||
|
||||
vector unsigned int ifragZ;
|
||||
vector unsigned int zmask;
|
||||
|
||||
/* convert four fragZ from float to uint */
|
||||
fragZ = spu_mul(fragZ, spu_splats((float) 0xffffff));
|
||||
ifragZ = spu_convtu(fragZ, 0);
|
||||
|
||||
/* do depth comparison, setting zmask with results */
|
||||
switch (spu.depth_stencil_alpha.depth.func) {
|
||||
case PIPE_FUNC_LESS:
|
||||
zmask = spu_cmpgt(ifbZ, ifragZ); /* mask = (ifragZ < ifbZ) */
|
||||
break;
|
||||
case PIPE_FUNC_GREATER:
|
||||
zmask = spu_cmpgt(ifragZ, ifbZ); /* mask = (ifbZ > ifragZ) */
|
||||
break;
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
zmask = spu_cmpgt(ifbZ, ifragZ);
|
||||
zmask = spu_nor(zmask, zmask);
|
||||
break;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
zmask = spu_cmpgt(ifragZ, ifbZ);
|
||||
zmask = spu_nor(zmask, zmask);
|
||||
break;
|
||||
case PIPE_FUNC_EQUAL:
|
||||
zmask = spu_cmpeq(ifbZ, ifragZ);
|
||||
break;
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
zmask = spu_cmpeq(ifbZ, ifragZ);
|
||||
zmask = spu_nor(zmask, zmask);
|
||||
break;
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
zmask = spu_splats(0xffffffffU);
|
||||
break;
|
||||
case PIPE_FUNC_NEVER:
|
||||
zmask = spu_splats( 0x0U);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
mask = spu_and(mask, zmask);
|
||||
|
||||
/* merge framebuffer Z and fragment Z according to the mask */
|
||||
ifbZ = spu_or(spu_and(ifragZ, mask),
|
||||
spu_andc(ifbZ, mask));
|
||||
}
|
||||
|
||||
if (spu_extract(spu_orx(mask), 0)) {
|
||||
/* put new fragment Z/Stencil values back into Z/Stencil tile */
|
||||
depthStencilTile->ui4[y/2][x/2] = spu_or(ifbZ, ifbS);
|
||||
|
||||
spu.cur_ztile_status = TILE_STATUS_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If we'll need the current framebuffer/tile colors for blending
|
||||
* or logicop or colormask, fetch them now.
|
||||
*/
|
||||
if (spu.blend.rt[0].blend_enable ||
|
||||
spu.blend.logicop_enable ||
|
||||
spu.blend.rt[0].colormask != 0xf) {
|
||||
|
||||
#if LINEAR_QUAD_LAYOUT /* See comments/diagram below */
|
||||
fbc0 = colorTile->ui[y][x*2+0];
|
||||
fbc1 = colorTile->ui[y][x*2+1];
|
||||
fbc2 = colorTile->ui[y][x*2+2];
|
||||
fbc3 = colorTile->ui[y][x*2+3];
|
||||
#else
|
||||
fbc0 = colorTile->ui[y+0][x+0];
|
||||
fbc1 = colorTile->ui[y+0][x+1];
|
||||
fbc2 = colorTile->ui[y+1][x+0];
|
||||
fbc3 = colorTile->ui[y+1][x+1];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do blending
|
||||
*/
|
||||
if (spu.blend.rt[0].blend_enable) {
|
||||
/* blending terms, misc regs */
|
||||
vector float term1r, term1g, term1b, term1a;
|
||||
vector float term2r, term2g, term2b, term2a;
|
||||
vector float one, tmp;
|
||||
|
||||
vector float fbRGBA[4]; /* current framebuffer colors */
|
||||
|
||||
/* convert framebuffer colors from packed int to vector float */
|
||||
{
|
||||
vector float temp[4]; /* float colors in AOS form */
|
||||
switch (spu.fb.color_format) {
|
||||
case PIPE_FORMAT_A8R8G8B8_UNORM:
|
||||
temp[0] = spu_unpack_B8G8R8A8(fbc0);
|
||||
temp[1] = spu_unpack_B8G8R8A8(fbc1);
|
||||
temp[2] = spu_unpack_B8G8R8A8(fbc2);
|
||||
temp[3] = spu_unpack_B8G8R8A8(fbc3);
|
||||
break;
|
||||
case PIPE_FORMAT_B8G8R8A8_UNORM:
|
||||
temp[0] = spu_unpack_A8R8G8B8(fbc0);
|
||||
temp[1] = spu_unpack_A8R8G8B8(fbc1);
|
||||
temp[2] = spu_unpack_A8R8G8B8(fbc2);
|
||||
temp[3] = spu_unpack_A8R8G8B8(fbc3);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
_transpose_matrix4x4(fbRGBA, temp); /* fbRGBA = transpose(temp) */
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute Src RGB terms (fragment color * factor)
|
||||
*/
|
||||
switch (spu.blend.rt[0].rgb_src_factor) {
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
term1r = fragR;
|
||||
term1g = fragG;
|
||||
term1b = fragB;
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_ZERO:
|
||||
term1r =
|
||||
term1g =
|
||||
term1b = spu_splats(0.0f);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||
term1r = spu_mul(fragR, fragR);
|
||||
term1g = spu_mul(fragG, fragG);
|
||||
term1b = spu_mul(fragB, fragB);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||
term1r = spu_mul(fragR, fragA);
|
||||
term1g = spu_mul(fragG, fragA);
|
||||
term1b = spu_mul(fragB, fragA);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||
term1r = spu_mul(fragR, fbRGBA[0]);
|
||||
term1g = spu_mul(fragG, fbRGBA[1]);
|
||||
term1b = spu_mul(fragB, fbRGBA[1]);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||
term1r = spu_mul(fragR, fbRGBA[3]);
|
||||
term1g = spu_mul(fragG, fbRGBA[3]);
|
||||
term1b = spu_mul(fragB, fbRGBA[3]);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||
term1r = spu_mul(fragR, spu_splats(spu.blend_color.color[0]));
|
||||
term1g = spu_mul(fragG, spu_splats(spu.blend_color.color[1]));
|
||||
term1b = spu_mul(fragB, spu_splats(spu.blend_color.color[2]));
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
term1r = spu_mul(fragR, spu_splats(spu.blend_color.color[3]));
|
||||
term1g = spu_mul(fragG, spu_splats(spu.blend_color.color[3]));
|
||||
term1b = spu_mul(fragB, spu_splats(spu.blend_color.color[3]));
|
||||
break;
|
||||
/* XXX more cases */
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute Src Alpha term (fragment alpha * factor)
|
||||
*/
|
||||
switch (spu.blend.rt[0].alpha_src_factor) {
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
term1a = fragA;
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||
term1a = spu_splats(0.0f);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||
term1a = spu_mul(fragA, fragA);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||
/* fall-through */
|
||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||
term1a = spu_mul(fragA, fbRGBA[3]);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||
/* fall-through */
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
term1a = spu_mul(fragR, spu_splats(spu.blend_color.color[3]));
|
||||
break;
|
||||
/* XXX more cases */
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute Dest RGB terms (framebuffer color * factor)
|
||||
*/
|
||||
switch (spu.blend.rt[0].rgb_dst_factor) {
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
term2r = fbRGBA[0];
|
||||
term2g = fbRGBA[1];
|
||||
term2b = fbRGBA[2];
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_ZERO:
|
||||
term2r =
|
||||
term2g =
|
||||
term2b = spu_splats(0.0f);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||
term2r = spu_mul(fbRGBA[0], fragR);
|
||||
term2g = spu_mul(fbRGBA[1], fragG);
|
||||
term2b = spu_mul(fbRGBA[2], fragB);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||
term2r = spu_mul(fbRGBA[0], fragA);
|
||||
term2g = spu_mul(fbRGBA[1], fragA);
|
||||
term2b = spu_mul(fbRGBA[2], fragA);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
|
||||
one = spu_splats(1.0f);
|
||||
tmp = spu_sub(one, fragA);
|
||||
term2r = spu_mul(fbRGBA[0], tmp);
|
||||
term2g = spu_mul(fbRGBA[1], tmp);
|
||||
term2b = spu_mul(fbRGBA[2], tmp);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||
term2r = spu_mul(fbRGBA[0], fbRGBA[0]);
|
||||
term2g = spu_mul(fbRGBA[1], fbRGBA[1]);
|
||||
term2b = spu_mul(fbRGBA[2], fbRGBA[2]);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||
term2r = spu_mul(fbRGBA[0], fbRGBA[3]);
|
||||
term2g = spu_mul(fbRGBA[1], fbRGBA[3]);
|
||||
term2b = spu_mul(fbRGBA[2], fbRGBA[3]);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||
term2r = spu_mul(fbRGBA[0], spu_splats(spu.blend_color.color[0]));
|
||||
term2g = spu_mul(fbRGBA[1], spu_splats(spu.blend_color.color[1]));
|
||||
term2b = spu_mul(fbRGBA[2], spu_splats(spu.blend_color.color[2]));
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
term2r = spu_mul(fbRGBA[0], spu_splats(spu.blend_color.color[3]));
|
||||
term2g = spu_mul(fbRGBA[1], spu_splats(spu.blend_color.color[3]));
|
||||
term2b = spu_mul(fbRGBA[2], spu_splats(spu.blend_color.color[3]));
|
||||
break;
|
||||
/* XXX more cases */
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute Dest Alpha term (framebuffer alpha * factor)
|
||||
*/
|
||||
switch (spu.blend.rt[0].alpha_dst_factor) {
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
term2a = fbRGBA[3];
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||
term2a = spu_splats(0.0f);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||
term2a = spu_mul(fbRGBA[3], fragA);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
|
||||
one = spu_splats(1.0f);
|
||||
tmp = spu_sub(one, fragA);
|
||||
term2a = spu_mul(fbRGBA[3], tmp);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||
/* fall-through */
|
||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||
term2a = spu_mul(fbRGBA[3], fbRGBA[3]);
|
||||
break;
|
||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||
/* fall-through */
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
term2a = spu_mul(fbRGBA[3], spu_splats(spu.blend_color.color[3]));
|
||||
break;
|
||||
/* XXX more cases */
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Combine Src/Dest RGB terms
|
||||
*/
|
||||
switch (spu.blend.rt[0].rgb_func) {
|
||||
case PIPE_BLEND_ADD:
|
||||
fragR = spu_add(term1r, term2r);
|
||||
fragG = spu_add(term1g, term2g);
|
||||
fragB = spu_add(term1b, term2b);
|
||||
break;
|
||||
case PIPE_BLEND_SUBTRACT:
|
||||
fragR = spu_sub(term1r, term2r);
|
||||
fragG = spu_sub(term1g, term2g);
|
||||
fragB = spu_sub(term1b, term2b);
|
||||
break;
|
||||
case PIPE_BLEND_REVERSE_SUBTRACT:
|
||||
fragR = spu_sub(term2r, term1r);
|
||||
fragG = spu_sub(term2g, term1g);
|
||||
fragB = spu_sub(term2b, term1b);
|
||||
break;
|
||||
case PIPE_BLEND_MIN:
|
||||
fragR = spu_min(term1r, term2r);
|
||||
fragG = spu_min(term1g, term2g);
|
||||
fragB = spu_min(term1b, term2b);
|
||||
break;
|
||||
case PIPE_BLEND_MAX:
|
||||
fragR = spu_max(term1r, term2r);
|
||||
fragG = spu_max(term1g, term2g);
|
||||
fragB = spu_max(term1b, term2b);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Combine Src/Dest A term
|
||||
*/
|
||||
switch (spu.blend.rt[0].alpha_func) {
|
||||
case PIPE_BLEND_ADD:
|
||||
fragA = spu_add(term1a, term2a);
|
||||
break;
|
||||
case PIPE_BLEND_SUBTRACT:
|
||||
fragA = spu_sub(term1a, term2a);
|
||||
break;
|
||||
case PIPE_BLEND_REVERSE_SUBTRACT:
|
||||
fragA = spu_sub(term2a, term1a);
|
||||
break;
|
||||
case PIPE_BLEND_MIN:
|
||||
fragA = spu_min(term1a, term2a);
|
||||
break;
|
||||
case PIPE_BLEND_MAX:
|
||||
fragA = spu_max(term1a, term2a);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert RRRR,GGGG,BBBB,AAAA to RGBA,RGBA,RGBA,RGBA.
|
||||
*/
|
||||
#if 0
|
||||
/* original code */
|
||||
{
|
||||
vector float frag_soa[4];
|
||||
frag_soa[0] = fragR;
|
||||
frag_soa[1] = fragG;
|
||||
frag_soa[2] = fragB;
|
||||
frag_soa[3] = fragA;
|
||||
_transpose_matrix4x4(frag_aos, frag_soa);
|
||||
}
|
||||
#else
|
||||
/* short-cut relying on function parameter layout: */
|
||||
_transpose_matrix4x4(frag_aos, &fragR);
|
||||
(void) fragG;
|
||||
(void) fragB;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Pack fragment float colors into 32-bit RGBA words.
|
||||
*/
|
||||
switch (spu.fb.color_format) {
|
||||
case PIPE_FORMAT_B8G8R8A8_UNORM:
|
||||
fragc0 = spu_pack_A8R8G8B8(frag_aos[0]);
|
||||
fragc1 = spu_pack_A8R8G8B8(frag_aos[1]);
|
||||
fragc2 = spu_pack_A8R8G8B8(frag_aos[2]);
|
||||
fragc3 = spu_pack_A8R8G8B8(frag_aos[3]);
|
||||
break;
|
||||
case PIPE_FORMAT_A8R8G8B8_UNORM:
|
||||
fragc0 = spu_pack_B8G8R8A8(frag_aos[0]);
|
||||
fragc1 = spu_pack_B8G8R8A8(frag_aos[1]);
|
||||
fragc2 = spu_pack_B8G8R8A8(frag_aos[2]);
|
||||
fragc3 = spu_pack_B8G8R8A8(frag_aos[3]);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "SPU: Bad pixel format in spu_default_fragment_ops\n");
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do color masking
|
||||
*/
|
||||
if (spu.blend.rt[0].colormask != 0xf) {
|
||||
uint cmask = 0x0; /* each byte corresponds to a color channel */
|
||||
|
||||
/* Form bitmask depending on color buffer format and colormask bits */
|
||||
switch (spu.fb.color_format) {
|
||||
case PIPE_FORMAT_B8G8R8A8_UNORM:
|
||||
if (spu.blend.rt[0].colormask & PIPE_MASK_R)
|
||||
cmask |= 0x00ff0000; /* red */
|
||||
if (spu.blend.rt[0].colormask & PIPE_MASK_G)
|
||||
cmask |= 0x0000ff00; /* green */
|
||||
if (spu.blend.rt[0].colormask & PIPE_MASK_B)
|
||||
cmask |= 0x000000ff; /* blue */
|
||||
if (spu.blend.rt[0].colormask & PIPE_MASK_A)
|
||||
cmask |= 0xff000000; /* alpha */
|
||||
break;
|
||||
case PIPE_FORMAT_A8R8G8B8_UNORM:
|
||||
if (spu.blend.rt[0].colormask & PIPE_MASK_R)
|
||||
cmask |= 0x0000ff00; /* red */
|
||||
if (spu.blend.rt[0].colormask & PIPE_MASK_G)
|
||||
cmask |= 0x00ff0000; /* green */
|
||||
if (spu.blend.rt[0].colormask & PIPE_MASK_B)
|
||||
cmask |= 0xff000000; /* blue */
|
||||
if (spu.blend.rt[0].colormask & PIPE_MASK_A)
|
||||
cmask |= 0x000000ff; /* alpha */
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply color mask to the 32-bit packed colors.
|
||||
* if (cmask[i])
|
||||
* frag color[i] = frag color[i];
|
||||
* else
|
||||
* frag color[i] = framebuffer color[i];
|
||||
*/
|
||||
fragc0 = (fragc0 & cmask) | (fbc0 & ~cmask);
|
||||
fragc1 = (fragc1 & cmask) | (fbc1 & ~cmask);
|
||||
fragc2 = (fragc2 & cmask) | (fbc2 & ~cmask);
|
||||
fragc3 = (fragc3 & cmask) | (fbc3 & ~cmask);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do logic ops
|
||||
*/
|
||||
if (spu.blend.logicop_enable) {
|
||||
/* XXX to do */
|
||||
/* apply logicop to 32-bit packed colors (fragcx and fbcx) */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If mask is non-zero, mark tile as dirty.
|
||||
*/
|
||||
if (spu_extract(spu_orx(mask), 0)) {
|
||||
spu.cur_ctile_status = TILE_STATUS_DIRTY;
|
||||
}
|
||||
else {
|
||||
/* write no fragments */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write new fragment/quad colors to the framebuffer/tile.
|
||||
* Only write pixels where the corresponding mask word is set.
|
||||
*/
|
||||
#if LINEAR_QUAD_LAYOUT
|
||||
/*
|
||||
* Quad layout:
|
||||
* +--+--+--+--+
|
||||
* |p0|p1|p2|p3|...
|
||||
* +--+--+--+--+
|
||||
*/
|
||||
if (spu_extract(mask, 0))
|
||||
colorTile->ui[y][x*2] = fragc0;
|
||||
if (spu_extract(mask, 1))
|
||||
colorTile->ui[y][x*2+1] = fragc1;
|
||||
if (spu_extract(mask, 2))
|
||||
colorTile->ui[y][x*2+2] = fragc2;
|
||||
if (spu_extract(mask, 3))
|
||||
colorTile->ui[y][x*2+3] = fragc3;
|
||||
#else
|
||||
/*
|
||||
* Quad layout:
|
||||
* +--+--+
|
||||
* |p0|p1|...
|
||||
* +--+--+
|
||||
* |p2|p3|...
|
||||
* +--+--+
|
||||
*/
|
||||
if (spu_extract(mask, 0))
|
||||
colorTile->ui[y+0][x+0] = fragc0;
|
||||
if (spu_extract(mask, 1))
|
||||
colorTile->ui[y+0][x+1] = fragc1;
|
||||
if (spu_extract(mask, 2))
|
||||
colorTile->ui[y+1][x+0] = fragc2;
|
||||
if (spu_extract(mask, 3))
|
||||
colorTile->ui[y+1][x+1] = fragc3;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SPU_PER_FRAGMENT_OP
|
||||
#define SPU_PER_FRAGMENT_OP
|
||||
|
||||
|
||||
extern void
|
||||
spu_fallback_fragment_ops(uint x, uint y,
|
||||
tile_t *colorTile,
|
||||
tile_t *depthStencilTile,
|
||||
vector float fragZ,
|
||||
vector float fragRed,
|
||||
vector float fragGreen,
|
||||
vector float fragBlue,
|
||||
vector float fragAlpha,
|
||||
vector unsigned int mask);
|
||||
|
||||
|
||||
#endif /* SPU_PER_FRAGMENT_OP */
|
||||
|
|
@ -1,356 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <libmisc.h>
|
||||
#include <spu_mfcio.h>
|
||||
|
||||
#include "spu_main.h"
|
||||
#include "spu_render.h"
|
||||
#include "spu_shuffle.h"
|
||||
#include "spu_tri.h"
|
||||
#include "spu_tile.h"
|
||||
#include "cell/common.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
|
||||
/**
|
||||
* Given a rendering command's bounding box (in pixels) compute the
|
||||
* location of the corresponding screen tile bounding box.
|
||||
*/
|
||||
static INLINE void
|
||||
tile_bounding_box(const struct cell_command_render *render,
|
||||
uint *txmin, uint *tymin,
|
||||
uint *box_num_tiles, uint *box_width_tiles)
|
||||
{
|
||||
#if 0
|
||||
/* Debug: full-window bounding box */
|
||||
uint txmax = spu.fb.width_tiles - 1;
|
||||
uint tymax = spu.fb.height_tiles - 1;
|
||||
*txmin = 0;
|
||||
*tymin = 0;
|
||||
*box_num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
|
||||
*box_width_tiles = spu.fb.width_tiles;
|
||||
(void) render;
|
||||
(void) txmax;
|
||||
(void) tymax;
|
||||
#else
|
||||
uint txmax, tymax, box_height_tiles;
|
||||
|
||||
*txmin = (uint) render->xmin / TILE_SIZE;
|
||||
*tymin = (uint) render->ymin / TILE_SIZE;
|
||||
txmax = (uint) render->xmax / TILE_SIZE;
|
||||
tymax = (uint) render->ymax / TILE_SIZE;
|
||||
if (txmax >= spu.fb.width_tiles)
|
||||
txmax = spu.fb.width_tiles-1;
|
||||
if (tymax >= spu.fb.height_tiles)
|
||||
tymax = spu.fb.height_tiles-1;
|
||||
*box_width_tiles = txmax - *txmin + 1;
|
||||
box_height_tiles = tymax - *tymin + 1;
|
||||
*box_num_tiles = *box_width_tiles * box_height_tiles;
|
||||
#endif
|
||||
#if 0
|
||||
printf("SPU %u: bounds: %g, %g ... %g, %g\n", spu.init.id,
|
||||
render->xmin, render->ymin, render->xmax, render->ymax);
|
||||
printf("SPU %u: tiles: %u, %u .. %u, %u\n",
|
||||
spu.init.id, *txmin, *tymin, txmax, tymax);
|
||||
ASSERT(render->xmin <= render->xmax);
|
||||
ASSERT(render->ymin <= render->ymax);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** Check if the tile at (tx,ty) belongs to this SPU */
|
||||
static INLINE boolean
|
||||
my_tile(uint tx, uint ty)
|
||||
{
|
||||
return (spu.fb.width_tiles * ty + tx) % spu.init.num_spus == spu.init.id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start fetching non-clear color/Z tiles from main memory
|
||||
*/
|
||||
static INLINE void
|
||||
get_cz_tiles(uint tx, uint ty)
|
||||
{
|
||||
if (spu.read_depth_stencil) {
|
||||
if (spu.cur_ztile_status != TILE_STATUS_CLEAR) {
|
||||
//printf("SPU %u: getting Z tile %u, %u\n", spu.init.id, tx, ty);
|
||||
get_tile(tx, ty, &spu.ztile, TAG_READ_TILE_Z, 1);
|
||||
spu.cur_ztile_status = TILE_STATUS_GETTING;
|
||||
}
|
||||
}
|
||||
|
||||
if (spu.cur_ctile_status != TILE_STATUS_CLEAR) {
|
||||
//printf("SPU %u: getting C tile %u, %u\n", spu.init.id, tx, ty);
|
||||
get_tile(tx, ty, &spu.ctile, TAG_READ_TILE_COLOR, 0);
|
||||
spu.cur_ctile_status = TILE_STATUS_GETTING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start putting dirty color/Z tiles back to main memory
|
||||
*/
|
||||
static INLINE void
|
||||
put_cz_tiles(uint tx, uint ty)
|
||||
{
|
||||
if (spu.cur_ztile_status == TILE_STATUS_DIRTY) {
|
||||
/* tile was modified and needs to be written back */
|
||||
//printf("SPU %u: put dirty Z tile %u, %u\n", spu.init.id, tx, ty);
|
||||
put_tile(tx, ty, &spu.ztile, TAG_WRITE_TILE_Z, 1);
|
||||
spu.cur_ztile_status = TILE_STATUS_DEFINED;
|
||||
}
|
||||
else if (spu.cur_ztile_status == TILE_STATUS_GETTING) {
|
||||
/* tile was never used */
|
||||
spu.cur_ztile_status = TILE_STATUS_DEFINED;
|
||||
//printf("SPU %u: put getting Z tile %u, %u\n", spu.init.id, tx, ty);
|
||||
}
|
||||
|
||||
if (spu.cur_ctile_status == TILE_STATUS_DIRTY) {
|
||||
/* tile was modified and needs to be written back */
|
||||
//printf("SPU %u: put dirty C tile %u, %u\n", spu.init.id, tx, ty);
|
||||
put_tile(tx, ty, &spu.ctile, TAG_WRITE_TILE_COLOR, 0);
|
||||
spu.cur_ctile_status = TILE_STATUS_DEFINED;
|
||||
}
|
||||
else if (spu.cur_ctile_status == TILE_STATUS_GETTING) {
|
||||
/* tile was never used */
|
||||
spu.cur_ctile_status = TILE_STATUS_DEFINED;
|
||||
//printf("SPU %u: put getting C tile %u, %u\n", spu.init.id, tx, ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wait for 'put' of color/z tiles to complete.
|
||||
*/
|
||||
static INLINE void
|
||||
wait_put_cz_tiles(void)
|
||||
{
|
||||
wait_on_mask(1 << TAG_WRITE_TILE_COLOR);
|
||||
if (spu.read_depth_stencil) {
|
||||
wait_on_mask(1 << TAG_WRITE_TILE_Z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render primitives
|
||||
* \param pos_incr returns value indicating how may words to skip after
|
||||
* this command in the batch buffer
|
||||
*/
|
||||
void
|
||||
cmd_render(const struct cell_command_render *render, uint *pos_incr)
|
||||
{
|
||||
/* we'll DMA into these buffers */
|
||||
PIPE_ALIGN_VAR(16) ubyte vertex_data[CELL_BUFFER_SIZE];
|
||||
const uint vertex_size = render->vertex_size; /* in bytes */
|
||||
/*const*/ uint total_vertex_bytes = render->num_verts * vertex_size;
|
||||
uint index_bytes;
|
||||
const ubyte *vertices;
|
||||
const ushort *indexes;
|
||||
uint i, j;
|
||||
uint num_tiles;
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD,
|
||||
"RENDER prim=%u num_vert=%u num_ind=%u inline_vert=%u\n",
|
||||
render->prim_type,
|
||||
render->num_verts,
|
||||
render->num_indexes,
|
||||
render->inline_verts);
|
||||
|
||||
ASSERT(sizeof(*render) % 4 == 0);
|
||||
ASSERT(total_vertex_bytes % 16 == 0);
|
||||
ASSERT(render->prim_type == PIPE_PRIM_TRIANGLES);
|
||||
ASSERT(render->num_indexes % 3 == 0);
|
||||
|
||||
|
||||
/* indexes are right after the render command in the batch buffer */
|
||||
indexes = (const ushort *) (render + 1);
|
||||
index_bytes = ROUNDUP8(render->num_indexes * 2);
|
||||
*pos_incr = index_bytes / 8 + sizeof(*render) / 8;
|
||||
|
||||
|
||||
if (render->inline_verts) {
|
||||
/* Vertices are after indexes in batch buffer at next 16-byte addr */
|
||||
vertices = (const ubyte *) render + (*pos_incr * 8);
|
||||
vertices = (const ubyte *) align_pointer((void *) vertices, 16);
|
||||
ASSERT_ALIGN16(vertices);
|
||||
*pos_incr = ((vertices + total_vertex_bytes) - (ubyte *) render) / 8;
|
||||
}
|
||||
else {
|
||||
/* Begin DMA fetch of vertex buffer */
|
||||
ubyte *src = spu.init.buffers[render->vertex_buf];
|
||||
ubyte *dest = vertex_data;
|
||||
|
||||
/* skip vertex data we won't use */
|
||||
#if 01
|
||||
src += render->min_index * vertex_size;
|
||||
dest += render->min_index * vertex_size;
|
||||
total_vertex_bytes -= render->min_index * vertex_size;
|
||||
#endif
|
||||
ASSERT(total_vertex_bytes % 16 == 0);
|
||||
ASSERT_ALIGN16(dest);
|
||||
ASSERT_ALIGN16(src);
|
||||
|
||||
mfc_get(dest, /* in vertex_data[] array */
|
||||
(unsigned int) src, /* src in main memory */
|
||||
total_vertex_bytes, /* size */
|
||||
TAG_VERTEX_BUFFER,
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
|
||||
vertices = vertex_data;
|
||||
|
||||
wait_on_mask(1 << TAG_VERTEX_BUFFER);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** find tiles which intersect the prim bounding box
|
||||
**/
|
||||
uint txmin, tymin, box_width_tiles, box_num_tiles;
|
||||
tile_bounding_box(render, &txmin, &tymin,
|
||||
&box_num_tiles, &box_width_tiles);
|
||||
|
||||
|
||||
/* make sure any pending clears have completed */
|
||||
wait_on_mask(1 << TAG_SURFACE_CLEAR); /* XXX temporary */
|
||||
|
||||
|
||||
num_tiles = 0;
|
||||
|
||||
/**
|
||||
** loop over tiles, rendering tris
|
||||
**/
|
||||
for (i = 0; i < box_num_tiles; i++) {
|
||||
const uint tx = txmin + i % box_width_tiles;
|
||||
const uint ty = tymin + i / box_width_tiles;
|
||||
|
||||
ASSERT(tx < spu.fb.width_tiles);
|
||||
ASSERT(ty < spu.fb.height_tiles);
|
||||
|
||||
if (!my_tile(tx, ty))
|
||||
continue;
|
||||
|
||||
num_tiles++;
|
||||
|
||||
spu.cur_ctile_status = spu.ctile_status[ty][tx];
|
||||
spu.cur_ztile_status = spu.ztile_status[ty][tx];
|
||||
|
||||
get_cz_tiles(tx, ty);
|
||||
|
||||
uint drawn = 0;
|
||||
|
||||
const qword vertex_sizes = (qword)spu_splats(vertex_size);
|
||||
const qword verticess = (qword)spu_splats((uint)vertices);
|
||||
|
||||
ASSERT_ALIGN16(&indexes[0]);
|
||||
|
||||
const uint num_indexes = render->num_indexes;
|
||||
|
||||
/* loop over tris
|
||||
* &indexes[0] will be 16 byte aligned. This loop is heavily unrolled
|
||||
* avoiding variable rotates when extracting vertex indices.
|
||||
*/
|
||||
for (j = 0; j < num_indexes; j += 24) {
|
||||
/* Load three vectors, containing 24 ushort indices */
|
||||
const qword* lower_qword = (qword*)&indexes[j];
|
||||
const qword indices0 = lower_qword[0];
|
||||
const qword indices1 = lower_qword[1];
|
||||
const qword indices2 = lower_qword[2];
|
||||
|
||||
/* stores three indices for each tri n in slots 0, 1 and 2 of vsn */
|
||||
/* Straightforward rotates for these */
|
||||
qword vs0 = indices0;
|
||||
qword vs1 = si_shlqbyi(indices0, 6);
|
||||
qword vs3 = si_shlqbyi(indices1, 2);
|
||||
qword vs4 = si_shlqbyi(indices1, 8);
|
||||
qword vs6 = si_shlqbyi(indices2, 4);
|
||||
qword vs7 = si_shlqbyi(indices2, 10);
|
||||
|
||||
/* For tri 2 and 5, the three indices are split across two machine
|
||||
* words - rotate and combine */
|
||||
const qword tmp2a = si_shlqbyi(indices0, 12);
|
||||
const qword tmp2b = si_rotqmbyi(indices1, 12|16);
|
||||
qword vs2 = si_selb(tmp2a, tmp2b, si_fsmh(si_from_uint(0x20)));
|
||||
|
||||
const qword tmp5a = si_shlqbyi(indices1, 14);
|
||||
const qword tmp5b = si_rotqmbyi(indices2, 14|16);
|
||||
qword vs5 = si_selb(tmp5a, tmp5b, si_fsmh(si_from_uint(0x60)));
|
||||
|
||||
/* unpack indices from halfword slots to word slots */
|
||||
vs0 = si_shufb(vs0, vs0, SHUFB8(0,A,0,B,0,C,0,0));
|
||||
vs1 = si_shufb(vs1, vs1, SHUFB8(0,A,0,B,0,C,0,0));
|
||||
vs2 = si_shufb(vs2, vs2, SHUFB8(0,A,0,B,0,C,0,0));
|
||||
vs3 = si_shufb(vs3, vs3, SHUFB8(0,A,0,B,0,C,0,0));
|
||||
vs4 = si_shufb(vs4, vs4, SHUFB8(0,A,0,B,0,C,0,0));
|
||||
vs5 = si_shufb(vs5, vs5, SHUFB8(0,A,0,B,0,C,0,0));
|
||||
vs6 = si_shufb(vs6, vs6, SHUFB8(0,A,0,B,0,C,0,0));
|
||||
vs7 = si_shufb(vs7, vs7, SHUFB8(0,A,0,B,0,C,0,0));
|
||||
|
||||
/* Calculate address of vertex in vertices[] */
|
||||
vs0 = si_mpya(vs0, vertex_sizes, verticess);
|
||||
vs1 = si_mpya(vs1, vertex_sizes, verticess);
|
||||
vs2 = si_mpya(vs2, vertex_sizes, verticess);
|
||||
vs3 = si_mpya(vs3, vertex_sizes, verticess);
|
||||
vs4 = si_mpya(vs4, vertex_sizes, verticess);
|
||||
vs5 = si_mpya(vs5, vertex_sizes, verticess);
|
||||
vs6 = si_mpya(vs6, vertex_sizes, verticess);
|
||||
vs7 = si_mpya(vs7, vertex_sizes, verticess);
|
||||
|
||||
/* Select the appropriate call based on the number of vertices
|
||||
* remaining */
|
||||
switch(num_indexes - j) {
|
||||
default: drawn += tri_draw(vs7, tx, ty);
|
||||
case 21: drawn += tri_draw(vs6, tx, ty);
|
||||
case 18: drawn += tri_draw(vs5, tx, ty);
|
||||
case 15: drawn += tri_draw(vs4, tx, ty);
|
||||
case 12: drawn += tri_draw(vs3, tx, ty);
|
||||
case 9: drawn += tri_draw(vs2, tx, ty);
|
||||
case 6: drawn += tri_draw(vs1, tx, ty);
|
||||
case 3: drawn += tri_draw(vs0, tx, ty);
|
||||
}
|
||||
}
|
||||
|
||||
//printf("SPU %u: drew %u of %u\n", spu.init.id, drawn, render->num_indexes/3);
|
||||
|
||||
/* write color/z tiles back to main framebuffer, if dirtied */
|
||||
put_cz_tiles(tx, ty);
|
||||
|
||||
wait_put_cz_tiles(); /* XXX seems unnecessary... */
|
||||
|
||||
spu.ctile_status[ty][tx] = spu.cur_ctile_status;
|
||||
spu.ztile_status[ty][tx] = spu.cur_ztile_status;
|
||||
}
|
||||
|
||||
D_PRINTF(CELL_DEBUG_CMD,
|
||||
"RENDER done (%u tiles hit)\n",
|
||||
num_tiles);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef SPU_RENDER_H
|
||||
#define SPU_RENDER_H
|
||||
|
||||
#include "cell/common.h"
|
||||
|
||||
extern void
|
||||
cmd_render(const struct cell_command_render *render, uint *pos_incr);
|
||||
|
||||
#endif /* SPU_RENDER_H */
|
||||
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
#ifndef SPU_SHUFFLE_H
|
||||
#define SPU_SHUFFLE_H
|
||||
|
||||
/*
|
||||
* Generate shuffle patterns with minimal fuss.
|
||||
*
|
||||
* Based on ideas from
|
||||
* http://www.insomniacgames.com/tech/articles/0408/files/shuffles.pdf
|
||||
*
|
||||
* A-P indicates 0-15th position in first vector
|
||||
* a-p indicates 0-15th position in second vector
|
||||
*
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* |00|01|02|03|04|05|06|07|08|09|0a|0b|0c|0d|0e|0f|
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | A| B| C| D|
|
||||
* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
* | A| B| C| D| E| F| G| H|
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | A| B| C| D| E| F| G| H| I| J| K| L| M| N| O| P|
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
*
|
||||
* x or X indicates 0xff
|
||||
* 8 indicates 0x80
|
||||
* 0 indicates 0x00
|
||||
*
|
||||
* The macros SHUFFLE4() SHUFFLE8() and SHUFFLE16() provide a const vector
|
||||
* unsigned char literal suitable for use with spu_shuffle().
|
||||
*
|
||||
* The macros SHUFB4() SHUFB8() and SHUFB16() provide a const qword vector
|
||||
* literal suitable for use with si_shufb().
|
||||
*
|
||||
*
|
||||
* For example :
|
||||
* SHUFB4(A,A,A,A)
|
||||
* expands to :
|
||||
* ((const qword){0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3})
|
||||
*
|
||||
* SHUFFLE8(A,B,a,b,C,c,8,8)
|
||||
* expands to :
|
||||
* ((const vector unsigned char){0x00,0x01,0x02,0x03,0x10,0x11,0x12,0x13,
|
||||
* 0x04,0x05,0x14,0x15,0xe0,0xe0,0xe0,0xe0})
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spu_intrinsics.h>
|
||||
|
||||
#define SHUFFLE_PATTERN_4_A__ 0x00, 0x01, 0x02, 0x03
|
||||
#define SHUFFLE_PATTERN_4_B__ 0x04, 0x05, 0x06, 0x07
|
||||
#define SHUFFLE_PATTERN_4_C__ 0x08, 0x09, 0x0a, 0x0b
|
||||
#define SHUFFLE_PATTERN_4_D__ 0x0c, 0x0d, 0x0e, 0x0f
|
||||
#define SHUFFLE_PATTERN_4_a__ 0x10, 0x11, 0x12, 0x13
|
||||
#define SHUFFLE_PATTERN_4_b__ 0x14, 0x15, 0x16, 0x17
|
||||
#define SHUFFLE_PATTERN_4_c__ 0x18, 0x19, 0x1a, 0x1b
|
||||
#define SHUFFLE_PATTERN_4_d__ 0x1c, 0x1d, 0x1e, 0x1f
|
||||
#define SHUFFLE_PATTERN_4_X__ 0xc0, 0xc0, 0xc0, 0xc0
|
||||
#define SHUFFLE_PATTERN_4_x__ 0xc0, 0xc0, 0xc0, 0xc0
|
||||
#define SHUFFLE_PATTERN_4_0__ 0x80, 0x80, 0x80, 0x80
|
||||
#define SHUFFLE_PATTERN_4_8__ 0xe0, 0xe0, 0xe0, 0xe0
|
||||
|
||||
#define SHUFFLE_VECTOR_4__(A, B, C, D) \
|
||||
SHUFFLE_PATTERN_4_##A##__, \
|
||||
SHUFFLE_PATTERN_4_##B##__, \
|
||||
SHUFFLE_PATTERN_4_##C##__, \
|
||||
SHUFFLE_PATTERN_4_##D##__
|
||||
|
||||
#define SHUFFLE4(A, B, C, D) \
|
||||
((const vector unsigned char){ \
|
||||
SHUFFLE_VECTOR_4__(A, B, C, D) \
|
||||
})
|
||||
|
||||
#define SHUFB4(A, B, C, D) \
|
||||
((const qword){ \
|
||||
SHUFFLE_VECTOR_4__(A, B, C, D) \
|
||||
})
|
||||
|
||||
|
||||
#define SHUFFLE_PATTERN_8_A__ 0x00, 0x01
|
||||
#define SHUFFLE_PATTERN_8_B__ 0x02, 0x03
|
||||
#define SHUFFLE_PATTERN_8_C__ 0x04, 0x05
|
||||
#define SHUFFLE_PATTERN_8_D__ 0x06, 0x07
|
||||
#define SHUFFLE_PATTERN_8_E__ 0x08, 0x09
|
||||
#define SHUFFLE_PATTERN_8_F__ 0x0a, 0x0b
|
||||
#define SHUFFLE_PATTERN_8_G__ 0x0c, 0x0d
|
||||
#define SHUFFLE_PATTERN_8_H__ 0x0e, 0x0f
|
||||
#define SHUFFLE_PATTERN_8_a__ 0x10, 0x11
|
||||
#define SHUFFLE_PATTERN_8_b__ 0x12, 0x13
|
||||
#define SHUFFLE_PATTERN_8_c__ 0x14, 0x15
|
||||
#define SHUFFLE_PATTERN_8_d__ 0x16, 0x17
|
||||
#define SHUFFLE_PATTERN_8_e__ 0x18, 0x19
|
||||
#define SHUFFLE_PATTERN_8_f__ 0x1a, 0x1b
|
||||
#define SHUFFLE_PATTERN_8_g__ 0x1c, 0x1d
|
||||
#define SHUFFLE_PATTERN_8_h__ 0x1e, 0x1f
|
||||
#define SHUFFLE_PATTERN_8_X__ 0xc0, 0xc0
|
||||
#define SHUFFLE_PATTERN_8_x__ 0xc0, 0xc0
|
||||
#define SHUFFLE_PATTERN_8_0__ 0x80, 0x80
|
||||
#define SHUFFLE_PATTERN_8_8__ 0xe0, 0xe0
|
||||
|
||||
|
||||
#define SHUFFLE_VECTOR_8__(A, B, C, D, E, F, G, H) \
|
||||
SHUFFLE_PATTERN_8_##A##__, \
|
||||
SHUFFLE_PATTERN_8_##B##__, \
|
||||
SHUFFLE_PATTERN_8_##C##__, \
|
||||
SHUFFLE_PATTERN_8_##D##__, \
|
||||
SHUFFLE_PATTERN_8_##E##__, \
|
||||
SHUFFLE_PATTERN_8_##F##__, \
|
||||
SHUFFLE_PATTERN_8_##G##__, \
|
||||
SHUFFLE_PATTERN_8_##H##__
|
||||
|
||||
#define SHUFFLE8(A, B, C, D, E, F, G, H) \
|
||||
((const vector unsigned char){ \
|
||||
SHUFFLE_VECTOR_8__(A, B, C, D, E, F, G, H) \
|
||||
})
|
||||
|
||||
#define SHUFB8(A, B, C, D, E, F, G, H) \
|
||||
((const qword){ \
|
||||
SHUFFLE_VECTOR_8__(A, B, C, D, E, F, G, H) \
|
||||
})
|
||||
|
||||
|
||||
#define SHUFFLE_PATTERN_16_A__ 0x00
|
||||
#define SHUFFLE_PATTERN_16_B__ 0x01
|
||||
#define SHUFFLE_PATTERN_16_C__ 0x02
|
||||
#define SHUFFLE_PATTERN_16_D__ 0x03
|
||||
#define SHUFFLE_PATTERN_16_E__ 0x04
|
||||
#define SHUFFLE_PATTERN_16_F__ 0x05
|
||||
#define SHUFFLE_PATTERN_16_G__ 0x06
|
||||
#define SHUFFLE_PATTERN_16_H__ 0x07
|
||||
#define SHUFFLE_PATTERN_16_I__ 0x08
|
||||
#define SHUFFLE_PATTERN_16_J__ 0x09
|
||||
#define SHUFFLE_PATTERN_16_K__ 0x0a
|
||||
#define SHUFFLE_PATTERN_16_L__ 0x0b
|
||||
#define SHUFFLE_PATTERN_16_M__ 0x0c
|
||||
#define SHUFFLE_PATTERN_16_N__ 0x0d
|
||||
#define SHUFFLE_PATTERN_16_O__ 0x0e
|
||||
#define SHUFFLE_PATTERN_16_P__ 0x0f
|
||||
#define SHUFFLE_PATTERN_16_a__ 0x10
|
||||
#define SHUFFLE_PATTERN_16_b__ 0x11
|
||||
#define SHUFFLE_PATTERN_16_c__ 0x12
|
||||
#define SHUFFLE_PATTERN_16_d__ 0x13
|
||||
#define SHUFFLE_PATTERN_16_e__ 0x14
|
||||
#define SHUFFLE_PATTERN_16_f__ 0x15
|
||||
#define SHUFFLE_PATTERN_16_g__ 0x16
|
||||
#define SHUFFLE_PATTERN_16_h__ 0x17
|
||||
#define SHUFFLE_PATTERN_16_i__ 0x18
|
||||
#define SHUFFLE_PATTERN_16_j__ 0x19
|
||||
#define SHUFFLE_PATTERN_16_k__ 0x1a
|
||||
#define SHUFFLE_PATTERN_16_l__ 0x1b
|
||||
#define SHUFFLE_PATTERN_16_m__ 0x1c
|
||||
#define SHUFFLE_PATTERN_16_n__ 0x1d
|
||||
#define SHUFFLE_PATTERN_16_o__ 0x1e
|
||||
#define SHUFFLE_PATTERN_16_p__ 0x1f
|
||||
#define SHUFFLE_PATTERN_16_X__ 0xc0
|
||||
#define SHUFFLE_PATTERN_16_x__ 0xc0
|
||||
#define SHUFFLE_PATTERN_16_0__ 0x80
|
||||
#define SHUFFLE_PATTERN_16_8__ 0xe0
|
||||
|
||||
#define SHUFFLE_VECTOR_16__(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
|
||||
SHUFFLE_PATTERN_16_##A##__, \
|
||||
SHUFFLE_PATTERN_16_##B##__, \
|
||||
SHUFFLE_PATTERN_16_##C##__, \
|
||||
SHUFFLE_PATTERN_16_##D##__, \
|
||||
SHUFFLE_PATTERN_16_##E##__, \
|
||||
SHUFFLE_PATTERN_16_##F##__, \
|
||||
SHUFFLE_PATTERN_16_##G##__, \
|
||||
SHUFFLE_PATTERN_16_##H##__, \
|
||||
SHUFFLE_PATTERN_16_##I##__, \
|
||||
SHUFFLE_PATTERN_16_##J##__, \
|
||||
SHUFFLE_PATTERN_16_##K##__, \
|
||||
SHUFFLE_PATTERN_16_##L##__, \
|
||||
SHUFFLE_PATTERN_16_##M##__, \
|
||||
SHUFFLE_PATTERN_16_##N##__, \
|
||||
SHUFFLE_PATTERN_16_##O##__, \
|
||||
SHUFFLE_PATTERN_16_##P##__
|
||||
|
||||
#define SHUFFLE16(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
|
||||
((const vector unsigned char){ \
|
||||
SHUFFLE_VECTOR_16__(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
|
||||
})
|
||||
|
||||
#define SHUFB16(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
|
||||
((const qword){ \
|
||||
SHUFFLE_VECTOR_16__(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
|
@ -1,641 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "spu_main.h"
|
||||
#include "spu_texture.h"
|
||||
#include "spu_tile.h"
|
||||
#include "spu_colorpack.h"
|
||||
#include "spu_dcache.h"
|
||||
|
||||
|
||||
/**
|
||||
* Mark all tex cache entries as invalid.
|
||||
*/
|
||||
void
|
||||
invalidate_tex_cache(void)
|
||||
{
|
||||
uint lvl;
|
||||
for (lvl = 0; lvl < CELL_MAX_TEXTURE_LEVELS; lvl++) {
|
||||
uint unit = 0;
|
||||
uint bytes = 4 * spu.texture[unit].level[lvl].width
|
||||
* spu.texture[unit].level[lvl].height;
|
||||
|
||||
if (spu.texture[unit].target == PIPE_TEXTURE_CUBE)
|
||||
bytes *= 6;
|
||||
else if (spu.texture[unit].target == PIPE_TEXTURE_3D)
|
||||
bytes *= spu.texture[unit].level[lvl].depth;
|
||||
|
||||
spu_dcache_mark_dirty((unsigned) spu.texture[unit].level[lvl].start, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get four texels from locations (x[0], y[0]), (x[1], y[1]) ...
|
||||
*
|
||||
* NOTE: in the typical case of bilinear filtering, the four texels
|
||||
* are in a 2x2 group so we could get by with just two dcache fetches
|
||||
* (two side-by-side texels per fetch). But when bilinear filtering
|
||||
* wraps around a texture edge, we'll probably need code like we have
|
||||
* now.
|
||||
* FURTHERMORE: since we're rasterizing a quad of 2x2 pixels at a time,
|
||||
* it's quite likely that the four pixels in a quad will need some of the
|
||||
* same texels. So look into doing texture fetches for four pixels at
|
||||
* a time.
|
||||
*/
|
||||
static void
|
||||
get_four_texels(const struct spu_texture_level *tlevel, uint face,
|
||||
vec_int4 x, vec_int4 y,
|
||||
vec_uint4 *texels)
|
||||
{
|
||||
unsigned texture_ea = (uintptr_t) tlevel->start;
|
||||
const vec_int4 tile_x = spu_rlmask(x, -5); /* tile_x = x / 32 */
|
||||
const vec_int4 tile_y = spu_rlmask(y, -5); /* tile_y = y / 32 */
|
||||
const qword offset_x = si_andi((qword) x, 0x1f); /* offset_x = x & 0x1f */
|
||||
const qword offset_y = si_andi((qword) y, 0x1f); /* offset_y = y & 0x1f */
|
||||
|
||||
const qword tiles_per_row = (qword) spu_splats(tlevel->tiles_per_row);
|
||||
const qword tile_size = (qword) spu_splats((unsigned) sizeof(tile_t));
|
||||
|
||||
qword tile_offset = si_mpya((qword) tile_y, tiles_per_row, (qword) tile_x);
|
||||
tile_offset = si_mpy((qword) tile_offset, tile_size);
|
||||
|
||||
qword texel_offset = si_a(si_mpyui(offset_y, 32), offset_x);
|
||||
texel_offset = si_mpyui(texel_offset, 4);
|
||||
|
||||
vec_uint4 offset = (vec_uint4) si_a(tile_offset, texel_offset);
|
||||
|
||||
texture_ea = texture_ea + face * tlevel->bytes_per_image;
|
||||
|
||||
spu_dcache_fetch_unaligned((qword *) & texels[0],
|
||||
texture_ea + spu_extract(offset, 0), 4);
|
||||
spu_dcache_fetch_unaligned((qword *) & texels[1],
|
||||
texture_ea + spu_extract(offset, 1), 4);
|
||||
spu_dcache_fetch_unaligned((qword *) & texels[2],
|
||||
texture_ea + spu_extract(offset, 2), 4);
|
||||
spu_dcache_fetch_unaligned((qword *) & texels[3],
|
||||
texture_ea + spu_extract(offset, 3), 4);
|
||||
}
|
||||
|
||||
|
||||
/** clamp vec to [0, max] */
|
||||
static INLINE vector signed int
|
||||
spu_clamp(vector signed int vec, vector signed int max)
|
||||
{
|
||||
static const vector signed int zero = {0,0,0,0};
|
||||
vector unsigned int c;
|
||||
c = spu_cmpgt(vec, zero); /* c = vec > zero ? ~0 : 0 */
|
||||
vec = spu_sel(zero, vec, c);
|
||||
c = spu_cmpgt(vec, max); /* c = vec > max ? ~0 : 0 */
|
||||
vec = spu_sel(vec, max, c);
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Do nearest texture sampling for four pixels.
|
||||
* \param colors returned colors in SOA format (rrrr, gggg, bbbb, aaaa).
|
||||
*/
|
||||
void
|
||||
sample_texture_2d_nearest(vector float s, vector float t,
|
||||
uint unit, uint level, uint face,
|
||||
vector float colors[4])
|
||||
{
|
||||
const struct spu_texture_level *tlevel = &spu.texture[unit].level[level];
|
||||
vector float ss = spu_mul(s, tlevel->scale_s);
|
||||
vector float tt = spu_mul(t, tlevel->scale_t);
|
||||
vector signed int is = spu_convts(ss, 0);
|
||||
vector signed int it = spu_convts(tt, 0);
|
||||
vec_uint4 texels[4];
|
||||
|
||||
/* PIPE_TEX_WRAP_REPEAT */
|
||||
is = spu_and(is, tlevel->mask_s);
|
||||
it = spu_and(it, tlevel->mask_t);
|
||||
|
||||
/* PIPE_TEX_WRAP_CLAMP */
|
||||
is = spu_clamp(is, tlevel->max_s);
|
||||
it = spu_clamp(it, tlevel->max_t);
|
||||
|
||||
get_four_texels(tlevel, face, is, it, texels);
|
||||
|
||||
/* convert four packed ARGBA pixels to float RRRR,GGGG,BBBB,AAAA */
|
||||
spu_unpack_A8R8G8B8_transpose4(texels, colors);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do bilinear texture sampling for four pixels.
|
||||
* \param colors returned colors in SOA format (rrrr, gggg, bbbb, aaaa).
|
||||
*/
|
||||
void
|
||||
sample_texture_2d_bilinear(vector float s, vector float t,
|
||||
uint unit, uint level, uint face,
|
||||
vector float colors[4])
|
||||
{
|
||||
const struct spu_texture_level *tlevel = &spu.texture[unit].level[level];
|
||||
static const vector float half = {-0.5f, -0.5f, -0.5f, -0.5f};
|
||||
|
||||
vector float ss = spu_madd(s, tlevel->scale_s, half);
|
||||
vector float tt = spu_madd(t, tlevel->scale_t, half);
|
||||
|
||||
vector signed int is0 = spu_convts(ss, 0);
|
||||
vector signed int it0 = spu_convts(tt, 0);
|
||||
|
||||
/* is + 1, it + 1 */
|
||||
vector signed int is1 = spu_add(is0, 1);
|
||||
vector signed int it1 = spu_add(it0, 1);
|
||||
|
||||
/* PIPE_TEX_WRAP_REPEAT */
|
||||
is0 = spu_and(is0, tlevel->mask_s);
|
||||
it0 = spu_and(it0, tlevel->mask_t);
|
||||
is1 = spu_and(is1, tlevel->mask_s);
|
||||
it1 = spu_and(it1, tlevel->mask_t);
|
||||
|
||||
/* PIPE_TEX_WRAP_CLAMP */
|
||||
is0 = spu_clamp(is0, tlevel->max_s);
|
||||
it0 = spu_clamp(it0, tlevel->max_t);
|
||||
is1 = spu_clamp(is1, tlevel->max_s);
|
||||
it1 = spu_clamp(it1, tlevel->max_t);
|
||||
|
||||
/* get packed int texels */
|
||||
vector unsigned int texels[16];
|
||||
get_four_texels(tlevel, face, is0, it0, texels + 0); /* upper-left */
|
||||
get_four_texels(tlevel, face, is1, it0, texels + 4); /* upper-right */
|
||||
get_four_texels(tlevel, face, is0, it1, texels + 8); /* lower-left */
|
||||
get_four_texels(tlevel, face, is1, it1, texels + 12); /* lower-right */
|
||||
|
||||
/* convert packed int texels to float colors */
|
||||
vector float ftexels[16];
|
||||
spu_unpack_A8R8G8B8_transpose4(texels + 0, ftexels + 0);
|
||||
spu_unpack_A8R8G8B8_transpose4(texels + 4, ftexels + 4);
|
||||
spu_unpack_A8R8G8B8_transpose4(texels + 8, ftexels + 8);
|
||||
spu_unpack_A8R8G8B8_transpose4(texels + 12, ftexels + 12);
|
||||
|
||||
/* Compute weighting factors in [0,1]
|
||||
* Multiply texcoord by 1024, AND with 1023, convert back to float.
|
||||
*/
|
||||
vector float ss1024 = spu_mul(ss, spu_splats(1024.0f));
|
||||
vector signed int iss1024 = spu_convts(ss1024, 0);
|
||||
iss1024 = spu_and(iss1024, 1023);
|
||||
vector float sWeights0 = spu_convtf(iss1024, 10);
|
||||
|
||||
vector float tt1024 = spu_mul(tt, spu_splats(1024.0f));
|
||||
vector signed int itt1024 = spu_convts(tt1024, 0);
|
||||
itt1024 = spu_and(itt1024, 1023);
|
||||
vector float tWeights0 = spu_convtf(itt1024, 10);
|
||||
|
||||
/* 1 - sWeight and 1 - tWeight */
|
||||
vector float sWeights1 = spu_sub(spu_splats(1.0f), sWeights0);
|
||||
vector float tWeights1 = spu_sub(spu_splats(1.0f), tWeights0);
|
||||
|
||||
/* reds, for four pixels */
|
||||
ftexels[ 0] = spu_mul(ftexels[ 0], spu_mul(sWeights1, tWeights1)); /*ul*/
|
||||
ftexels[ 4] = spu_mul(ftexels[ 4], spu_mul(sWeights0, tWeights1)); /*ur*/
|
||||
ftexels[ 8] = spu_mul(ftexels[ 8], spu_mul(sWeights1, tWeights0)); /*ll*/
|
||||
ftexels[12] = spu_mul(ftexels[12], spu_mul(sWeights0, tWeights0)); /*lr*/
|
||||
colors[0] = spu_add(spu_add(ftexels[0], ftexels[4]),
|
||||
spu_add(ftexels[8], ftexels[12]));
|
||||
|
||||
/* greens, for four pixels */
|
||||
ftexels[ 1] = spu_mul(ftexels[ 1], spu_mul(sWeights1, tWeights1)); /*ul*/
|
||||
ftexels[ 5] = spu_mul(ftexels[ 5], spu_mul(sWeights0, tWeights1)); /*ur*/
|
||||
ftexels[ 9] = spu_mul(ftexels[ 9], spu_mul(sWeights1, tWeights0)); /*ll*/
|
||||
ftexels[13] = spu_mul(ftexels[13], spu_mul(sWeights0, tWeights0)); /*lr*/
|
||||
colors[1] = spu_add(spu_add(ftexels[1], ftexels[5]),
|
||||
spu_add(ftexels[9], ftexels[13]));
|
||||
|
||||
/* blues, for four pixels */
|
||||
ftexels[ 2] = spu_mul(ftexels[ 2], spu_mul(sWeights1, tWeights1)); /*ul*/
|
||||
ftexels[ 6] = spu_mul(ftexels[ 6], spu_mul(sWeights0, tWeights1)); /*ur*/
|
||||
ftexels[10] = spu_mul(ftexels[10], spu_mul(sWeights1, tWeights0)); /*ll*/
|
||||
ftexels[14] = spu_mul(ftexels[14], spu_mul(sWeights0, tWeights0)); /*lr*/
|
||||
colors[2] = spu_add(spu_add(ftexels[2], ftexels[6]),
|
||||
spu_add(ftexels[10], ftexels[14]));
|
||||
|
||||
/* alphas, for four pixels */
|
||||
ftexels[ 3] = spu_mul(ftexels[ 3], spu_mul(sWeights1, tWeights1)); /*ul*/
|
||||
ftexels[ 7] = spu_mul(ftexels[ 7], spu_mul(sWeights0, tWeights1)); /*ur*/
|
||||
ftexels[11] = spu_mul(ftexels[11], spu_mul(sWeights1, tWeights0)); /*ll*/
|
||||
ftexels[15] = spu_mul(ftexels[15], spu_mul(sWeights0, tWeights0)); /*lr*/
|
||||
colors[3] = spu_add(spu_add(ftexels[3], ftexels[7]),
|
||||
spu_add(ftexels[11], ftexels[15]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adapted from /opt/cell/sdk/usr/spu/include/transpose_matrix4x4.h
|
||||
*/
|
||||
static INLINE void
|
||||
transpose(vector unsigned int *mOut0,
|
||||
vector unsigned int *mOut1,
|
||||
vector unsigned int *mOut2,
|
||||
vector unsigned int *mOut3,
|
||||
vector unsigned int *mIn)
|
||||
{
|
||||
vector unsigned int abcd, efgh, ijkl, mnop; /* input vectors */
|
||||
vector unsigned int aeim, bfjn, cgko, dhlp; /* output vectors */
|
||||
vector unsigned int aibj, ckdl, emfn, gohp; /* intermediate vectors */
|
||||
|
||||
vector unsigned char shufflehi = ((vector unsigned char) {
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x10, 0x11, 0x12, 0x13,
|
||||
0x04, 0x05, 0x06, 0x07,
|
||||
0x14, 0x15, 0x16, 0x17});
|
||||
vector unsigned char shufflelo = ((vector unsigned char) {
|
||||
0x08, 0x09, 0x0A, 0x0B,
|
||||
0x18, 0x19, 0x1A, 0x1B,
|
||||
0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x1C, 0x1D, 0x1E, 0x1F});
|
||||
abcd = *(mIn+0);
|
||||
efgh = *(mIn+1);
|
||||
ijkl = *(mIn+2);
|
||||
mnop = *(mIn+3);
|
||||
|
||||
aibj = spu_shuffle(abcd, ijkl, shufflehi);
|
||||
ckdl = spu_shuffle(abcd, ijkl, shufflelo);
|
||||
emfn = spu_shuffle(efgh, mnop, shufflehi);
|
||||
gohp = spu_shuffle(efgh, mnop, shufflelo);
|
||||
|
||||
aeim = spu_shuffle(aibj, emfn, shufflehi);
|
||||
bfjn = spu_shuffle(aibj, emfn, shufflelo);
|
||||
cgko = spu_shuffle(ckdl, gohp, shufflehi);
|
||||
dhlp = spu_shuffle(ckdl, gohp, shufflelo);
|
||||
|
||||
*mOut0 = aeim;
|
||||
*mOut1 = bfjn;
|
||||
*mOut2 = cgko;
|
||||
*mOut3 = dhlp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bilinear filtering, using int instead of float arithmetic for computing
|
||||
* sample weights.
|
||||
*/
|
||||
void
|
||||
sample_texture_2d_bilinear_int(vector float s, vector float t,
|
||||
uint unit, uint level, uint face,
|
||||
vector float colors[4])
|
||||
{
|
||||
const struct spu_texture_level *tlevel = &spu.texture[unit].level[level];
|
||||
static const vector float half = {-0.5f, -0.5f, -0.5f, -0.5f};
|
||||
|
||||
/* Scale texcoords by size of texture, and add half pixel bias */
|
||||
vector float ss = spu_madd(s, tlevel->scale_s, half);
|
||||
vector float tt = spu_madd(t, tlevel->scale_t, half);
|
||||
|
||||
/* convert float coords to fixed-pt coords with 7 fraction bits */
|
||||
vector signed int is = spu_convts(ss, 7); /* XXX really need floor() here */
|
||||
vector signed int it = spu_convts(tt, 7); /* XXX really need floor() here */
|
||||
|
||||
/* compute integer texel weights in [0, 127] */
|
||||
vector signed int sWeights0 = spu_and(is, 127);
|
||||
vector signed int tWeights0 = spu_and(it, 127);
|
||||
vector signed int sWeights1 = spu_sub(127, sWeights0);
|
||||
vector signed int tWeights1 = spu_sub(127, tWeights0);
|
||||
|
||||
/* texel coords: is0 = is / 128, it0 = is / 128 */
|
||||
vector signed int is0 = spu_rlmask(is, -7);
|
||||
vector signed int it0 = spu_rlmask(it, -7);
|
||||
|
||||
/* texel coords: i1 = is0 + 1, it1 = it0 + 1 */
|
||||
vector signed int is1 = spu_add(is0, 1);
|
||||
vector signed int it1 = spu_add(it0, 1);
|
||||
|
||||
/* PIPE_TEX_WRAP_REPEAT */
|
||||
is0 = spu_and(is0, tlevel->mask_s);
|
||||
it0 = spu_and(it0, tlevel->mask_t);
|
||||
is1 = spu_and(is1, tlevel->mask_s);
|
||||
it1 = spu_and(it1, tlevel->mask_t);
|
||||
|
||||
/* PIPE_TEX_WRAP_CLAMP */
|
||||
is0 = spu_clamp(is0, tlevel->max_s);
|
||||
it0 = spu_clamp(it0, tlevel->max_t);
|
||||
is1 = spu_clamp(is1, tlevel->max_s);
|
||||
it1 = spu_clamp(it1, tlevel->max_t);
|
||||
|
||||
/* get packed int texels */
|
||||
vector unsigned int texels[16];
|
||||
get_four_texels(tlevel, face, is0, it0, texels + 0); /* upper-left */
|
||||
get_four_texels(tlevel, face, is1, it0, texels + 4); /* upper-right */
|
||||
get_four_texels(tlevel, face, is0, it1, texels + 8); /* lower-left */
|
||||
get_four_texels(tlevel, face, is1, it1, texels + 12); /* lower-right */
|
||||
|
||||
/* twiddle packed 32-bit BGRA pixels into RGBA as four unsigned ints */
|
||||
{
|
||||
static const unsigned char ZERO = 0x80;
|
||||
int i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
texels[i] = spu_shuffle(texels[i], texels[i],
|
||||
((vector unsigned char) {
|
||||
ZERO, ZERO, ZERO, 1,
|
||||
ZERO, ZERO, ZERO, 2,
|
||||
ZERO, ZERO, ZERO, 3,
|
||||
ZERO, ZERO, ZERO, 0}));
|
||||
}
|
||||
}
|
||||
|
||||
/* convert RGBA,RGBA,RGBA,RGBA to RRRR,GGGG,BBBB,AAAA */
|
||||
vector unsigned int texel0, texel1, texel2, texel3, texel4, texel5, texel6, texel7,
|
||||
texel8, texel9, texel10, texel11, texel12, texel13, texel14, texel15;
|
||||
transpose(&texel0, &texel1, &texel2, &texel3, texels + 0);
|
||||
transpose(&texel4, &texel5, &texel6, &texel7, texels + 4);
|
||||
transpose(&texel8, &texel9, &texel10, &texel11, texels + 8);
|
||||
transpose(&texel12, &texel13, &texel14, &texel15, texels + 12);
|
||||
|
||||
/* computed weighted colors */
|
||||
vector unsigned int c0, c1, c2, c3, cSum;
|
||||
|
||||
/* red */
|
||||
c0 = (vector unsigned int) si_mpy((qword) texel0, si_mpy((qword) sWeights1, (qword) tWeights1)); /*ul*/
|
||||
c1 = (vector unsigned int) si_mpy((qword) texel4, si_mpy((qword) sWeights0, (qword) tWeights1)); /*ur*/
|
||||
c2 = (vector unsigned int) si_mpy((qword) texel8, si_mpy((qword) sWeights1, (qword) tWeights0)); /*ll*/
|
||||
c3 = (vector unsigned int) si_mpy((qword) texel12, si_mpy((qword) sWeights0, (qword) tWeights0)); /*lr*/
|
||||
cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
|
||||
colors[0] = spu_convtf(cSum, 22);
|
||||
|
||||
/* green */
|
||||
c0 = (vector unsigned int) si_mpy((qword) texel1, si_mpy((qword) sWeights1, (qword) tWeights1)); /*ul*/
|
||||
c1 = (vector unsigned int) si_mpy((qword) texel5, si_mpy((qword) sWeights0, (qword) tWeights1)); /*ur*/
|
||||
c2 = (vector unsigned int) si_mpy((qword) texel9, si_mpy((qword) sWeights1, (qword) tWeights0)); /*ll*/
|
||||
c3 = (vector unsigned int) si_mpy((qword) texel13, si_mpy((qword) sWeights0, (qword) tWeights0)); /*lr*/
|
||||
cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
|
||||
colors[1] = spu_convtf(cSum, 22);
|
||||
|
||||
/* blue */
|
||||
c0 = (vector unsigned int) si_mpy((qword) texel2, si_mpy((qword) sWeights1, (qword) tWeights1)); /*ul*/
|
||||
c1 = (vector unsigned int) si_mpy((qword) texel6, si_mpy((qword) sWeights0, (qword) tWeights1)); /*ur*/
|
||||
c2 = (vector unsigned int) si_mpy((qword) texel10, si_mpy((qword) sWeights1, (qword) tWeights0)); /*ll*/
|
||||
c3 = (vector unsigned int) si_mpy((qword) texel14, si_mpy((qword) sWeights0, (qword) tWeights0)); /*lr*/
|
||||
cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
|
||||
colors[2] = spu_convtf(cSum, 22);
|
||||
|
||||
/* alpha */
|
||||
c0 = (vector unsigned int) si_mpy((qword) texel3, si_mpy((qword) sWeights1, (qword) tWeights1)); /*ul*/
|
||||
c1 = (vector unsigned int) si_mpy((qword) texel7, si_mpy((qword) sWeights0, (qword) tWeights1)); /*ur*/
|
||||
c2 = (vector unsigned int) si_mpy((qword) texel11, si_mpy((qword) sWeights1, (qword) tWeights0)); /*ll*/
|
||||
c3 = (vector unsigned int) si_mpy((qword) texel15, si_mpy((qword) sWeights0, (qword) tWeights0)); /*lr*/
|
||||
cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
|
||||
colors[3] = spu_convtf(cSum, 22);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compute level of detail factor from texcoords.
|
||||
*/
|
||||
static INLINE float
|
||||
compute_lambda_2d(uint unit, vector float s, vector float t)
|
||||
{
|
||||
uint baseLevel = 0;
|
||||
float width = spu.texture[unit].level[baseLevel].width;
|
||||
float height = spu.texture[unit].level[baseLevel].width;
|
||||
float dsdx = width * (spu_extract(s, 1) - spu_extract(s, 0));
|
||||
float dsdy = width * (spu_extract(s, 2) - spu_extract(s, 0));
|
||||
float dtdx = height * (spu_extract(t, 1) - spu_extract(t, 0));
|
||||
float dtdy = height * (spu_extract(t, 2) - spu_extract(t, 0));
|
||||
#if 0
|
||||
/* ideal value */
|
||||
float x = dsdx * dsdx + dtdx * dtdx;
|
||||
float y = dsdy * dsdy + dtdy * dtdy;
|
||||
float rho = x > y ? x : y;
|
||||
rho = sqrtf(rho);
|
||||
#else
|
||||
/* approximation */
|
||||
dsdx = fabsf(dsdx);
|
||||
dsdy = fabsf(dsdy);
|
||||
dtdx = fabsf(dtdx);
|
||||
dtdy = fabsf(dtdy);
|
||||
float rho = (dsdx + dsdy + dtdx + dtdy) * 0.5;
|
||||
#endif
|
||||
float lambda = logf(rho) * 1.442695f; /* compute logbase2(rho) */
|
||||
return lambda;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Blend two sets of colors according to weight.
|
||||
*/
|
||||
static void
|
||||
blend_colors(vector float c0[4], const vector float c1[4], float weight)
|
||||
{
|
||||
vector float t = spu_splats(weight);
|
||||
vector float dc0 = spu_sub(c1[0], c0[0]);
|
||||
vector float dc1 = spu_sub(c1[1], c0[1]);
|
||||
vector float dc2 = spu_sub(c1[2], c0[2]);
|
||||
vector float dc3 = spu_sub(c1[3], c0[3]);
|
||||
c0[0] = spu_madd(dc0, t, c0[0]);
|
||||
c0[1] = spu_madd(dc1, t, c0[1]);
|
||||
c0[2] = spu_madd(dc2, t, c0[2]);
|
||||
c0[3] = spu_madd(dc3, t, c0[3]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Texture sampling with level of detail selection and possibly mipmap
|
||||
* interpolation.
|
||||
*/
|
||||
void
|
||||
sample_texture_2d_lod(vector float s, vector float t,
|
||||
uint unit, uint level_ignored, uint face,
|
||||
vector float colors[4])
|
||||
{
|
||||
/*
|
||||
* Note that we're computing a lambda/lod here that's used for all
|
||||
* four pixels in the quad.
|
||||
*/
|
||||
float lambda = compute_lambda_2d(unit, s, t);
|
||||
|
||||
(void) face;
|
||||
(void) level_ignored;
|
||||
|
||||
/* apply lod bias */
|
||||
lambda += spu.sampler[unit].lod_bias;
|
||||
|
||||
/* clamp */
|
||||
if (lambda < spu.sampler[unit].min_lod)
|
||||
lambda = spu.sampler[unit].min_lod;
|
||||
else if (lambda > spu.sampler[unit].max_lod)
|
||||
lambda = spu.sampler[unit].max_lod;
|
||||
|
||||
if (lambda <= 0.0f) {
|
||||
/* magnify */
|
||||
spu.mag_sample_texture_2d[unit](s, t, unit, 0, face, colors);
|
||||
}
|
||||
else {
|
||||
/* minify */
|
||||
if (spu.sampler[unit].min_img_filter == PIPE_TEX_FILTER_LINEAR) {
|
||||
/* sample two mipmap levels and interpolate */
|
||||
int level = (int) lambda;
|
||||
if (level > (int) spu.texture[unit].max_level)
|
||||
level = spu.texture[unit].max_level;
|
||||
spu.min_sample_texture_2d[unit](s, t, unit, level, face, colors);
|
||||
if (spu.sampler[unit].min_img_filter == PIPE_TEX_FILTER_LINEAR) {
|
||||
/* sample second mipmap level */
|
||||
float weight = lambda - (float) level;
|
||||
level++;
|
||||
if (level <= (int) spu.texture[unit].max_level) {
|
||||
vector float colors2[4];
|
||||
spu.min_sample_texture_2d[unit](s, t, unit, level, face, colors2);
|
||||
blend_colors(colors, colors2, weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* sample one mipmap level */
|
||||
int level = (int) (lambda + 0.5f);
|
||||
if (level > (int) spu.texture[unit].max_level)
|
||||
level = spu.texture[unit].max_level;
|
||||
spu.min_sample_texture_2d[unit](s, t, unit, level, face, colors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** XXX need a SIMD version of this */
|
||||
static unsigned
|
||||
choose_cube_face(float rx, float ry, float rz, float *newS, float *newT)
|
||||
{
|
||||
/*
|
||||
major axis
|
||||
direction target sc tc ma
|
||||
---------- ------------------------------- --- --- ---
|
||||
+rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
|
||||
-rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
|
||||
+ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
|
||||
-ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
|
||||
+rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
|
||||
-rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
|
||||
*/
|
||||
const float arx = fabsf(rx);
|
||||
const float ary = fabsf(ry);
|
||||
const float arz = fabsf(rz);
|
||||
unsigned face;
|
||||
float sc, tc, ma;
|
||||
|
||||
if (arx > ary && arx > arz) {
|
||||
if (rx >= 0.0F) {
|
||||
face = PIPE_TEX_FACE_POS_X;
|
||||
sc = -rz;
|
||||
tc = -ry;
|
||||
ma = arx;
|
||||
}
|
||||
else {
|
||||
face = PIPE_TEX_FACE_NEG_X;
|
||||
sc = rz;
|
||||
tc = -ry;
|
||||
ma = arx;
|
||||
}
|
||||
}
|
||||
else if (ary > arx && ary > arz) {
|
||||
if (ry >= 0.0F) {
|
||||
face = PIPE_TEX_FACE_POS_Y;
|
||||
sc = rx;
|
||||
tc = rz;
|
||||
ma = ary;
|
||||
}
|
||||
else {
|
||||
face = PIPE_TEX_FACE_NEG_Y;
|
||||
sc = rx;
|
||||
tc = -rz;
|
||||
ma = ary;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (rz > 0.0F) {
|
||||
face = PIPE_TEX_FACE_POS_Z;
|
||||
sc = rx;
|
||||
tc = -ry;
|
||||
ma = arz;
|
||||
}
|
||||
else {
|
||||
face = PIPE_TEX_FACE_NEG_Z;
|
||||
sc = -rx;
|
||||
tc = -ry;
|
||||
ma = arz;
|
||||
}
|
||||
}
|
||||
|
||||
*newS = (sc / ma + 1.0F) * 0.5F;
|
||||
*newT = (tc / ma + 1.0F) * 0.5F;
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
sample_texture_cube(vector float s, vector float t, vector float r,
|
||||
uint unit, vector float colors[4])
|
||||
{
|
||||
uint p, faces[4], level = 0;
|
||||
float newS[4], newT[4];
|
||||
|
||||
/* Compute cube faces referenced by the four sets of texcoords.
|
||||
* XXX we should SIMD-ize this.
|
||||
*/
|
||||
for (p = 0; p < 4; p++) {
|
||||
float rx = spu_extract(s, p);
|
||||
float ry = spu_extract(t, p);
|
||||
float rz = spu_extract(r, p);
|
||||
faces[p] = choose_cube_face(rx, ry, rz, &newS[p], &newT[p]);
|
||||
}
|
||||
|
||||
if (faces[0] == faces[1] &&
|
||||
faces[0] == faces[2] &&
|
||||
faces[0] == faces[3]) {
|
||||
/* GOOD! All four texcoords refer to the same cube face */
|
||||
s = (vector float) {newS[0], newS[1], newS[2], newS[3]};
|
||||
t = (vector float) {newT[0], newT[1], newT[2], newT[3]};
|
||||
spu.sample_texture_2d[unit](s, t, unit, level, faces[0], colors);
|
||||
}
|
||||
else {
|
||||
/* BAD! The four texcoords refer to different faces */
|
||||
for (p = 0; p < 4; p++) {
|
||||
vector float c[4];
|
||||
|
||||
spu.sample_texture_2d[unit](spu_splats(newS[p]), spu_splats(newT[p]),
|
||||
unit, level, faces[p], c);
|
||||
|
||||
float red = spu_extract(c[0], p);
|
||||
float green = spu_extract(c[1], p);
|
||||
float blue = spu_extract(c[2], p);
|
||||
float alpha = spu_extract(c[3], p);
|
||||
|
||||
colors[0] = spu_insert(red, colors[0], p);
|
||||
colors[1] = spu_insert(green, colors[1], p);
|
||||
colors[2] = spu_insert(blue, colors[2], p);
|
||||
colors[3] = spu_insert(alpha, colors[3], p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SPU_TEXTURE_H
|
||||
#define SPU_TEXTURE_H
|
||||
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
|
||||
extern void
|
||||
invalidate_tex_cache(void);
|
||||
|
||||
|
||||
extern void
|
||||
sample_texture_2d_nearest(vector float s, vector float t,
|
||||
uint unit, uint level, uint face,
|
||||
vector float colors[4]);
|
||||
|
||||
|
||||
extern void
|
||||
sample_texture_2d_bilinear(vector float s, vector float t,
|
||||
uint unit, uint level, uint face,
|
||||
vector float colors[4]);
|
||||
|
||||
extern void
|
||||
sample_texture_2d_bilinear_int(vector float s, vector float t,
|
||||
uint unit, uint level, uint face,
|
||||
vector float colors[4]);
|
||||
|
||||
|
||||
extern void
|
||||
sample_texture_2d_lod(vector float s, vector float t,
|
||||
uint unit, uint level, uint face,
|
||||
vector float colors[4]);
|
||||
|
||||
|
||||
extern void
|
||||
sample_texture_cube(vector float s, vector float t, vector float r,
|
||||
uint unit, vector float colors[4]);
|
||||
|
||||
|
||||
#endif /* SPU_TEXTURE_H */
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
* Copyright 2009-2010 VMware, Inc. All rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SPU_TGSI_EXEC_H
|
||||
#define SPU_TGSI_EXEC_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define NUM_CHANNELS 4 /* R,G,B,A */
|
||||
#define QUAD_SIZE 4 /* 4 pixel/quad */
|
||||
|
||||
|
||||
|
||||
#define TGSI_EXEC_NUM_TEMPS 128
|
||||
#define TGSI_EXEC_NUM_IMMEDIATES 256
|
||||
|
||||
/*
|
||||
* Locations of various utility registers (_I = Index, _C = Channel)
|
||||
*/
|
||||
#define TGSI_EXEC_TEMP_00000000_IDX (TGSI_EXEC_NUM_TEMPS + 0)
|
||||
#define TGSI_EXEC_TEMP_00000000_CHAN 0
|
||||
|
||||
#define TGSI_EXEC_TEMP_7FFFFFFF_IDX (TGSI_EXEC_NUM_TEMPS + 0)
|
||||
#define TGSI_EXEC_TEMP_7FFFFFFF_CHAN 1
|
||||
|
||||
#define TGSI_EXEC_TEMP_80000000_IDX (TGSI_EXEC_NUM_TEMPS + 0)
|
||||
#define TGSI_EXEC_TEMP_80000000_CHAN 2
|
||||
|
||||
#define TGSI_EXEC_TEMP_FFFFFFFF_IDX (TGSI_EXEC_NUM_TEMPS + 0)
|
||||
#define TGSI_EXEC_TEMP_FFFFFFFF_CHAN 3
|
||||
|
||||
#define TGSI_EXEC_TEMP_ONE_IDX (TGSI_EXEC_NUM_TEMPS + 1)
|
||||
#define TGSI_EXEC_TEMP_ONE_CHAN 0
|
||||
|
||||
#define TGSI_EXEC_TEMP_TWO_IDX (TGSI_EXEC_NUM_TEMPS + 1)
|
||||
#define TGSI_EXEC_TEMP_TWO_CHAN 1
|
||||
|
||||
#define TGSI_EXEC_TEMP_128_IDX (TGSI_EXEC_NUM_TEMPS + 1)
|
||||
#define TGSI_EXEC_TEMP_128_CHAN 2
|
||||
|
||||
#define TGSI_EXEC_TEMP_MINUS_128_IDX (TGSI_EXEC_NUM_TEMPS + 1)
|
||||
#define TGSI_EXEC_TEMP_MINUS_128_CHAN 3
|
||||
|
||||
#define TGSI_EXEC_TEMP_KILMASK_IDX (TGSI_EXEC_NUM_TEMPS + 2)
|
||||
#define TGSI_EXEC_TEMP_KILMASK_CHAN 0
|
||||
|
||||
#define TGSI_EXEC_TEMP_OUTPUT_IDX (TGSI_EXEC_NUM_TEMPS + 2)
|
||||
#define TGSI_EXEC_TEMP_OUTPUT_CHAN 1
|
||||
|
||||
#define TGSI_EXEC_TEMP_PRIMITIVE_IDX (TGSI_EXEC_NUM_TEMPS + 2)
|
||||
#define TGSI_EXEC_TEMP_PRIMITIVE_CHAN 2
|
||||
|
||||
/* NVIDIA condition code (CC) vector
|
||||
*/
|
||||
#define TGSI_EXEC_CC_GT 0x01
|
||||
#define TGSI_EXEC_CC_EQ 0x02
|
||||
#define TGSI_EXEC_CC_LT 0x04
|
||||
#define TGSI_EXEC_CC_UN 0x08
|
||||
|
||||
#define TGSI_EXEC_CC_X_MASK 0x000000ff
|
||||
#define TGSI_EXEC_CC_X_SHIFT 0
|
||||
#define TGSI_EXEC_CC_Y_MASK 0x0000ff00
|
||||
#define TGSI_EXEC_CC_Y_SHIFT 8
|
||||
#define TGSI_EXEC_CC_Z_MASK 0x00ff0000
|
||||
#define TGSI_EXEC_CC_Z_SHIFT 16
|
||||
#define TGSI_EXEC_CC_W_MASK 0xff000000
|
||||
#define TGSI_EXEC_CC_W_SHIFT 24
|
||||
|
||||
#define TGSI_EXEC_TEMP_CC_IDX (TGSI_EXEC_NUM_TEMPS + 2)
|
||||
#define TGSI_EXEC_TEMP_CC_CHAN 3
|
||||
|
||||
#define TGSI_EXEC_TEMP_THREE_IDX (TGSI_EXEC_NUM_TEMPS + 3)
|
||||
#define TGSI_EXEC_TEMP_THREE_CHAN 0
|
||||
|
||||
#define TGSI_EXEC_TEMP_HALF_IDX (TGSI_EXEC_NUM_TEMPS + 3)
|
||||
#define TGSI_EXEC_TEMP_HALF_CHAN 1
|
||||
|
||||
/* execution mask, each value is either 0 or ~0 */
|
||||
#define TGSI_EXEC_MASK_IDX (TGSI_EXEC_NUM_TEMPS + 3)
|
||||
#define TGSI_EXEC_MASK_CHAN 2
|
||||
|
||||
/* 4 register buffer for various purposes */
|
||||
#define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4)
|
||||
#define TGSI_EXEC_NUM_TEMP_R 4
|
||||
|
||||
#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 8)
|
||||
#define TGSI_EXEC_NUM_ADDRS 1
|
||||
|
||||
/* predicate register */
|
||||
#define TGSI_EXEC_TEMP_P0 (TGSI_EXEC_NUM_TEMPS + 9)
|
||||
#define TGSI_EXEC_NUM_PREDS 1
|
||||
|
||||
#define TGSI_EXEC_NUM_TEMP_EXTRAS 10
|
||||
|
||||
|
||||
|
||||
#define TGSI_EXEC_MAX_NESTING 32
|
||||
#define TGSI_EXEC_MAX_COND_NESTING TGSI_EXEC_MAX_NESTING
|
||||
#define TGSI_EXEC_MAX_LOOP_NESTING TGSI_EXEC_MAX_NESTING
|
||||
#define TGSI_EXEC_MAX_SWITCH_NESTING TGSI_EXEC_MAX_NESTING
|
||||
#define TGSI_EXEC_MAX_CALL_NESTING TGSI_EXEC_MAX_NESTING
|
||||
|
||||
/* The maximum number of input attributes per vertex. For 2D
|
||||
* input register files, this is the stride between two 1D
|
||||
* arrays.
|
||||
*/
|
||||
#define TGSI_EXEC_MAX_INPUT_ATTRIBS 17
|
||||
|
||||
/* The maximum number of constant vectors per constant buffer.
|
||||
*/
|
||||
#define TGSI_EXEC_MAX_CONST_BUFFER 4096
|
||||
|
||||
/* The maximum number of vertices per primitive */
|
||||
#define TGSI_MAX_PRIM_VERTICES 6
|
||||
|
||||
/* The maximum number of primitives to be generated */
|
||||
#define TGSI_MAX_PRIMITIVES 64
|
||||
|
||||
/* The maximum total number of vertices */
|
||||
#define TGSI_MAX_TOTAL_VERTICES (TGSI_MAX_PRIM_VERTICES * TGSI_MAX_PRIMITIVES * PIPE_MAX_ATTRIBS)
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* TGSI_EXEC_H */
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "spu_tile.h"
|
||||
#include "spu_main.h"
|
||||
|
||||
|
||||
/**
|
||||
* Get tile of color or Z values from main memory, put into SPU memory.
|
||||
*/
|
||||
void
|
||||
get_tile(uint tx, uint ty, tile_t *tile, int tag, int zBuf)
|
||||
{
|
||||
const uint offset = ty * spu.fb.width_tiles + tx;
|
||||
const uint bytesPerTile = TILE_SIZE * TILE_SIZE * (zBuf ? spu.fb.zsize : 4);
|
||||
const ubyte *src = zBuf ? spu.fb.depth_start : spu.fb.color_start;
|
||||
|
||||
src += offset * bytesPerTile;
|
||||
|
||||
ASSERT(tx < spu.fb.width_tiles);
|
||||
ASSERT(ty < spu.fb.height_tiles);
|
||||
ASSERT_ALIGN16(tile);
|
||||
/*
|
||||
printf("get_tile: dest: %p src: 0x%x size: %d\n",
|
||||
tile, (unsigned int) src, bytesPerTile);
|
||||
*/
|
||||
mfc_get(tile->ui, /* dest in local memory */
|
||||
(unsigned int) src, /* src in main memory */
|
||||
bytesPerTile,
|
||||
tag,
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move tile of color or Z values from SPU memory to main memory.
|
||||
*/
|
||||
void
|
||||
put_tile(uint tx, uint ty, const tile_t *tile, int tag, int zBuf)
|
||||
{
|
||||
const uint offset = ty * spu.fb.width_tiles + tx;
|
||||
const uint bytesPerTile = TILE_SIZE * TILE_SIZE * (zBuf ? spu.fb.zsize : 4);
|
||||
ubyte *dst = zBuf ? spu.fb.depth_start : spu.fb.color_start;
|
||||
|
||||
dst += offset * bytesPerTile;
|
||||
|
||||
ASSERT(tx < spu.fb.width_tiles);
|
||||
ASSERT(ty < spu.fb.height_tiles);
|
||||
ASSERT_ALIGN16(tile);
|
||||
/*
|
||||
printf("SPU %u: put_tile: src: %p dst: 0x%x size: %d\n",
|
||||
spu.init.id,
|
||||
tile, (unsigned int) dst, bytesPerTile);
|
||||
*/
|
||||
mfc_put((void *) tile->ui, /* src in local memory */
|
||||
(unsigned int) dst, /* dst in main memory */
|
||||
bytesPerTile,
|
||||
tag,
|
||||
0, /* tid */
|
||||
0 /* rid */);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For tiles whose status is TILE_STATUS_CLEAR, write solid-filled
|
||||
* tiles back to the main framebuffer.
|
||||
*/
|
||||
void
|
||||
really_clear_tiles(uint surfaceIndex)
|
||||
{
|
||||
const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
|
||||
uint i;
|
||||
|
||||
if (surfaceIndex == 0) {
|
||||
clear_c_tile(&spu.ctile);
|
||||
|
||||
for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
|
||||
uint tx = i % spu.fb.width_tiles;
|
||||
uint ty = i / spu.fb.width_tiles;
|
||||
if (spu.ctile_status[ty][tx] == TILE_STATUS_CLEAR) {
|
||||
put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
clear_z_tile(&spu.ztile);
|
||||
|
||||
for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
|
||||
uint tx = i % spu.fb.width_tiles;
|
||||
uint ty = i / spu.fb.width_tiles;
|
||||
if (spu.ztile_status[ty][tx] == TILE_STATUS_CLEAR)
|
||||
put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
wait_on_mask(1 << TAG_SURFACE_CLEAR);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SPU_TILE_H
|
||||
#define SPU_TILE_H
|
||||
|
||||
|
||||
#include <libmisc.h>
|
||||
#include <spu_mfcio.h>
|
||||
#include "spu_main.h"
|
||||
#include "cell/common.h"
|
||||
|
||||
|
||||
|
||||
extern void
|
||||
get_tile(uint tx, uint ty, tile_t *tile, int tag, int zBuf);
|
||||
|
||||
extern void
|
||||
put_tile(uint tx, uint ty, const tile_t *tile, int tag, int zBuf);
|
||||
|
||||
extern void
|
||||
really_clear_tiles(uint surfaceIndex);
|
||||
|
||||
|
||||
static INLINE void
|
||||
clear_c_tile(tile_t *ctile)
|
||||
{
|
||||
memset32((uint*) ctile->ui,
|
||||
spu.fb.color_clear_value,
|
||||
TILE_SIZE * TILE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
clear_z_tile(tile_t *ztile)
|
||||
{
|
||||
if (spu.fb.zsize == 2) {
|
||||
memset16((ushort*) ztile->us,
|
||||
spu.fb.depth_clear_value,
|
||||
TILE_SIZE * TILE_SIZE);
|
||||
}
|
||||
else {
|
||||
ASSERT(spu.fb.zsize != 0);
|
||||
memset32((uint*) ztile->ui,
|
||||
spu.fb.depth_clear_value,
|
||||
TILE_SIZE * TILE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* SPU_TILE_H */
|
||||
|
|
@ -1,843 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Triangle rendering within a tile.
|
||||
*/
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_format.h"
|
||||
#include "util/u_math.h"
|
||||
#include "spu_colorpack.h"
|
||||
#include "spu_main.h"
|
||||
#include "spu_shuffle.h"
|
||||
#include "spu_texture.h"
|
||||
#include "spu_tile.h"
|
||||
#include "spu_tri.h"
|
||||
|
||||
|
||||
/** Masks are uint[4] vectors with each element being 0 or 0xffffffff */
|
||||
typedef vector unsigned int mask_t;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simplified types taken from other parts of Gallium
|
||||
*/
|
||||
struct vertex_header {
|
||||
vector float data[1];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* XXX fix this */
|
||||
#undef CEILF
|
||||
#define CEILF(X) ((float) (int) ((X) + 0.99999f))
|
||||
|
||||
|
||||
#define QUAD_TOP_LEFT 0
|
||||
#define QUAD_TOP_RIGHT 1
|
||||
#define QUAD_BOTTOM_LEFT 2
|
||||
#define QUAD_BOTTOM_RIGHT 3
|
||||
#define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
|
||||
#define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
|
||||
#define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
|
||||
#define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
|
||||
#define MASK_ALL 0xf
|
||||
|
||||
|
||||
#define CHAN0 0
|
||||
#define CHAN1 1
|
||||
#define CHAN2 2
|
||||
#define CHAN3 3
|
||||
|
||||
|
||||
#define DEBUG_VERTS 0
|
||||
|
||||
/**
|
||||
* Triangle edge info
|
||||
*/
|
||||
struct edge {
|
||||
union {
|
||||
struct {
|
||||
float dx; /**< X(v1) - X(v0), used only during setup */
|
||||
float dy; /**< Y(v1) - Y(v0), used only during setup */
|
||||
};
|
||||
vec_float4 ds; /**< vector accessor for dx and dy */
|
||||
};
|
||||
float dxdy; /**< dx/dy */
|
||||
float sx, sy; /**< first sample point coord */
|
||||
int lines; /**< number of lines on this edge */
|
||||
};
|
||||
|
||||
|
||||
struct interp_coef
|
||||
{
|
||||
vector float a0;
|
||||
vector float dadx;
|
||||
vector float dady;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triangle setup info (derived from draw_stage).
|
||||
* Also used for line drawing (taking some liberties).
|
||||
*/
|
||||
struct setup_stage {
|
||||
|
||||
/* Vertices are just an array of floats making up each attribute in
|
||||
* turn. Currently fixed at 4 floats, but should change in time.
|
||||
* Codegen will help cope with this.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
const struct vertex_header *vmin;
|
||||
const struct vertex_header *vmid;
|
||||
const struct vertex_header *vmax;
|
||||
const struct vertex_header *vprovoke;
|
||||
};
|
||||
qword vertex_headers;
|
||||
};
|
||||
|
||||
struct edge ebot;
|
||||
struct edge etop;
|
||||
struct edge emaj;
|
||||
|
||||
float oneOverArea; /* XXX maybe make into vector? */
|
||||
|
||||
uint facing;
|
||||
|
||||
uint tx, ty; /**< position of current tile (x, y) */
|
||||
|
||||
union {
|
||||
struct {
|
||||
int cliprect_minx;
|
||||
int cliprect_miny;
|
||||
int cliprect_maxx;
|
||||
int cliprect_maxy;
|
||||
};
|
||||
qword cliprect;
|
||||
};
|
||||
|
||||
struct interp_coef coef[PIPE_MAX_SHADER_INPUTS];
|
||||
|
||||
struct {
|
||||
vec_int4 quad; /**< [0] = row0, [1] = row1; {left[0],left[1],right[0],right[1]} */
|
||||
int y;
|
||||
unsigned y_flags;
|
||||
unsigned mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
|
||||
} span;
|
||||
};
|
||||
|
||||
|
||||
static struct setup_stage setup;
|
||||
|
||||
|
||||
static INLINE vector float
|
||||
splatx(vector float v)
|
||||
{
|
||||
return spu_splats(spu_extract(v, CHAN0));
|
||||
}
|
||||
|
||||
static INLINE vector float
|
||||
splaty(vector float v)
|
||||
{
|
||||
return spu_splats(spu_extract(v, CHAN1));
|
||||
}
|
||||
|
||||
static INLINE vector float
|
||||
splatz(vector float v)
|
||||
{
|
||||
return spu_splats(spu_extract(v, CHAN2));
|
||||
}
|
||||
|
||||
static INLINE vector float
|
||||
splatw(vector float v)
|
||||
{
|
||||
return spu_splats(spu_extract(v, CHAN3));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup fragment shader inputs by evaluating triangle's vertex
|
||||
* attribute coefficient info.
|
||||
* \param x quad x pos
|
||||
* \param y quad y pos
|
||||
* \param fragZ returns quad Z values
|
||||
* \param fragInputs returns fragment program inputs
|
||||
* Note: this code could be incorporated into the fragment program
|
||||
* itself to avoid the loop and switch.
|
||||
*/
|
||||
static void
|
||||
eval_inputs(float x, float y, vector float *fragZ, vector float fragInputs[])
|
||||
{
|
||||
static const vector float deltaX = (const vector float) {0, 1, 0, 1};
|
||||
static const vector float deltaY = (const vector float) {0, 0, 1, 1};
|
||||
|
||||
const uint posSlot = 0;
|
||||
const vector float pos = setup.coef[posSlot].a0;
|
||||
const vector float dposdx = setup.coef[posSlot].dadx;
|
||||
const vector float dposdy = setup.coef[posSlot].dady;
|
||||
const vector float fragX = spu_splats(x) + deltaX;
|
||||
const vector float fragY = spu_splats(y) + deltaY;
|
||||
vector float fragW, wInv;
|
||||
uint i;
|
||||
|
||||
*fragZ = splatz(pos) + fragX * splatz(dposdx) + fragY * splatz(dposdy);
|
||||
fragW = splatw(pos) + fragX * splatw(dposdx) + fragY * splatw(dposdy);
|
||||
wInv = spu_re(fragW); /* 1 / w */
|
||||
|
||||
/* loop over fragment program inputs */
|
||||
for (i = 0; i < spu.vertex_info.num_attribs; i++) {
|
||||
uint attr = i + 1;
|
||||
enum interp_mode interp = spu.vertex_info.attrib[attr].interp_mode;
|
||||
|
||||
/* constant term */
|
||||
vector float a0 = setup.coef[attr].a0;
|
||||
vector float r0 = splatx(a0);
|
||||
vector float r1 = splaty(a0);
|
||||
vector float r2 = splatz(a0);
|
||||
vector float r3 = splatw(a0);
|
||||
|
||||
if (interp == INTERP_LINEAR || interp == INTERP_PERSPECTIVE) {
|
||||
/* linear term */
|
||||
vector float dadx = setup.coef[attr].dadx;
|
||||
vector float dady = setup.coef[attr].dady;
|
||||
/* Use SPU intrinsics here to get slightly better code.
|
||||
* originally: r0 += fragX * splatx(dadx) + fragY * splatx(dady);
|
||||
*/
|
||||
r0 = spu_madd(fragX, splatx(dadx), spu_madd(fragY, splatx(dady), r0));
|
||||
r1 = spu_madd(fragX, splaty(dadx), spu_madd(fragY, splaty(dady), r1));
|
||||
r2 = spu_madd(fragX, splatz(dadx), spu_madd(fragY, splatz(dady), r2));
|
||||
r3 = spu_madd(fragX, splatw(dadx), spu_madd(fragY, splatw(dady), r3));
|
||||
if (interp == INTERP_PERSPECTIVE) {
|
||||
/* perspective term */
|
||||
r0 *= wInv;
|
||||
r1 *= wInv;
|
||||
r2 *= wInv;
|
||||
r3 *= wInv;
|
||||
}
|
||||
}
|
||||
fragInputs[CHAN0] = r0;
|
||||
fragInputs[CHAN1] = r1;
|
||||
fragInputs[CHAN2] = r2;
|
||||
fragInputs[CHAN3] = r3;
|
||||
fragInputs += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emit a quad (pass to next stage). No clipping is done.
|
||||
* Note: about 1/5 to 1/7 of the time, mask is zero and this function
|
||||
* should be skipped. But adding the test for that slows things down
|
||||
* overall.
|
||||
*/
|
||||
static INLINE void
|
||||
emit_quad( int x, int y, mask_t mask)
|
||||
{
|
||||
/* If any bits in mask are set... */
|
||||
if (spu_extract(spu_orx(mask), 0)) {
|
||||
const int ix = x - setup.cliprect_minx;
|
||||
const int iy = y - setup.cliprect_miny;
|
||||
|
||||
spu.cur_ctile_status = TILE_STATUS_DIRTY;
|
||||
spu.cur_ztile_status = TILE_STATUS_DIRTY;
|
||||
|
||||
{
|
||||
/*
|
||||
* Run fragment shader, execute per-fragment ops, update fb/tile.
|
||||
*/
|
||||
vector float inputs[4*4], outputs[2*4];
|
||||
vector unsigned int kill_mask;
|
||||
vector float fragZ;
|
||||
|
||||
eval_inputs((float) x, (float) y, &fragZ, inputs);
|
||||
|
||||
ASSERT(spu.fragment_program);
|
||||
ASSERT(spu.fragment_ops);
|
||||
|
||||
/* Execute the current fragment program */
|
||||
kill_mask = spu.fragment_program(inputs, outputs, spu.constants);
|
||||
|
||||
mask = spu_andc(mask, kill_mask);
|
||||
|
||||
/* Execute per-fragment/quad operations, including:
|
||||
* alpha test, z test, stencil test, blend and framebuffer writing.
|
||||
* Note that there are two different fragment operations functions
|
||||
* that can be called, one for front-facing fragments, and one
|
||||
* for back-facing fragments. (Often the two are the same;
|
||||
* but in some cases, like two-sided stenciling, they can be
|
||||
* very different.) So choose the correct function depending
|
||||
* on the calculated facing.
|
||||
*/
|
||||
spu.fragment_ops[setup.facing](ix, iy, &spu.ctile, &spu.ztile,
|
||||
fragZ,
|
||||
outputs[0*4+0],
|
||||
outputs[0*4+1],
|
||||
outputs[0*4+2],
|
||||
outputs[0*4+3],
|
||||
mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given an X or Y coordinate, return the block/quad coordinate that it
|
||||
* belongs to.
|
||||
*/
|
||||
static INLINE int
|
||||
block(int x)
|
||||
{
|
||||
return x & ~1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render a horizontal span of quads
|
||||
*/
|
||||
static void
|
||||
flush_spans(void)
|
||||
{
|
||||
int minleft, maxright;
|
||||
|
||||
const int l0 = spu_extract(setup.span.quad, 0);
|
||||
const int l1 = spu_extract(setup.span.quad, 1);
|
||||
const int r0 = spu_extract(setup.span.quad, 2);
|
||||
const int r1 = spu_extract(setup.span.quad, 3);
|
||||
|
||||
switch (setup.span.y_flags) {
|
||||
case 0x3:
|
||||
/* both odd and even lines written (both quad rows) */
|
||||
minleft = MIN2(l0, l1);
|
||||
maxright = MAX2(r0, r1);
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
/* only even line written (quad top row) */
|
||||
minleft = l0;
|
||||
maxright = r0;
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
/* only odd line written (quad bottom row) */
|
||||
minleft = l1;
|
||||
maxright = r1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* OK, we're very likely to need the tile data now.
|
||||
* clear or finish waiting if needed.
|
||||
*/
|
||||
if (spu.cur_ctile_status == TILE_STATUS_GETTING) {
|
||||
/* wait for mfc_get() to complete */
|
||||
//printf("SPU: %u: waiting for ctile\n", spu.init.id);
|
||||
wait_on_mask(1 << TAG_READ_TILE_COLOR);
|
||||
spu.cur_ctile_status = TILE_STATUS_CLEAN;
|
||||
}
|
||||
else if (spu.cur_ctile_status == TILE_STATUS_CLEAR) {
|
||||
//printf("SPU %u: clearing C tile %u, %u\n", spu.init.id, setup.tx, setup.ty);
|
||||
clear_c_tile(&spu.ctile);
|
||||
spu.cur_ctile_status = TILE_STATUS_DIRTY;
|
||||
}
|
||||
ASSERT(spu.cur_ctile_status != TILE_STATUS_DEFINED);
|
||||
|
||||
if (spu.read_depth_stencil) {
|
||||
if (spu.cur_ztile_status == TILE_STATUS_GETTING) {
|
||||
/* wait for mfc_get() to complete */
|
||||
//printf("SPU: %u: waiting for ztile\n", spu.init.id);
|
||||
wait_on_mask(1 << TAG_READ_TILE_Z);
|
||||
spu.cur_ztile_status = TILE_STATUS_CLEAN;
|
||||
}
|
||||
else if (spu.cur_ztile_status == TILE_STATUS_CLEAR) {
|
||||
//printf("SPU %u: clearing Z tile %u, %u\n", spu.init.id, setup.tx, setup.ty);
|
||||
clear_z_tile(&spu.ztile);
|
||||
spu.cur_ztile_status = TILE_STATUS_DIRTY;
|
||||
}
|
||||
ASSERT(spu.cur_ztile_status != TILE_STATUS_DEFINED);
|
||||
}
|
||||
|
||||
/* XXX this loop could be moved into the above switch cases... */
|
||||
|
||||
/* Setup for mask calculation */
|
||||
const vec_int4 quad_LlRr = setup.span.quad;
|
||||
const vec_int4 quad_RrLl = spu_rlqwbyte(quad_LlRr, 8);
|
||||
const vec_int4 quad_LLll = spu_shuffle(quad_LlRr, quad_LlRr, SHUFFLE4(A,A,B,B));
|
||||
const vec_int4 quad_RRrr = spu_shuffle(quad_RrLl, quad_RrLl, SHUFFLE4(A,A,B,B));
|
||||
|
||||
const vec_int4 twos = spu_splats(2);
|
||||
|
||||
const int x = block(minleft);
|
||||
vec_int4 xs = {x, x+1, x, x+1};
|
||||
|
||||
for (; spu_extract(xs, 0) <= block(maxright); xs += twos) {
|
||||
/**
|
||||
* Computes mask to indicate which pixels in the 2x2 quad are actually
|
||||
* inside the triangle's bounds.
|
||||
*/
|
||||
|
||||
/* Calculate ({x,x+1,x,x+1} >= {l[0],l[0],l[1],l[1]}) */
|
||||
const mask_t gt_LLll_xs = spu_cmpgt(quad_LLll, xs);
|
||||
const mask_t gte_xs_LLll = spu_nand(gt_LLll_xs, gt_LLll_xs);
|
||||
|
||||
/* Calculate ({r[0],r[0],r[1],r[1]} > {x,x+1,x,x+1}) */
|
||||
const mask_t gt_RRrr_xs = spu_cmpgt(quad_RRrr, xs);
|
||||
|
||||
/* Combine results to create mask */
|
||||
const mask_t mask = spu_and(gte_xs_LLll, gt_RRrr_xs);
|
||||
|
||||
emit_quad(spu_extract(xs, 0), setup.span.y, mask);
|
||||
}
|
||||
|
||||
setup.span.y = 0;
|
||||
setup.span.y_flags = 0;
|
||||
/* Zero right elements */
|
||||
setup.span.quad = spu_shuffle(setup.span.quad, setup.span.quad, SHUFFLE4(A,B,0,0));
|
||||
}
|
||||
|
||||
|
||||
#if DEBUG_VERTS
|
||||
static void
|
||||
print_vertex(const struct vertex_header *v)
|
||||
{
|
||||
uint i;
|
||||
fprintf(stderr, " Vertex: (%p)\n", v);
|
||||
for (i = 0; i < spu.vertex_info.num_attribs; i++) {
|
||||
fprintf(stderr, " %d: %f %f %f %f\n", i,
|
||||
spu_extract(v->data[i], 0),
|
||||
spu_extract(v->data[i], 1),
|
||||
spu_extract(v->data[i], 2),
|
||||
spu_extract(v->data[i], 3));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns the minimum of each slot of two vec_float4s as qwords.
|
||||
* i.e. return[n] = min(q0[n],q1[n]);
|
||||
*/
|
||||
static qword
|
||||
minfq(qword q0, qword q1)
|
||||
{
|
||||
const qword q0q1m = si_fcgt(q0, q1);
|
||||
return si_selb(q0, q1, q0q1m);
|
||||
}
|
||||
|
||||
/* Returns the minimum of each slot of three vec_float4s as qwords.
|
||||
* i.e. return[n] = min(q0[n],q1[n],q2[n]);
|
||||
*/
|
||||
static qword
|
||||
min3fq(qword q0, qword q1, qword q2)
|
||||
{
|
||||
return minfq(minfq(q0, q1), q2);
|
||||
}
|
||||
|
||||
/* Returns the maximum of each slot of two vec_float4s as qwords.
|
||||
* i.e. return[n] = min(q0[n],q1[n],q2[n]);
|
||||
*/
|
||||
static qword
|
||||
maxfq(qword q0, qword q1) {
|
||||
const qword q0q1m = si_fcgt(q0, q1);
|
||||
return si_selb(q1, q0, q0q1m);
|
||||
}
|
||||
|
||||
/* Returns the maximum of each slot of three vec_float4s as qwords.
|
||||
* i.e. return[n] = min(q0[n],q1[n],q2[n]);
|
||||
*/
|
||||
static qword
|
||||
max3fq(qword q0, qword q1, qword q2) {
|
||||
return maxfq(maxfq(q0, q1), q2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort vertices from top to bottom.
|
||||
* Compute area and determine front vs. back facing.
|
||||
* Do coarse clip test against tile bounds
|
||||
* \return FALSE if tri is totally outside tile, TRUE otherwise
|
||||
*/
|
||||
static boolean
|
||||
setup_sort_vertices(const qword vs)
|
||||
{
|
||||
float area, sign;
|
||||
|
||||
#if DEBUG_VERTS
|
||||
if (spu.init.id==0) {
|
||||
fprintf(stderr, "SPU %u: Triangle:\n", spu.init.id);
|
||||
print_vertex(v0);
|
||||
print_vertex(v1);
|
||||
print_vertex(v2);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
/* Load the float values for various processing... */
|
||||
const qword f0 = (qword)(((const struct vertex_header*)si_to_ptr(vs))->data[0]);
|
||||
const qword f1 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 4)))->data[0]);
|
||||
const qword f2 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 8)))->data[0]);
|
||||
|
||||
/* Check if triangle is completely outside the tile bounds
|
||||
* Find the min and max x and y positions of the three poits */
|
||||
const qword minf = min3fq(f0, f1, f2);
|
||||
const qword maxf = max3fq(f0, f1, f2);
|
||||
|
||||
/* Compare min and max against cliprect vals */
|
||||
const qword maxsmins = si_shufb(maxf, minf, SHUFB4(A,B,a,b));
|
||||
const qword outside = si_fcgt(maxsmins, si_csflt(setup.cliprect, 0));
|
||||
|
||||
/* Use a little magic to work out of the tri is visible or not */
|
||||
if(si_to_uint(si_xori(si_gb(outside), 0xc))) return FALSE;
|
||||
|
||||
/* determine bottom to top order of vertices */
|
||||
/* A table of shuffle patterns for putting vertex_header pointers into
|
||||
correct order. Quite magical. */
|
||||
const qword sort_order_patterns[] = {
|
||||
SHUFB4(A,B,C,C),
|
||||
SHUFB4(C,A,B,C),
|
||||
SHUFB4(A,C,B,C),
|
||||
SHUFB4(B,C,A,C),
|
||||
SHUFB4(B,A,C,C),
|
||||
SHUFB4(C,B,A,C) };
|
||||
|
||||
/* Collate y values into two vectors for comparison.
|
||||
Using only one shuffle constant! ;) */
|
||||
const qword y_02_ = si_shufb(f0, f2, SHUFB4(0,B,b,C));
|
||||
const qword y_10_ = si_shufb(f1, f0, SHUFB4(0,B,b,C));
|
||||
const qword y_012 = si_shufb(y_02_, f1, SHUFB4(0,B,b,C));
|
||||
const qword y_120 = si_shufb(y_10_, f2, SHUFB4(0,B,b,C));
|
||||
|
||||
/* Perform comparison: {y0,y1,y2} > {y1,y2,y0} */
|
||||
const qword compare = si_fcgt(y_012, y_120);
|
||||
/* Compress the result of the comparison into 4 bits */
|
||||
const qword gather = si_gb(compare);
|
||||
/* Subtract one to attain the index into the LUT. Magical. */
|
||||
const unsigned int index = si_to_uint(gather) - 1;
|
||||
|
||||
/* Load the appropriate pattern and construct the desired vector. */
|
||||
setup.vertex_headers = si_shufb(vs, vs, sort_order_patterns[index]);
|
||||
|
||||
/* Using the result of the comparison, set sign.
|
||||
Very magical. */
|
||||
sign = ((si_to_uint(si_cntb(gather)) == 2) ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
setup.ebot.ds = spu_sub(setup.vmid->data[0], setup.vmin->data[0]);
|
||||
setup.emaj.ds = spu_sub(setup.vmax->data[0], setup.vmin->data[0]);
|
||||
setup.etop.ds = spu_sub(setup.vmax->data[0], setup.vmid->data[0]);
|
||||
|
||||
/*
|
||||
* Compute triangle's area. Use 1/area to compute partial
|
||||
* derivatives of attributes later.
|
||||
*/
|
||||
area = setup.emaj.dx * setup.ebot.dy - setup.ebot.dx * setup.emaj.dy;
|
||||
|
||||
setup.oneOverArea = 1.0f / area;
|
||||
|
||||
/* The product of area * sign indicates front/back orientation (0/1).
|
||||
* Just in case someone gets the bright idea of switching the front
|
||||
* and back constants without noticing that we're assuming their
|
||||
* values in this operation, also assert that the values are
|
||||
* what we think they are.
|
||||
*/
|
||||
ASSERT(CELL_FACING_FRONT == 0);
|
||||
ASSERT(CELL_FACING_BACK == 1);
|
||||
setup.facing = (area * sign > 0.0f)
|
||||
^ (!spu.rasterizer.front_ccw);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
|
||||
* The value value comes from vertex->data[slot].
|
||||
* The result will be put into setup.coef[slot].a0.
|
||||
* \param slot which attribute slot
|
||||
*/
|
||||
static INLINE void
|
||||
const_coeff4(uint slot)
|
||||
{
|
||||
setup.coef[slot].dadx = (vector float) {0.0, 0.0, 0.0, 0.0};
|
||||
setup.coef[slot].dady = (vector float) {0.0, 0.0, 0.0, 0.0};
|
||||
setup.coef[slot].a0 = setup.vprovoke->data[slot];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As above, but interp setup all four vector components.
|
||||
*/
|
||||
static INLINE void
|
||||
tri_linear_coeff4(uint slot)
|
||||
{
|
||||
const vector float vmin_d = setup.vmin->data[slot];
|
||||
const vector float vmid_d = setup.vmid->data[slot];
|
||||
const vector float vmax_d = setup.vmax->data[slot];
|
||||
const vector float xxxx = spu_splats(spu_extract(setup.vmin->data[0], 0) - 0.5f);
|
||||
const vector float yyyy = spu_splats(spu_extract(setup.vmin->data[0], 1) - 0.5f);
|
||||
|
||||
vector float botda = vmid_d - vmin_d;
|
||||
vector float majda = vmax_d - vmin_d;
|
||||
|
||||
vector float a = spu_sub(spu_mul(spu_splats(setup.ebot.dy), majda),
|
||||
spu_mul(botda, spu_splats(setup.emaj.dy)));
|
||||
vector float b = spu_sub(spu_mul(spu_splats(setup.emaj.dx), botda),
|
||||
spu_mul(majda, spu_splats(setup.ebot.dx)));
|
||||
|
||||
setup.coef[slot].dadx = spu_mul(a, spu_splats(setup.oneOverArea));
|
||||
setup.coef[slot].dady = spu_mul(b, spu_splats(setup.oneOverArea));
|
||||
|
||||
vector float tempx = spu_mul(setup.coef[slot].dadx, xxxx);
|
||||
vector float tempy = spu_mul(setup.coef[slot].dady, yyyy);
|
||||
|
||||
setup.coef[slot].a0 = spu_sub(vmin_d, spu_add(tempx, tempy));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute a0, dadx and dady for a perspective-corrected interpolant,
|
||||
* for a triangle.
|
||||
* We basically multiply the vertex value by 1/w before computing
|
||||
* the plane coefficients (a0, dadx, dady).
|
||||
* Later, when we compute the value at a particular fragment position we'll
|
||||
* divide the interpolated value by the interpolated W at that fragment.
|
||||
*/
|
||||
static void
|
||||
tri_persp_coeff4(uint slot)
|
||||
{
|
||||
const vector float xxxx = spu_splats(spu_extract(setup.vmin->data[0], 0) - 0.5f);
|
||||
const vector float yyyy = spu_splats(spu_extract(setup.vmin->data[0], 1) - 0.5f);
|
||||
|
||||
const vector float vmin_w = spu_splats(spu_extract(setup.vmin->data[0], 3));
|
||||
const vector float vmid_w = spu_splats(spu_extract(setup.vmid->data[0], 3));
|
||||
const vector float vmax_w = spu_splats(spu_extract(setup.vmax->data[0], 3));
|
||||
|
||||
vector float vmin_d = setup.vmin->data[slot];
|
||||
vector float vmid_d = setup.vmid->data[slot];
|
||||
vector float vmax_d = setup.vmax->data[slot];
|
||||
|
||||
vmin_d = spu_mul(vmin_d, vmin_w);
|
||||
vmid_d = spu_mul(vmid_d, vmid_w);
|
||||
vmax_d = spu_mul(vmax_d, vmax_w);
|
||||
|
||||
vector float botda = vmid_d - vmin_d;
|
||||
vector float majda = vmax_d - vmin_d;
|
||||
|
||||
vector float a = spu_sub(spu_mul(spu_splats(setup.ebot.dy), majda),
|
||||
spu_mul(botda, spu_splats(setup.emaj.dy)));
|
||||
vector float b = spu_sub(spu_mul(spu_splats(setup.emaj.dx), botda),
|
||||
spu_mul(majda, spu_splats(setup.ebot.dx)));
|
||||
|
||||
setup.coef[slot].dadx = spu_mul(a, spu_splats(setup.oneOverArea));
|
||||
setup.coef[slot].dady = spu_mul(b, spu_splats(setup.oneOverArea));
|
||||
|
||||
vector float tempx = spu_mul(setup.coef[slot].dadx, xxxx);
|
||||
vector float tempy = spu_mul(setup.coef[slot].dady, yyyy);
|
||||
|
||||
setup.coef[slot].a0 = spu_sub(vmin_d, spu_add(tempx, tempy));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compute the setup.coef[] array dadx, dady, a0 values.
|
||||
* Must be called after setup.vmin,vmid,vmax,vprovoke are initialized.
|
||||
*/
|
||||
static void
|
||||
setup_tri_coefficients(void)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < spu.vertex_info.num_attribs; i++) {
|
||||
switch (spu.vertex_info.attrib[i].interp_mode) {
|
||||
case INTERP_NONE:
|
||||
break;
|
||||
case INTERP_CONSTANT:
|
||||
const_coeff4(i);
|
||||
break;
|
||||
case INTERP_POS:
|
||||
/* fall-through */
|
||||
case INTERP_LINEAR:
|
||||
tri_linear_coeff4(i);
|
||||
break;
|
||||
case INTERP_PERSPECTIVE:
|
||||
tri_persp_coeff4(i);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setup_tri_edges(void)
|
||||
{
|
||||
float vmin_x = spu_extract(setup.vmin->data[0], 0) + 0.5f;
|
||||
float vmid_x = spu_extract(setup.vmid->data[0], 0) + 0.5f;
|
||||
|
||||
float vmin_y = spu_extract(setup.vmin->data[0], 1) - 0.5f;
|
||||
float vmid_y = spu_extract(setup.vmid->data[0], 1) - 0.5f;
|
||||
float vmax_y = spu_extract(setup.vmax->data[0], 1) - 0.5f;
|
||||
|
||||
setup.emaj.sy = CEILF(vmin_y);
|
||||
setup.emaj.lines = (int) CEILF(vmax_y - setup.emaj.sy);
|
||||
setup.emaj.dxdy = setup.emaj.dx / setup.emaj.dy;
|
||||
setup.emaj.sx = vmin_x + (setup.emaj.sy - vmin_y) * setup.emaj.dxdy;
|
||||
|
||||
setup.etop.sy = CEILF(vmid_y);
|
||||
setup.etop.lines = (int) CEILF(vmax_y - setup.etop.sy);
|
||||
setup.etop.dxdy = setup.etop.dx / setup.etop.dy;
|
||||
setup.etop.sx = vmid_x + (setup.etop.sy - vmid_y) * setup.etop.dxdy;
|
||||
|
||||
setup.ebot.sy = CEILF(vmin_y);
|
||||
setup.ebot.lines = (int) CEILF(vmid_y - setup.ebot.sy);
|
||||
setup.ebot.dxdy = setup.ebot.dx / setup.ebot.dy;
|
||||
setup.ebot.sx = vmin_x + (setup.ebot.sy - vmin_y) * setup.ebot.dxdy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render the upper or lower half of a triangle.
|
||||
* Scissoring/cliprect is applied here too.
|
||||
*/
|
||||
static void
|
||||
subtriangle(struct edge *eleft, struct edge *eright, unsigned lines)
|
||||
{
|
||||
const int minx = setup.cliprect_minx;
|
||||
const int maxx = setup.cliprect_maxx;
|
||||
const int miny = setup.cliprect_miny;
|
||||
const int maxy = setup.cliprect_maxy;
|
||||
int y, start_y, finish_y;
|
||||
int sy = (int)eleft->sy;
|
||||
|
||||
ASSERT((int)eleft->sy == (int) eright->sy);
|
||||
|
||||
/* clip top/bottom */
|
||||
start_y = sy;
|
||||
finish_y = sy + lines;
|
||||
|
||||
if (start_y < miny)
|
||||
start_y = miny;
|
||||
|
||||
if (finish_y > maxy)
|
||||
finish_y = maxy;
|
||||
|
||||
start_y -= sy;
|
||||
finish_y -= sy;
|
||||
|
||||
/*
|
||||
printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
|
||||
*/
|
||||
|
||||
for (y = start_y; y < finish_y; y++) {
|
||||
|
||||
/* avoid accumulating adds as floats don't have the precision to
|
||||
* accurately iterate large triangle edges that way. luckily we
|
||||
* can just multiply these days.
|
||||
*
|
||||
* this is all drowned out by the attribute interpolation anyway.
|
||||
*/
|
||||
int left = (int)(eleft->sx + y * eleft->dxdy);
|
||||
int right = (int)(eright->sx + y * eright->dxdy);
|
||||
|
||||
/* clip left/right */
|
||||
if (left < minx)
|
||||
left = minx;
|
||||
if (right > maxx)
|
||||
right = maxx;
|
||||
|
||||
if (left < right) {
|
||||
int _y = sy + y;
|
||||
if (block(_y) != setup.span.y) {
|
||||
flush_spans();
|
||||
setup.span.y = block(_y);
|
||||
}
|
||||
|
||||
int offset = _y&1;
|
||||
vec_int4 quad_LlRr = {left, left, right, right};
|
||||
/* Store left and right in 0 or 1 row of quad based on offset */
|
||||
setup.span.quad = spu_sel(quad_LlRr, setup.span.quad, spu_maskw(5<<offset));
|
||||
setup.span.y_flags |= 1<<offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* save the values so that emaj can be restarted:
|
||||
*/
|
||||
eleft->sx += lines * eleft->dxdy;
|
||||
eright->sx += lines * eright->dxdy;
|
||||
eleft->sy += lines;
|
||||
eright->sy += lines;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw triangle into tile at (tx, ty) (tile coords)
|
||||
* The tile data should have already been fetched.
|
||||
*/
|
||||
boolean
|
||||
tri_draw(const qword vs,
|
||||
uint tx, uint ty)
|
||||
{
|
||||
setup.tx = tx;
|
||||
setup.ty = ty;
|
||||
|
||||
/* set clipping bounds to tile bounds */
|
||||
const qword clipbase = (qword)((vec_uint4){tx, ty});
|
||||
const qword clipmin = si_mpyui(clipbase, TILE_SIZE);
|
||||
const qword clipmax = si_ai(clipmin, TILE_SIZE);
|
||||
setup.cliprect = si_shufb(clipmin, clipmax, SHUFB4(A,B,a,b));
|
||||
|
||||
if(!setup_sort_vertices(vs)) {
|
||||
return FALSE; /* totally clipped */
|
||||
}
|
||||
|
||||
setup_tri_coefficients();
|
||||
setup_tri_edges();
|
||||
|
||||
setup.span.y = 0;
|
||||
setup.span.y_flags = 0;
|
||||
/* Zero right elements */
|
||||
setup.span.quad = spu_shuffle(setup.span.quad, setup.span.quad, SHUFFLE4(A,B,0,0));
|
||||
|
||||
if (setup.oneOverArea < 0.0) {
|
||||
/* emaj on left */
|
||||
subtriangle( &setup.emaj, &setup.ebot, setup.ebot.lines );
|
||||
subtriangle( &setup.emaj, &setup.etop, setup.etop.lines );
|
||||
}
|
||||
else {
|
||||
/* emaj on right */
|
||||
subtriangle( &setup.ebot, &setup.emaj, setup.ebot.lines );
|
||||
subtriangle( &setup.etop, &setup.emaj, setup.etop.lines );
|
||||
}
|
||||
|
||||
flush_spans();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef SPU_TRI_H
|
||||
#define SPU_TRI_H
|
||||
|
||||
|
||||
extern boolean
|
||||
tri_draw(const qword vs, uint tx, uint ty);
|
||||
|
||||
|
||||
#endif /* SPU_TRI_H */
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
|
||||
#include "cell/common.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
//#include "tgsi_build.h"
|
||||
#include "tgsi/tgsi_util.h"
|
||||
|
||||
unsigned
|
||||
tgsi_util_get_src_register_swizzle(
|
||||
const struct tgsi_src_register *reg,
|
||||
unsigned component )
|
||||
{
|
||||
switch( component ) {
|
||||
case 0:
|
||||
return reg->SwizzleX;
|
||||
case 1:
|
||||
return reg->SwizzleY;
|
||||
case 2:
|
||||
return reg->SwizzleZ;
|
||||
case 3:
|
||||
return reg->SwizzleW;
|
||||
default:
|
||||
ASSERT( 0 );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
tgsi_util_get_full_src_register_swizzle(
|
||||
const struct tgsi_full_src_register *reg,
|
||||
unsigned component )
|
||||
{
|
||||
return tgsi_util_get_src_register_swizzle(
|
||||
reg->Register,
|
||||
component );
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
tgsi_util_get_full_src_register_sign_mode(
|
||||
const struct tgsi_full_src_register *reg,
|
||||
unsigned component )
|
||||
{
|
||||
unsigned sign_mode;
|
||||
|
||||
if( reg->RegisterExtMod.Absolute ) {
|
||||
/* Consider only the post-abs negation. */
|
||||
|
||||
if( reg->RegisterExtMod.Negate ) {
|
||||
sign_mode = TGSI_UTIL_SIGN_SET;
|
||||
}
|
||||
else {
|
||||
sign_mode = TGSI_UTIL_SIGN_CLEAR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Accumulate the three negations. */
|
||||
|
||||
unsigned negate;
|
||||
|
||||
negate = reg->Register.Negate;
|
||||
if( reg->RegisterExtMod.Negate ) {
|
||||
negate = !negate;
|
||||
}
|
||||
|
||||
if( negate ) {
|
||||
sign_mode = TGSI_UTIL_SIGN_TOGGLE;
|
||||
}
|
||||
else {
|
||||
sign_mode = TGSI_UTIL_SIGN_KEEP;
|
||||
}
|
||||
}
|
||||
|
||||
return sign_mode;
|
||||
}
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* (C) Copyright IBM Corporation 2008
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Ian Romanick <idr@us.ibm.com>
|
||||
*/
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "spu_exec.h"
|
||||
#include "spu_vertex_shader.h"
|
||||
#include "spu_main.h"
|
||||
#include "spu_dcache.h"
|
||||
|
||||
typedef void (*spu_fetch_func)(qword *out, const qword *in,
|
||||
const qword *shuffle_data);
|
||||
|
||||
|
||||
PIPE_ALIGN_VAR(16) static const qword
|
||||
fetch_shuffle_data[5] = {
|
||||
/* Shuffle used by CVT_64_FLOAT
|
||||
*/
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
},
|
||||
|
||||
/* Shuffle used by CVT_8_USCALED and CVT_8_SSCALED
|
||||
*/
|
||||
{
|
||||
0x00, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80,
|
||||
0x02, 0x80, 0x80, 0x80, 0x03, 0x80, 0x80, 0x80,
|
||||
},
|
||||
|
||||
/* Shuffle used by CVT_16_USCALED and CVT_16_SSCALED
|
||||
*/
|
||||
{
|
||||
0x00, 0x01, 0x80, 0x80, 0x02, 0x03, 0x80, 0x80,
|
||||
0x04, 0x05, 0x80, 0x80, 0x06, 0x07, 0x80, 0x80,
|
||||
},
|
||||
|
||||
/* High value shuffle used by trans4x4.
|
||||
*/
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
|
||||
0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17
|
||||
},
|
||||
|
||||
/* Low value shuffle used by trans4x4.
|
||||
*/
|
||||
{
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
|
||||
0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fetch vertex attributes for 'count' vertices.
|
||||
*/
|
||||
static void generic_vertex_fetch(struct spu_vs_context *draw,
|
||||
struct spu_exec_machine *machine,
|
||||
const unsigned *elts,
|
||||
unsigned count)
|
||||
{
|
||||
unsigned nr_attrs = draw->vertex_fetch.nr_attrs;
|
||||
unsigned attr;
|
||||
|
||||
ASSERT(count <= 4);
|
||||
|
||||
#if DRAW_DBG
|
||||
printf("SPU: %s count = %u, nr_attrs = %u\n",
|
||||
__FUNCTION__, count, nr_attrs);
|
||||
#endif
|
||||
|
||||
/* loop over vertex attributes (vertex shader inputs)
|
||||
*/
|
||||
for (attr = 0; attr < nr_attrs; attr++) {
|
||||
const unsigned pitch = draw->vertex_fetch.pitch[attr];
|
||||
const uint64_t src = draw->vertex_fetch.src_ptr[attr];
|
||||
const spu_fetch_func fetch = (spu_fetch_func)
|
||||
(draw->vertex_fetch.code + draw->vertex_fetch.code_offset[attr]);
|
||||
unsigned i;
|
||||
unsigned idx;
|
||||
const unsigned bytes_per_entry = draw->vertex_fetch.size[attr];
|
||||
const unsigned quads_per_entry = (bytes_per_entry + 15) / 16;
|
||||
PIPE_ALIGN_VAR(16) qword in[2 * 4];
|
||||
|
||||
|
||||
/* Fetch four attributes for four vertices.
|
||||
*/
|
||||
idx = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
const uint64_t addr = src + (elts[i] * pitch);
|
||||
|
||||
#if DRAW_DBG
|
||||
printf("SPU: fetching = 0x%llx\n", addr);
|
||||
#endif
|
||||
|
||||
spu_dcache_fetch_unaligned(& in[idx], addr, bytes_per_entry);
|
||||
idx += quads_per_entry;
|
||||
}
|
||||
|
||||
/* Be nice and zero out any missing vertices.
|
||||
*/
|
||||
(void) memset(& in[idx], 0, (8 - idx) * sizeof(qword));
|
||||
|
||||
|
||||
/* Convert all 4 vertices to vectors of float.
|
||||
*/
|
||||
(*fetch)(&machine->Inputs[attr].xyzw[0].q, in, fetch_shuffle_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void spu_update_vertex_fetch( struct spu_vs_context *draw )
|
||||
{
|
||||
draw->vertex_fetch.fetch_func = generic_vertex_fetch;
|
||||
}
|
||||
|
|
@ -1,245 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Brian Paul
|
||||
* Ian Romanick <idr@us.ibm.com>
|
||||
*/
|
||||
|
||||
#include <spu_mfcio.h>
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "util/u_math.h"
|
||||
#include "draw/draw_private.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "cell/common.h"
|
||||
#include "spu_vertex_shader.h"
|
||||
#include "spu_exec.h"
|
||||
#include "spu_main.h"
|
||||
|
||||
|
||||
#define MAX_VERTEX_SIZE ((2 + PIPE_MAX_SHADER_OUTPUTS) * 4 * sizeof(float))
|
||||
|
||||
|
||||
#define CLIP_RIGHT_BIT 0x01
|
||||
#define CLIP_LEFT_BIT 0x02
|
||||
#define CLIP_TOP_BIT 0x04
|
||||
#define CLIP_BOTTOM_BIT 0x08
|
||||
#define CLIP_FAR_BIT 0x10
|
||||
#define CLIP_NEAR_BIT 0x20
|
||||
|
||||
|
||||
static INLINE float
|
||||
dot4(const float *a, const float *b)
|
||||
{
|
||||
return (a[0]*b[0] +
|
||||
a[1]*b[1] +
|
||||
a[2]*b[2] +
|
||||
a[3]*b[3]);
|
||||
}
|
||||
|
||||
static INLINE unsigned
|
||||
compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
|
||||
{
|
||||
unsigned mask = 0;
|
||||
unsigned i;
|
||||
|
||||
/* Do the hardwired planes first:
|
||||
*/
|
||||
if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
|
||||
if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
|
||||
if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
|
||||
if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
|
||||
if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
|
||||
if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
|
||||
|
||||
/* Followed by any remaining ones:
|
||||
*/
|
||||
for (i = 6; i < nr; i++) {
|
||||
if (dot4(clip, plane[i]) < 0)
|
||||
mask |= (1<<i);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transform vertices with the current vertex program/shader
|
||||
* Up to four vertices can be shaded at a time.
|
||||
* \param vbuffer the input vertex data
|
||||
* \param elts indexes of four input vertices
|
||||
* \param count number of vertices to shade [1..4]
|
||||
* \param vOut array of pointers to four output vertices
|
||||
*/
|
||||
static void
|
||||
run_vertex_program(struct spu_vs_context *draw,
|
||||
unsigned elts[4], unsigned count,
|
||||
const uint64_t *vOut)
|
||||
{
|
||||
struct spu_exec_machine *machine = &draw->machine;
|
||||
unsigned int j;
|
||||
|
||||
PIPE_ALIGN_VAR(16) struct spu_exec_vector inputs[PIPE_MAX_ATTRIBS];
|
||||
PIPE_ALIGN_VAR(16) struct spu_exec_vector outputs[PIPE_MAX_ATTRIBS];
|
||||
const float *scale = draw->viewport.scale;
|
||||
const float *trans = draw->viewport.translate;
|
||||
|
||||
ASSERT(count <= 4);
|
||||
|
||||
machine->Processor = TGSI_PROCESSOR_VERTEX;
|
||||
|
||||
ASSERT_ALIGN16(draw->constants);
|
||||
machine->Consts = (float (*)[4]) draw->constants;
|
||||
|
||||
machine->Inputs = inputs;
|
||||
machine->Outputs = outputs;
|
||||
|
||||
spu_vertex_fetch( draw, machine, elts, count );
|
||||
|
||||
/* run shader */
|
||||
spu_exec_machine_run( machine );
|
||||
|
||||
|
||||
/* store machine results */
|
||||
for (j = 0; j < count; j++) {
|
||||
unsigned slot;
|
||||
float x, y, z, w;
|
||||
PIPE_ALIGN_VAR(16)
|
||||
unsigned char buffer[sizeof(struct vertex_header)
|
||||
+ MAX_VERTEX_SIZE];
|
||||
struct vertex_header *const tmpOut =
|
||||
(struct vertex_header *) buffer;
|
||||
const unsigned vert_size = ROUNDUP16(sizeof(struct vertex_header)
|
||||
+ (sizeof(float) * 4
|
||||
* draw->num_vs_outputs));
|
||||
|
||||
mfc_get(tmpOut, vOut[j], vert_size, TAG_VERTEX_BUFFER, 0, 0);
|
||||
wait_on_mask(1 << TAG_VERTEX_BUFFER);
|
||||
|
||||
|
||||
/* Handle attr[0] (position) specially:
|
||||
*
|
||||
* XXX: Computing the clipmask should be done in the vertex
|
||||
* program as a set of DP4 instructions appended to the
|
||||
* user-provided code.
|
||||
*/
|
||||
x = tmpOut->clip[0] = machine->Outputs[0].xyzw[0].f[j];
|
||||
y = tmpOut->clip[1] = machine->Outputs[0].xyzw[1].f[j];
|
||||
z = tmpOut->clip[2] = machine->Outputs[0].xyzw[2].f[j];
|
||||
w = tmpOut->clip[3] = machine->Outputs[0].xyzw[3].f[j];
|
||||
|
||||
tmpOut->clipmask = compute_clipmask(tmpOut->clip, draw->plane,
|
||||
draw->nr_planes);
|
||||
tmpOut->edgeflag = 1;
|
||||
|
||||
/* divide by w */
|
||||
w = 1.0f / w;
|
||||
x *= w;
|
||||
y *= w;
|
||||
z *= w;
|
||||
|
||||
/* Viewport mapping */
|
||||
tmpOut->data[0][0] = x * scale[0] + trans[0];
|
||||
tmpOut->data[0][1] = y * scale[1] + trans[1];
|
||||
tmpOut->data[0][2] = z * scale[2] + trans[2];
|
||||
tmpOut->data[0][3] = w;
|
||||
|
||||
/* Remaining attributes are packed into sequential post-transform
|
||||
* vertex attrib slots.
|
||||
*/
|
||||
for (slot = 1; slot < draw->num_vs_outputs; slot++) {
|
||||
tmpOut->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
|
||||
tmpOut->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
|
||||
tmpOut->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
|
||||
tmpOut->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
|
||||
}
|
||||
|
||||
mfc_put(tmpOut, vOut[j], vert_size, TAG_VERTEX_BUFFER, 0, 0);
|
||||
} /* loop over vertices */
|
||||
}
|
||||
|
||||
|
||||
PIPE_ALIGN_VAR(16) unsigned char
|
||||
immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32];
|
||||
|
||||
|
||||
void
|
||||
spu_bind_vertex_shader(struct spu_vs_context *draw,
|
||||
struct cell_shader_info *vs)
|
||||
{
|
||||
const unsigned immediate_addr = vs->immediates;
|
||||
const unsigned immediate_size =
|
||||
ROUNDUP16((sizeof(float) * 4 * vs->num_immediates)
|
||||
+ (immediate_addr & 0x0f));
|
||||
|
||||
|
||||
mfc_get(immediates, immediate_addr & ~0x0f, immediate_size,
|
||||
TAG_VERTEX_BUFFER, 0, 0);
|
||||
|
||||
draw->machine.Instructions = (struct tgsi_full_instruction *)
|
||||
vs->instructions;
|
||||
draw->machine.NumInstructions = vs->num_instructions;
|
||||
|
||||
draw->machine.Declarations = (struct tgsi_full_declaration *)
|
||||
vs->declarations;
|
||||
draw->machine.NumDeclarations = vs->num_declarations;
|
||||
|
||||
draw->num_vs_outputs = vs->num_outputs;
|
||||
|
||||
/* specify the shader to interpret/execute */
|
||||
spu_exec_machine_init(&draw->machine,
|
||||
PIPE_MAX_SAMPLERS,
|
||||
NULL /*samplers*/,
|
||||
PIPE_SHADER_VERTEX);
|
||||
|
||||
wait_on_mask(1 << TAG_VERTEX_BUFFER);
|
||||
|
||||
(void) memcpy(& draw->machine.Imms, &immediates[immediate_addr & 0x0f],
|
||||
sizeof(float) * 4 * vs->num_immediates);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
spu_execute_vertex_shader(struct spu_vs_context *draw,
|
||||
const struct cell_command_vs *vs)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
(void) memcpy(draw->plane, vs->plane, sizeof(float) * 4 * vs->nr_planes);
|
||||
draw->nr_planes = vs->nr_planes;
|
||||
draw->vertex_fetch.nr_attrs = vs->nr_attrs;
|
||||
|
||||
for (i = 0; i < vs->num_elts; i += 4) {
|
||||
const unsigned batch_size = MIN2(vs->num_elts - i, 4);
|
||||
|
||||
run_vertex_program(draw, & vs->elts[i], batch_size, &vs->vOut[i]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
#ifndef SPU_VERTEX_SHADER_H
|
||||
#define SPU_VERTEX_SHADER_H
|
||||
|
||||
#include "cell/common.h"
|
||||
#include "pipe/p_format.h"
|
||||
#include "spu_exec.h"
|
||||
|
||||
struct spu_vs_context;
|
||||
|
||||
typedef void (*spu_full_fetch_func)( struct spu_vs_context *draw,
|
||||
struct spu_exec_machine *machine,
|
||||
const unsigned *elts,
|
||||
unsigned count );
|
||||
|
||||
struct spu_vs_context {
|
||||
struct pipe_viewport_state viewport;
|
||||
|
||||
struct {
|
||||
uint64_t src_ptr[PIPE_MAX_ATTRIBS];
|
||||
unsigned pitch[PIPE_MAX_ATTRIBS];
|
||||
unsigned size[PIPE_MAX_ATTRIBS];
|
||||
unsigned code_offset[PIPE_MAX_ATTRIBS];
|
||||
unsigned nr_attrs;
|
||||
boolean dirty;
|
||||
|
||||
spu_full_fetch_func fetch_func;
|
||||
void *code;
|
||||
} vertex_fetch;
|
||||
|
||||
/* Clip derived state:
|
||||
*/
|
||||
float plane[12][4];
|
||||
unsigned nr_planes;
|
||||
|
||||
struct spu_exec_machine machine;
|
||||
const float (*constants)[4];
|
||||
|
||||
unsigned num_vs_outputs;
|
||||
};
|
||||
|
||||
extern void spu_update_vertex_fetch(struct spu_vs_context *draw);
|
||||
|
||||
static INLINE void spu_vertex_fetch(struct spu_vs_context *draw,
|
||||
struct spu_exec_machine *machine,
|
||||
const unsigned *elts,
|
||||
unsigned count)
|
||||
{
|
||||
if (draw->vertex_fetch.dirty) {
|
||||
spu_update_vertex_fetch(draw);
|
||||
draw->vertex_fetch.dirty = 0;
|
||||
}
|
||||
|
||||
(*draw->vertex_fetch.fetch_func)(draw, machine, elts, count);
|
||||
}
|
||||
|
||||
struct cell_command_vs;
|
||||
|
||||
extern void
|
||||
spu_bind_vertex_shader(struct spu_vs_context *draw,
|
||||
struct cell_shader_info *vs);
|
||||
|
||||
extern void
|
||||
spu_execute_vertex_shader(struct spu_vs_context *draw,
|
||||
const struct cell_command_vs *vs);
|
||||
|
||||
#endif /* SPU_VERTEX_SHADER_H */
|
||||
|
|
@ -29,7 +29,6 @@ DEFINES += \
|
|||
-DGALLIUM_RBUG \
|
||||
-DGALLIUM_TRACE \
|
||||
-DGALLIUM_GALAHAD
|
||||
#-DGALLIUM_CELL will be defined by the config */
|
||||
|
||||
XLIB_TARGET_SOURCES = \
|
||||
xlib.c
|
||||
|
|
@ -38,7 +37,6 @@ XLIB_TARGET_SOURCES = \
|
|||
XLIB_TARGET_OBJECTS = $(XLIB_TARGET_SOURCES:.c=.o)
|
||||
|
||||
|
||||
# Note: CELL_SPU_LIB is only defined for cell configs
|
||||
|
||||
LIBS = \
|
||||
$(GALLIUM_DRIVERS) \
|
||||
|
|
@ -50,7 +48,6 @@ LIBS = \
|
|||
$(TOP)/src/mapi/glapi/libglapi.a \
|
||||
$(TOP)/src/mesa/libmesagallium.a \
|
||||
$(GALLIUM_AUXILIARIES) \
|
||||
$(CELL_SPU_LIB) \
|
||||
|
||||
|
||||
# LLVM
|
||||
|
|
|
|||
|
|
@ -42,11 +42,6 @@ if True:
|
|||
if env['llvm']:
|
||||
env.Append(CPPDEFINES = ['GALLIUM_LLVMPIPE'])
|
||||
env.Prepend(LIBS = [llvmpipe])
|
||||
|
||||
if False:
|
||||
# TODO: Detect Cell SDK
|
||||
env.Append(CPPDEFINES = 'GALLIUM_CELL')
|
||||
env.Prepend(LIBS = [cell])
|
||||
|
||||
# libGL.so.1.5
|
||||
libgl_1_5 = env.SharedLibrary(
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
|
||||
/* Helper function to build a subset of a driver stack consisting of
|
||||
* one of the software rasterizers (cell, llvmpipe, softpipe) and the
|
||||
* one of the software rasterizers (llvmpipe, softpipe) and the
|
||||
* xlib winsys.
|
||||
*/
|
||||
static struct pipe_screen *
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue