diff options
author | Keith Whitwell <[email protected]> | 2009-01-19 10:15:04 +0000 |
---|---|---|
committer | Keith Whitwell <[email protected]> | 2009-01-19 10:15:04 +0000 |
commit | b5db6b039c34117be4e441a2b95abbf97df928c3 (patch) | |
tree | 8efb8698304b70f67cc408e8d12b93ae01a13015 /src/gallium | |
parent | 8f3fac6107460b6d9b011b5c76246468bb16004b (diff) | |
parent | 76753e30781e88912c0465642616ab16bbc1b4f3 (diff) |
Merge commit 'origin/gallium-0.2' into gallium-xlib-rework
Diffstat (limited to 'src/gallium')
68 files changed, 3147 insertions, 2329 deletions
diff --git a/src/gallium/auxiliary/gallivm/Makefile b/src/gallium/auxiliary/gallivm/Makefile index c3f7bfba93b..5a96d94ec37 100644 --- a/src/gallium/auxiliary/gallivm/Makefile +++ b/src/gallium/auxiliary/gallivm/Makefile @@ -66,12 +66,12 @@ depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(INC_SOURCES) gallivm_builtins.cpp: llvm_builtins.c clang --emit-llvm < $< |llvm-as|opt -std-compile-opts > temp1.bin - (echo "static const unsigned char llvm_builtins_data[] = {"; od -txC temp1.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/};/") >$@ + (echo "static const unsigned char llvm_builtins_data[] = {"; od -txC temp1.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/,0x00};/") >$@ rm temp1.bin gallivmsoabuiltins.cpp: soabuiltins.c clang --emit-llvm < $< |llvm-as|opt -std-compile-opts > temp2.bin - (echo "static const unsigned char soabuiltins_data[] = {"; od -txC temp2.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/};/") >$@ + (echo "static const unsigned char soabuiltins_data[] = {"; od -txC temp2.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/,0x00};/") >$@ rm temp2.bin # Emacs tags diff --git a/src/gallium/auxiliary/gallivm/gallivm.cpp b/src/gallium/auxiliary/gallivm/gallivm.cpp index 29adeea47de..f4af5cc8ad5 100644 --- a/src/gallium/auxiliary/gallivm/gallivm.cpp +++ b/src/gallium/auxiliary/gallivm/gallivm.cpp @@ -53,7 +53,7 @@ #include <llvm/ModuleProvider.h> #include <llvm/Pass.h> #include <llvm/PassManager.h> -#include <llvm/ParameterAttributes.h> +#include <llvm/Attributes.h> #include <llvm/Support/PatternMatch.h> #include <llvm/ExecutionEngine/JIT.h> #include <llvm/ExecutionEngine/Interpreter.h> diff --git a/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp b/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp index fcc5c05794a..634bac01507 100644 --- a/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp +++ b/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp @@ -137,4 +137,4 @@ static const unsigned char llvm_builtins_data[] = { 0x58,0x85,0x05,0x14,0xbe,0x34,0x45,0xb5,0x21,0x10,0x82,0x23,0x15,0x46,0x30,0x2c, 0xc8,0x64,0x02,0x06,0xf0,0x3c,0x91,0x73,0x19,0x00,0xe1,0x4b,0x53,0x64,0x0a,0x84, 0x84,0x34,0x85,0x25,0x0c,0x92,0x20,0x59,0xc1,0x20,0x30,0x8f,0x2d,0x10,0x95,0x84, -0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; diff --git a/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp b/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp index 93a9748bdb3..1bd00a0c2a6 100644 --- a/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp +++ b/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp @@ -56,7 +56,7 @@ #include <llvm/ModuleProvider.h> #include <llvm/Pass.h> #include <llvm/PassManager.h> -#include <llvm/ParameterAttributes.h> +#include <llvm/Attributes.h> #include <llvm/Support/PatternMatch.h> #include <llvm/ExecutionEngine/JIT.h> #include <llvm/ExecutionEngine/Interpreter.h> diff --git a/src/gallium/auxiliary/gallivm/instructions.cpp b/src/gallium/auxiliary/gallivm/instructions.cpp index 599975d5add..ee8162efce5 100644 --- a/src/gallium/auxiliary/gallivm/instructions.cpp +++ b/src/gallium/auxiliary/gallivm/instructions.cpp @@ -43,7 +43,7 @@ #include <llvm/Function.h> #include <llvm/InstrTypes.h> #include <llvm/Instructions.h> -#include <llvm/ParameterAttributes.h> +#include <llvm/Attributes.h> #include <llvm/Support/MemoryBuffer.h> #include <llvm/Bitcode/ReaderWriter.h> diff --git a/src/gallium/auxiliary/gallivm/instructionssoa.cpp b/src/gallium/auxiliary/gallivm/instructionssoa.cpp index d5600fd22da..925e948763e 100644 --- a/src/gallium/auxiliary/gallivm/instructionssoa.cpp +++ b/src/gallium/auxiliary/gallivm/instructionssoa.cpp @@ -37,7 +37,7 @@ #include <llvm/Function.h> #include <llvm/Instructions.h> #include <llvm/Transforms/Utils/Cloning.h> -#include <llvm/ParameterAttributes.h> +#include <llvm/Attributes.h> #include <llvm/Support/MemoryBuffer.h> #include <llvm/Bitcode/ReaderWriter.h> @@ -206,11 +206,12 @@ llvm::Module * InstructionsSoa::currentModule() const void InstructionsSoa::createBuiltins() { + std::string ErrMsg; MemoryBuffer *buffer = MemoryBuffer::getMemBuffer( (const char*)&soabuiltins_data[0], - (const char*)&soabuiltins_data[Elements(soabuiltins_data)]); - m_builtins = ParseBitcodeFile(buffer); - std::cout<<"Builtins created at "<<m_builtins<<std::endl; + (const char*)&soabuiltins_data[Elements(soabuiltins_data) - 1]); + m_builtins = ParseBitcodeFile(buffer, &ErrMsg); + std::cout<<"Builtins created at "<<m_builtins<<" ("<<ErrMsg<<")"<<std::endl; assert(m_builtins); createDependencies(); } diff --git a/src/gallium/auxiliary/gallivm/tgsitollvm.cpp b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp index c11b88af9ec..6b18a68fe66 100644 --- a/src/gallium/auxiliary/gallivm/tgsitollvm.cpp +++ b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp @@ -25,7 +25,7 @@ #include <llvm/ModuleProvider.h> #include <llvm/Pass.h> #include <llvm/PassManager.h> -#include <llvm/ParameterAttributes.h> +#include <llvm/Attributes.h> #include <llvm/Support/PatternMatch.h> #include <llvm/ExecutionEngine/JIT.h> #include <llvm/ExecutionEngine/Interpreter.h> diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 071bc2015c7..53a0e722cff 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -213,8 +213,8 @@ emit_instruction(struct spe_function *p, uint32_t inst_bits) -static void emit_RR(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, unsigned rB, const char *name) +static void emit_RR(struct spe_function *p, unsigned op, int rT, + int rA, int rB, const char *name) { union spe_inst_RR inst; inst.inst.op = op; @@ -230,8 +230,8 @@ static void emit_RR(struct spe_function *p, unsigned op, unsigned rT, } -static void emit_RRR(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, unsigned rB, unsigned rC, const char *name) +static void emit_RRR(struct spe_function *p, unsigned op, int rT, + int rA, int rB, int rC, const char *name) { union spe_inst_RRR inst; inst.inst.op = op; @@ -248,8 +248,8 @@ static void emit_RRR(struct spe_function *p, unsigned op, unsigned rT, } -static void emit_RI7(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, int imm, const char *name) +static void emit_RI7(struct spe_function *p, unsigned op, int rT, + int rA, int imm, const char *name) { union spe_inst_RI7 inst; inst.inst.op = op; @@ -266,8 +266,8 @@ static void emit_RI7(struct spe_function *p, unsigned op, unsigned rT, -static void emit_RI8(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, int imm, const char *name) +static void emit_RI8(struct spe_function *p, unsigned op, int rT, + int rA, int imm, const char *name) { union spe_inst_RI8 inst; inst.inst.op = op; @@ -284,8 +284,8 @@ static void emit_RI8(struct spe_function *p, unsigned op, unsigned rT, -static void emit_RI10(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, int imm, const char *name) +static void emit_RI10(struct spe_function *p, unsigned op, int rT, + int rA, int imm, const char *name) { union spe_inst_RI10 inst; inst.inst.op = op; @@ -302,8 +302,8 @@ static void emit_RI10(struct spe_function *p, unsigned op, unsigned rT, /** As above, but do range checking on signed immediate value */ -static void emit_RI10s(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, int imm, const char *name) +static void emit_RI10s(struct spe_function *p, unsigned op, int rT, + int rA, int imm, const char *name) { assert(imm <= 511); assert(imm >= -512); @@ -311,7 +311,7 @@ static void emit_RI10s(struct spe_function *p, unsigned op, unsigned rT, } -static void emit_RI16(struct spe_function *p, unsigned op, unsigned rT, +static void emit_RI16(struct spe_function *p, unsigned op, int rT, int imm, const char *name) { union spe_inst_RI16 inst; @@ -326,7 +326,7 @@ static void emit_RI16(struct spe_function *p, unsigned op, unsigned rT, } -static void emit_RI18(struct spe_function *p, unsigned op, unsigned rT, +static void emit_RI18(struct spe_function *p, unsigned op, int rT, int imm, const char *name) { union spe_inst_RI18 inst; @@ -348,61 +348,61 @@ void _name (struct spe_function *p) \ } #define EMIT_(_name, _op) \ -void _name (struct spe_function *p, unsigned rT) \ +void _name (struct spe_function *p, int rT) \ { \ emit_RR(p, _op, rT, 0, 0, __FUNCTION__); \ } #define EMIT_R(_name, _op) \ -void _name (struct spe_function *p, unsigned rT, unsigned rA) \ +void _name (struct spe_function *p, int rT, int rA) \ { \ emit_RR(p, _op, rT, rA, 0, __FUNCTION__); \ } #define EMIT_RR(_name, _op) \ -void _name (struct spe_function *p, unsigned rT, unsigned rA, unsigned rB) \ +void _name (struct spe_function *p, int rT, int rA, int rB) \ { \ emit_RR(p, _op, rT, rA, rB, __FUNCTION__); \ } #define EMIT_RRR(_name, _op) \ -void _name (struct spe_function *p, unsigned rT, unsigned rA, unsigned rB, unsigned rC) \ +void _name (struct spe_function *p, int rT, int rA, int rB, int rC) \ { \ emit_RRR(p, _op, rT, rA, rB, rC, __FUNCTION__); \ } #define EMIT_RI7(_name, _op) \ -void _name (struct spe_function *p, unsigned rT, unsigned rA, int imm) \ +void _name (struct spe_function *p, int rT, int rA, int imm) \ { \ emit_RI7(p, _op, rT, rA, imm, __FUNCTION__); \ } #define EMIT_RI8(_name, _op, bias) \ -void _name (struct spe_function *p, unsigned rT, unsigned rA, int imm) \ +void _name (struct spe_function *p, int rT, int rA, int imm) \ { \ emit_RI8(p, _op, rT, rA, bias - imm, __FUNCTION__); \ } #define EMIT_RI10(_name, _op) \ -void _name (struct spe_function *p, unsigned rT, unsigned rA, int imm) \ +void _name (struct spe_function *p, int rT, int rA, int imm) \ { \ emit_RI10(p, _op, rT, rA, imm, __FUNCTION__); \ } #define EMIT_RI10s(_name, _op) \ -void _name (struct spe_function *p, unsigned rT, unsigned rA, int imm) \ +void _name (struct spe_function *p, int rT, int rA, int imm) \ { \ emit_RI10s(p, _op, rT, rA, imm, __FUNCTION__); \ } #define EMIT_RI16(_name, _op) \ -void _name (struct spe_function *p, unsigned rT, int imm) \ +void _name (struct spe_function *p, int rT, int imm) \ { \ emit_RI16(p, _op, rT, imm, __FUNCTION__); \ } #define EMIT_RI18(_name, _op) \ -void _name (struct spe_function *p, unsigned rT, int imm) \ +void _name (struct spe_function *p, int rT, int imm) \ { \ emit_RI18(p, _op, rT, imm, __FUNCTION__); \ } @@ -424,7 +424,7 @@ void _name (struct spe_function *p, int imm) \ */ void spe_init_func(struct spe_function *p, unsigned code_size) { - unsigned int i; + uint i; if (!code_size) code_size = 64; @@ -503,6 +503,7 @@ int spe_allocate_register(struct spe_function *p, int reg) */ void spe_release_register(struct spe_function *p, int reg) { + assert(reg >= 0); assert(reg < SPE_NUM_REGS); assert(p->regs[reg] == 1); @@ -517,7 +518,7 @@ void spe_release_register(struct spe_function *p, int reg) */ void spe_allocate_register_set(struct spe_function *p) { - unsigned int i; + uint i; /* Keep track of the set count. If it ever wraps around to 0, * we're in trouble. @@ -538,7 +539,7 @@ void spe_allocate_register_set(struct spe_function *p) void spe_release_register_set(struct spe_function *p) { - unsigned int i; + uint i; /* If the set count drops below zero, we're in trouble. */ assert(p->set_count > 0); @@ -599,7 +600,7 @@ spe_comment(struct spe_function *p, int rel_indent, const char *s) * Load quad word. * NOTE: offset is in bytes and the least significant 4 bits must be zero! */ -void spe_lqd(struct spe_function *p, unsigned rT, unsigned rA, int offset) +void spe_lqd(struct spe_function *p, int rT, int rA, int offset) { const boolean pSave = p->print; @@ -624,7 +625,7 @@ void spe_lqd(struct spe_function *p, unsigned rT, unsigned rA, int offset) * Store quad word. * NOTE: offset is in bytes and the least significant 4 bits must be zero! */ -void spe_stqd(struct spe_function *p, unsigned rT, unsigned rA, int offset) +void spe_stqd(struct spe_function *p, int rT, int rA, int offset) { const boolean pSave = p->print; @@ -653,51 +654,51 @@ void spe_stqd(struct spe_function *p, unsigned rT, unsigned rA, int offset) */ /** Branch Indirect to address in rA */ -void spe_bi(struct spe_function *p, unsigned rA, int d, int e) +void spe_bi(struct spe_function *p, int rA, int d, int e) { emit_RI7(p, 0x1a8, 0, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Interupt Return */ -void spe_iret(struct spe_function *p, unsigned rA, int d, int e) +void spe_iret(struct spe_function *p, int rA, int d, int e) { emit_RI7(p, 0x1aa, 0, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect and set link on external data */ -void spe_bisled(struct spe_function *p, unsigned rT, unsigned rA, int d, +void spe_bisled(struct spe_function *p, int rT, int rA, int d, int e) { emit_RI7(p, 0x1ab, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect and set link. Save PC in rT, jump to rA. */ -void spe_bisl(struct spe_function *p, unsigned rT, unsigned rA, int d, +void spe_bisl(struct spe_function *p, int rT, int rA, int d, int e) { emit_RI7(p, 0x1a9, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect if zero word. If rT.word[0]==0, jump to rA. */ -void spe_biz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) +void spe_biz(struct spe_function *p, int rT, int rA, int d, int e) { emit_RI7(p, 0x128, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect if non-zero word. If rT.word[0]!=0, jump to rA. */ -void spe_binz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) +void spe_binz(struct spe_function *p, int rT, int rA, int d, int e) { emit_RI7(p, 0x129, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect if zero halfword. If rT.halfword[1]==0, jump to rA. */ -void spe_bihz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) +void spe_bihz(struct spe_function *p, int rT, int rA, int d, int e) { emit_RI7(p, 0x12a, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect if non-zero halfword. If rT.halfword[1]!=0, jump to rA. */ -void spe_bihnz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) +void spe_bihnz(struct spe_function *p, int rT, int rA, int d, int e) { emit_RI7(p, 0x12b, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } @@ -733,7 +734,7 @@ EMIT_R (spe_mtspr, 0x10c); void -spe_load_float(struct spe_function *p, unsigned rT, float x) +spe_load_float(struct spe_function *p, int rT, float x) { if (x == 0.0f) { spe_il(p, rT, 0x0); @@ -760,7 +761,7 @@ spe_load_float(struct spe_function *p, unsigned rT, float x) void -spe_load_int(struct spe_function *p, unsigned rT, int i) +spe_load_int(struct spe_function *p, int rT, int i) { if (-32768 <= i && i <= 32767) { spe_il(p, rT, i); @@ -772,7 +773,7 @@ spe_load_int(struct spe_function *p, unsigned rT, int i) } } -void spe_load_uint(struct spe_function *p, unsigned rT, unsigned int ui) +void spe_load_uint(struct spe_function *p, int rT, uint ui) { /* If the whole value is in the lower 18 bits, use ila, which * doesn't sign-extend. Otherwise, if the two halfwords of @@ -793,7 +794,7 @@ void spe_load_uint(struct spe_function *p, unsigned rT, unsigned int ui) ((ui & 0x00ff0000) == 0 || (ui & 0x00ff0000) == 0x00ff0000) && ((ui & 0xff000000) == 0 || (ui & 0xff000000) == 0xff000000) ) { - unsigned int mask = 0; + uint mask = 0; /* fsmbi duplicates each bit in the given mask eight times, * using a 16-bit value to initialize a 16-byte quadword. * Each 4-bit nybble of the mask corresponds to a full word @@ -822,7 +823,7 @@ void spe_load_uint(struct spe_function *p, unsigned rT, unsigned int ui) * Changes to one should be made in the other. */ void -spe_and_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) +spe_and_uint(struct spe_function *p, int rT, int rA, uint ui) { /* If we can, emit a single instruction, either And Byte Immediate * (which uses the same constant across each byte), And Halfword Immediate @@ -832,7 +833,7 @@ spe_and_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) * * Otherwise, we'll need to use a temporary register. */ - unsigned int tmp; + uint tmp; /* If the upper 23 bits are all 0s or all 1s, sign extension * will work and we can use And Word Immediate @@ -863,7 +864,7 @@ spe_and_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) } /* Otherwise, we'll have to use a temporary register. */ - unsigned int tmp_reg = spe_allocate_available_register(p); + int tmp_reg = spe_allocate_available_register(p); spe_load_uint(p, tmp_reg, ui); spe_and(p, rT, rA, tmp_reg); spe_release_register(p, tmp_reg); @@ -875,7 +876,7 @@ spe_and_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) * Changes to one should be made in the other. */ void -spe_xor_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) +spe_xor_uint(struct spe_function *p, int rT, int rA, uint ui) { /* If we can, emit a single instruction, either Exclusive Or Byte * Immediate (which uses the same constant across each byte), Exclusive @@ -885,7 +886,7 @@ spe_xor_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) * * Otherwise, we'll need to use a temporary register. */ - unsigned int tmp; + uint tmp; /* If the upper 23 bits are all 0s or all 1s, sign extension * will work and we can use Exclusive Or Word Immediate @@ -916,14 +917,14 @@ spe_xor_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) } /* Otherwise, we'll have to use a temporary register. */ - unsigned int tmp_reg = spe_allocate_available_register(p); + int tmp_reg = spe_allocate_available_register(p); spe_load_uint(p, tmp_reg, ui); spe_xor(p, rT, rA, tmp_reg); spe_release_register(p, tmp_reg); } void -spe_compare_equal_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) +spe_compare_equal_uint(struct spe_function *p, int rT, int rA, uint ui) { /* If the comparison value is 9 bits or less, it fits inside a * Compare Equal Word Immediate instruction. @@ -933,7 +934,7 @@ spe_compare_equal_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigne } /* Otherwise, we're going to have to load a word first. */ else { - unsigned int tmp_reg = spe_allocate_available_register(p); + int tmp_reg = spe_allocate_available_register(p); spe_load_uint(p, tmp_reg, ui); spe_ceq(p, rT, rA, tmp_reg); spe_release_register(p, tmp_reg); @@ -941,7 +942,7 @@ spe_compare_equal_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigne } void -spe_compare_greater_uint(struct spe_function *p, unsigned rT, unsigned rA, unsigned int ui) +spe_compare_greater_uint(struct spe_function *p, int rT, int rA, uint ui) { /* If the comparison value is 10 bits or less, it fits inside a * Compare Logical Greater Than Word Immediate instruction. @@ -951,7 +952,7 @@ spe_compare_greater_uint(struct spe_function *p, unsigned rT, unsigned rA, unsig } /* Otherwise, we're going to have to load a word first. */ else { - unsigned int tmp_reg = spe_allocate_available_register(p); + int tmp_reg = spe_allocate_available_register(p); spe_load_uint(p, tmp_reg, ui); spe_clgt(p, rT, rA, tmp_reg); spe_release_register(p, tmp_reg); @@ -959,10 +960,10 @@ spe_compare_greater_uint(struct spe_function *p, unsigned rT, unsigned rA, unsig } void -spe_splat(struct spe_function *p, unsigned rT, unsigned rA) +spe_splat(struct spe_function *p, int rT, int rA) { /* Use a temporary, just in case rT == rA */ - unsigned int tmp_reg = spe_allocate_available_register(p); + int tmp_reg = spe_allocate_available_register(p); /* Duplicate bytes 0, 1, 2, and 3 across the whole register */ spe_ila(p, tmp_reg, 0x00010203); spe_shufb(p, rT, rA, rA, tmp_reg); @@ -971,14 +972,14 @@ spe_splat(struct spe_function *p, unsigned rT, unsigned rA) void -spe_complement(struct spe_function *p, unsigned rT, unsigned rA) +spe_complement(struct spe_function *p, int rT, int rA) { spe_nor(p, rT, rA, rA); } void -spe_move(struct spe_function *p, unsigned rT, unsigned rA) +spe_move(struct spe_function *p, int rT, int rA) { /* Use different instructions depending on the instruction address * to take advantage of the dual pipelines. @@ -991,14 +992,14 @@ spe_move(struct spe_function *p, unsigned rT, unsigned rA) void -spe_zero(struct spe_function *p, unsigned rT) +spe_zero(struct spe_function *p, int rT) { spe_xor(p, rT, rT, rT); } void -spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word) +spe_splat_word(struct spe_function *p, int rT, int rA, int word) { assert(word >= 0); assert(word <= 3); @@ -1038,9 +1039,9 @@ spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word) * like "x = min(x, a)", we always allocate a new register to be safe. */ void -spe_float_min(struct spe_function *p, unsigned rT, unsigned rA, unsigned rB) +spe_float_min(struct spe_function *p, int rT, int rA, int rB) { - unsigned int compare_reg = spe_allocate_available_register(p); + int compare_reg = spe_allocate_available_register(p); spe_fcgt(p, compare_reg, rA, rB); spe_selb(p, rT, rA, rB, compare_reg); spe_release_register(p, compare_reg); @@ -1055,9 +1056,9 @@ spe_float_min(struct spe_function *p, unsigned rT, unsigned rA, unsigned rB) * so that the larger of the two is selected instead of the smaller. */ void -spe_float_max(struct spe_function *p, unsigned rT, unsigned rA, unsigned rB) +spe_float_max(struct spe_function *p, int rT, int rA, int rB) { - unsigned int compare_reg = spe_allocate_available_register(p); + int compare_reg = spe_allocate_available_register(p); spe_fcgt(p, compare_reg, rA, rB); spe_selb(p, rT, rB, rA, compare_reg); spe_release_register(p, compare_reg); diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index f9ad2acacdd..65d9c774154 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -79,9 +79,9 @@ struct spe_function }; -extern void spe_init_func(struct spe_function *p, unsigned code_size); +extern void spe_init_func(struct spe_function *p, uint code_size); extern void spe_release_func(struct spe_function *p); -extern unsigned spe_code_size(const 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); @@ -89,8 +89,7 @@ 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 unsigned -spe_get_registers_used(const struct spe_function *p, ubyte used[]); +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); @@ -103,31 +102,25 @@ extern void spe_comment(struct spe_function *p, int rel_indent, const char *s); #define EMIT(_name, _op) \ extern void _name (struct spe_function *p); #define EMIT_(_name, _op) \ - extern void _name (struct spe_function *p, unsigned rT); + extern void _name (struct spe_function *p, int rT); #define EMIT_R(_name, _op) \ - extern void _name (struct spe_function *p, unsigned rT, unsigned rA); + extern void _name (struct spe_function *p, int rT, int rA); #define EMIT_RR(_name, _op) \ - extern void _name (struct spe_function *p, unsigned rT, unsigned rA, \ - unsigned rB); + 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, unsigned rT, unsigned rA, \ - unsigned rB, unsigned rC); + 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, unsigned rT, unsigned rA, \ - int imm); + 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, unsigned rT, unsigned rA, \ - int imm); + 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, unsigned rT, unsigned rA, \ - int imm); + 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, unsigned rT, unsigned rA, \ - int imm); + 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, unsigned rT, int imm); + extern void _name (struct spe_function *p, int rT, int imm); #define EMIT_RI18(_name, _op) \ - extern void _name (struct spe_function *p, unsigned rT, int imm); + 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 @@ -301,82 +294,82 @@ EMIT_RI16(spe_brhz, 0x044) EMIT (spe_lnop, 0x001) extern void -spe_lqd(struct spe_function *p, unsigned rT, unsigned rA, int offset); +spe_lqd(struct spe_function *p, int rT, int rA, int offset); extern void -spe_stqd(struct spe_function *p, unsigned rT, unsigned rA, int offset); +spe_stqd(struct spe_function *p, int rT, int rA, int offset); -extern void spe_bi(struct spe_function *p, unsigned rA, int d, int e); -extern void spe_iret(struct spe_function *p, unsigned rA, int d, int e); -extern void spe_bisled(struct spe_function *p, unsigned rT, unsigned rA, +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, unsigned rT, unsigned rA, +extern void spe_bisl(struct spe_function *p, int rT, int rA, int d, int e); -extern void spe_biz(struct spe_function *p, unsigned rT, unsigned rA, +extern void spe_biz(struct spe_function *p, int rT, int rA, int d, int e); -extern void spe_binz(struct spe_function *p, unsigned rT, unsigned rA, +extern void spe_binz(struct spe_function *p, int rT, int rA, int d, int e); -extern void spe_bihz(struct spe_function *p, unsigned rT, unsigned rA, +extern void spe_bihz(struct spe_function *p, int rT, int rA, int d, int e); -extern void spe_bihnz(struct spe_function *p, unsigned rT, unsigned rA, +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, unsigned rT, float x); +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, unsigned rT, int i); +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, unsigned rT, unsigned int ui); +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, unsigned rT, unsigned rA, unsigned int ui); +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, unsigned rT, unsigned rA, unsigned int ui); +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, unsigned rT, unsigned rA, unsigned int ui); +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, unsigned rT, unsigned rA, unsigned int ui); +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, unsigned rT, unsigned rA); +spe_splat(struct spe_function *p, int rT, int rA); /** rT = complement_all_bits(rA). */ extern void -spe_complement(struct spe_function *p, unsigned rT, unsigned rA); +spe_complement(struct spe_function *p, int rT, int rA); /** rT = rA. */ extern void -spe_move(struct spe_function *p, unsigned rT, unsigned rA); +spe_move(struct spe_function *p, int rT, int rA); /** rT = {0,0,0,0}. */ extern void -spe_zero(struct spe_function *p, unsigned rT); +spe_zero(struct spe_function *p, int rT); /** rT = splat(rA, word) */ extern void -spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word); +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, unsigned rT, unsigned rA, unsigned rB); +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, unsigned rT, unsigned rA, unsigned rB); +spe_float_max(struct spe_function *p, int rT, int rA, int rB); /* Floating-point instructions diff --git a/src/gallium/auxiliary/util/u_memory.h b/src/gallium/auxiliary/util/u_memory.h index 626b13af83d..1a6b596421f 100644 --- a/src/gallium/auxiliary/util/u_memory.h +++ b/src/gallium/auxiliary/util/u_memory.h @@ -52,7 +52,7 @@ extern "C" { #endif -#if defined(PIPE_OS_WINDOWS) && defined(DEBUG) +#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) && defined(DEBUG) /* memory debugging */ diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h index 98554d7f521..1f6860da119 100644 --- a/src/gallium/drivers/cell/common.h +++ b/src/gallium/drivers/cell/common.h @@ -49,6 +49,15 @@ } + +#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); @@ -134,6 +143,11 @@ struct cell_fence 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 @@ -141,8 +155,9 @@ struct cell_fence */ struct cell_command_fence { - uint64_t opcode; /**< CELL_CMD_FENCE */ + opcode_t opcode; /**< CELL_CMD_FENCE */ struct cell_fence *fence; + uint32_t pad_[3]; }; @@ -163,7 +178,7 @@ struct cell_command_fence */ struct cell_command_fragment_ops { - uint64_t opcode; /**< CELL_CMD_STATE_FRAGMENT_OPS */ + opcode_t opcode; /**< CELL_CMD_STATE_FRAGMENT_OPS */ /* Fields for the fallback case */ struct pipe_depth_stencil_alpha_state dsa; @@ -189,8 +204,9 @@ struct cell_command_fragment_ops */ struct cell_command_fragment_program { - uint64_t opcode; /**< CELL_CMD_STATE_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]; }; @@ -200,10 +216,11 @@ struct cell_command_fragment_program */ struct cell_command_framebuffer { - uint64_t opcode; /**< CELL_CMD_STATE_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]; }; @@ -212,7 +229,7 @@ struct cell_command_framebuffer */ struct cell_command_rasterizer { - uint64_t opcode; /**< CELL_CMD_STATE_RASTERIZER */ + opcode_t opcode; /**< CELL_CMD_STATE_RASTERIZER */ struct pipe_rasterizer_state rasterizer; }; @@ -222,9 +239,10 @@ struct cell_command_rasterizer */ struct cell_command_clear_surface { - uint64_t opcode; /**< CELL_CMD_CLEAR_SURFACE */ + opcode_t opcode; /**< CELL_CMD_CLEAR_SURFACE */ uint surface; /**< Temporary: 0=color, 1=Z */ uint value; + uint32_t pad[2]; }; @@ -271,7 +289,7 @@ struct cell_shader_info #define SPU_VERTS_PER_BATCH 64 struct cell_command_vs { - uint64_t opcode; /**< CELL_CMD_VS_EXECUTE */ + opcode_t opcode; /**< CELL_CMD_VS_EXECUTE */ uint64_t vOut[SPU_VERTS_PER_BATCH]; unsigned num_elts; unsigned elts[SPU_VERTS_PER_BATCH]; @@ -283,7 +301,7 @@ struct cell_command_vs struct cell_command_render { - uint64_t opcode; /**< CELL_CMD_RENDER */ + opcode_t opcode; /**< CELL_CMD_RENDER */ uint prim_type; /**< PIPE_PRIM_x */ uint num_verts; uint vertex_size; /**< bytes per vertex */ @@ -292,27 +310,30 @@ struct cell_command_render float xmin, ymin, xmax, ymax; /* XXX another dummy field */ uint min_index; boolean inline_verts; + uint32_t pad_[1]; }; struct cell_command_release_verts { - uint64_t opcode; /**< CELL_CMD_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 { - uint64_t opcode; /**< CELL_CMD_STATE_SAMPLER */ + opcode_t opcode; /**< CELL_CMD_STATE_SAMPLER */ uint unit; struct pipe_sampler_state state; + uint32_t pad_[1]; }; struct cell_command_texture { - uint64_t opcode; /**< CELL_CMD_STATE_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 */ diff --git a/src/gallium/drivers/cell/ppu/cell_batch.c b/src/gallium/drivers/cell/ppu/cell_batch.c index 962775cd335..fe144f8b849 100644 --- a/src/gallium/drivers/cell/ppu/cell_batch.c +++ b/src/gallium/drivers/cell/ppu/cell_batch.c @@ -108,15 +108,16 @@ emit_fence(struct cell_context *cell) 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 = CELL_CMD_FENCE; + 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); - assert(sizeof(struct cell_command_fence) % 8 == 0); } @@ -192,69 +193,18 @@ cell_batch_free_space(const struct cell_context *cell) /** - * Append data to the current batch buffer. - * \param data address of block of bytes to append - * \param bytes size of block of bytes - */ -void -cell_batch_append(struct cell_context *cell, const void *data, uint bytes) -{ - uint size; - - ASSERT(bytes % 8 == 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 + bytes <= CELL_BUFFER_SIZE); - - memcpy(cell->buffer[cell->cur_batch] + size, data, bytes); - - cell->buffer_size[cell->cur_batch] = size + bytes; -} - - -/** * 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_alloc(struct cell_context *cell, uint bytes) -{ - return cell_batch_alloc_aligned(cell, bytes, 1); -} - - -/** - * Same as \sa cell_batch_alloc, but return an address at a particular - * alignment. - */ -void * -cell_batch_alloc_aligned(struct cell_context *cell, uint bytes, - uint alignment) +cell_batch_alloc16(struct cell_context *cell, uint bytes) { void *pos; - uint size, padbytes; + uint size; - ASSERT(bytes % 8 == 0); + ASSERT(bytes % 16 == 0); ASSERT(bytes <= CELL_BUFFER_SIZE); - ASSERT(alignment > 0); ASSERT(cell->cur_batch >= 0); #ifdef ASSERT @@ -269,17 +219,12 @@ cell_batch_alloc_aligned(struct cell_context *cell, uint bytes, size = cell->buffer_size[cell->cur_batch]; - padbytes = (alignment - (size % alignment)) % alignment; - - if (padbytes + bytes > cell_batch_free_space(cell)) { + if (bytes > cell_batch_free_space(cell)) { cell_batch_flush(cell); size = 0; } - else { - size += padbytes; - } - ASSERT(size % alignment == 0); + ASSERT(size % 16 == 0); ASSERT(size + bytes <= CELL_BUFFER_SIZE); pos = (void *) (cell->buffer[cell->cur_batch] + size); diff --git a/src/gallium/drivers/cell/ppu/cell_batch.h b/src/gallium/drivers/cell/ppu/cell_batch.h index f74dd600791..290136031a1 100644 --- a/src/gallium/drivers/cell/ppu/cell_batch.h +++ b/src/gallium/drivers/cell/ppu/cell_batch.h @@ -44,15 +44,8 @@ cell_batch_flush(struct cell_context *cell); extern uint cell_batch_free_space(const struct cell_context *cell); -extern void -cell_batch_append(struct cell_context *cell, const void *data, uint bytes); - -extern void * -cell_batch_alloc(struct cell_context *cell, uint bytes); - extern void * -cell_batch_alloc_aligned(struct cell_context *cell, uint bytes, - uint alignment); +cell_batch_alloc16(struct cell_context *cell, uint bytes); extern void cell_init_batch_buffers(struct cell_context *cell); diff --git a/src/gallium/drivers/cell/ppu/cell_clear.c b/src/gallium/drivers/cell/ppu/cell_clear.c index 037635e4660..c2e276988ca 100644 --- a/src/gallium/drivers/cell/ppu/cell_clear.c +++ b/src/gallium/drivers/cell/ppu/cell_clear.c @@ -99,10 +99,11 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps, /* 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_alloc(cell, sizeof(*clr)); - clr->opcode = CELL_CMD_CLEAR_SURFACE; + cell_batch_alloc16(cell, sizeof(*clr)); + clr->opcode[0] = CELL_CMD_CLEAR_SURFACE; clr->surface = surfIndex; clr->value = clearValue; } diff --git a/src/gallium/drivers/cell/ppu/cell_flush.c b/src/gallium/drivers/cell/ppu/cell_flush.c index a64967b4b9e..8275c9dc9c7 100644 --- a/src/gallium/drivers/cell/ppu/cell_flush.c +++ b/src/gallium/drivers/cell/ppu/cell_flush.c @@ -72,8 +72,9 @@ cell_flush_int(struct cell_context *cell, unsigned flags) flushing = TRUE; if (flags & CELL_FLUSH_WAIT) { - uint64_t *cmd = (uint64_t *) cell_batch_alloc(cell, sizeof(uint64_t)); - *cmd = CELL_CMD_FINISH; + 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); @@ -101,11 +102,11 @@ void cell_flush_buffer_range(struct cell_context *cell, void *ptr, unsigned size) { - uint64_t batch[1 + (ROUNDUP8(sizeof(struct cell_buffer_range)) / 8)]; - struct cell_buffer_range *br = (struct cell_buffer_range *) & batch[1]; - + 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; - cell_batch_append(cell, batch, sizeof(batch)); } diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c index 2c64eb1bccd..0ea8f017ef9 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c @@ -2,6 +2,7 @@ * * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. + * Copyright 2009 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 @@ -25,11 +26,10 @@ * **************************************************************************/ - - /** * Generate SPU per-fragment code (actually per-quad code). * \author Brian Paul + * \author Bob Ellison */ @@ -55,7 +55,7 @@ * \param ifbZ_reg register containing integer frame buffer Z values (in/out) * \param zmask_reg register containing result of Z test/comparison (out) * - * Returns true if the Z-buffer needs to be updated. + * Returns TRUE if the Z-buffer needs to be updated. */ static boolean gen_depth_test(struct spe_function *f, @@ -134,10 +134,10 @@ gen_depth_test(struct spe_function *f, * framebufferZ = (ztest_passed ? fragmentZ : framebufferZ; */ spe_selb(f, ifbZ_reg, ifbZ_reg, ifragZ_reg, mask_reg); - return true; + return TRUE; } - return false; + return FALSE; } @@ -237,41 +237,136 @@ gen_alpha_test(const struct pipe_depth_stencil_alpha_state *dsa, spe_release_register(f, amask_reg); } -/* This pair of functions is used inline to allocate and deallocate + +/** + * This pair of functions is used inline to allocate and deallocate * optional constant registers. Once a constant is discovered to be * needed, we will likely need it again, so we don't want to deallocate * it and have to allocate and load it again unnecessarily. */ -static inline void -setup_optional_register(struct spe_function *f, boolean *is_already_set, unsigned int *r) +static INLINE void +setup_optional_register(struct spe_function *f, + int *r) { - if (*is_already_set) return; - *r = spe_allocate_available_register(f); - *is_already_set = true; + if (*r < 0) + *r = spe_allocate_available_register(f); } -static inline void -release_optional_register(struct spe_function *f, boolean *is_already_set, unsigned int r) +static INLINE void +release_optional_register(struct spe_function *f, + int r) { - if (!*is_already_set) return; - spe_release_register(f, r); - *is_already_set = false; + if (r >= 0) + spe_release_register(f, r); } -static inline void -setup_const_register(struct spe_function *f, boolean *is_already_set, unsigned int *r, float value) +static INLINE void +setup_const_register(struct spe_function *f, + int *r, + float value) { - if (*is_already_set) return; - setup_optional_register(f, is_already_set, r); + if (*r >= 0) + return; + setup_optional_register(f, r); spe_load_float(f, *r, value); } -static inline void -release_const_register(struct spe_function *f, boolean *is_already_set, unsigned int r) +static INLINE void +release_const_register(struct spe_function *f, + int r) { - release_optional_register(f, is_already_set, r); + release_optional_register(f, r); } + + +/** + * Unpack/convert framebuffer colors from four 32-bit packed colors + * (fbRGBA) to four float RGBA vectors (fbR, fbG, fbB, fbA). + * Each 8-bit color component is expanded into a float in [0.0, 1.0]. + */ +static void +unpack_colors(struct spe_function *f, + enum pipe_format color_format, + int fbRGBA_reg, + int fbR_reg, int fbG_reg, int fbB_reg, int fbA_reg) +{ + int mask0_reg = spe_allocate_available_register(f); + int mask1_reg = spe_allocate_available_register(f); + int mask2_reg = spe_allocate_available_register(f); + int mask3_reg = spe_allocate_available_register(f); + + spe_load_int(f, mask0_reg, 0xff); + spe_load_int(f, mask1_reg, 0xff00); + spe_load_int(f, mask2_reg, 0xff0000); + spe_load_int(f, mask3_reg, 0xff000000); + + spe_comment(f, 0, "Unpack framebuffer colors, convert to floats"); + + switch (color_format) { + case PIPE_FORMAT_A8R8G8B8_UNORM: + /* fbB = fbRGBA & mask */ + spe_and(f, fbB_reg, fbRGBA_reg, mask0_reg); + + /* fbG = fbRGBA & mask */ + spe_and(f, fbG_reg, fbRGBA_reg, mask1_reg); + + /* fbR = fbRGBA & mask */ + spe_and(f, fbR_reg, fbRGBA_reg, mask2_reg); + + /* fbA = fbRGBA & mask */ + spe_and(f, fbA_reg, fbRGBA_reg, mask3_reg); + + /* fbG = fbG >> 8 */ + spe_roti(f, fbG_reg, fbG_reg, -8); + + /* fbR = fbR >> 16 */ + spe_roti(f, fbR_reg, fbR_reg, -16); + + /* fbA = fbA >> 24 */ + spe_roti(f, fbA_reg, fbA_reg, -24); + break; + + case PIPE_FORMAT_B8G8R8A8_UNORM: + /* fbA = fbRGBA & mask */ + spe_and(f, fbA_reg, fbRGBA_reg, mask0_reg); + + /* fbR = fbRGBA & mask */ + spe_and(f, fbR_reg, fbRGBA_reg, mask1_reg); + + /* fbG = fbRGBA & mask */ + spe_and(f, fbG_reg, fbRGBA_reg, mask2_reg); + + /* fbB = fbRGBA & mask */ + spe_and(f, fbB_reg, fbRGBA_reg, mask3_reg); + + /* fbR = fbR >> 8 */ + spe_roti(f, fbR_reg, fbR_reg, -8); + + /* fbG = fbG >> 16 */ + spe_roti(f, fbG_reg, fbG_reg, -16); + + /* fbB = fbB >> 24 */ + spe_roti(f, fbB_reg, fbB_reg, -24); + break; + + default: + ASSERT(0); + } + + /* convert int[4] in [0,255] to float[4] in [0.0, 1.0] */ + spe_cuflt(f, fbR_reg, fbR_reg, 8); + spe_cuflt(f, fbG_reg, fbG_reg, 8); + spe_cuflt(f, fbB_reg, fbB_reg, 8); + spe_cuflt(f, fbA_reg, fbA_reg, 8); + + spe_release_register(f, mask0_reg); + spe_release_register(f, mask1_reg); + spe_release_register(f, mask2_reg); + spe_release_register(f, mask3_reg); +} + + /** * Generate SPE code to implement the given blend mode for a quad of pixels. * \param f SPE function to append instruction onto. @@ -310,90 +405,14 @@ gen_blend(const struct pipe_blend_state *blend, * if we do use them, make sure we only allocate them once by * keeping a flag on each one. */ - boolean one_reg_set = false; - unsigned int one_reg; - boolean constR_reg_set = false, constG_reg_set = false, - constB_reg_set = false, constA_reg_set = false; - unsigned int constR_reg, constG_reg, constB_reg, constA_reg; + int one_reg = -1; + int constR_reg = -1, constG_reg = -1, constB_reg = -1, constA_reg = -1; ASSERT(blend->blend_enable); - /* Unpack/convert framebuffer colors from four 32-bit packed colors - * (fbRGBA) to four float RGBA vectors (fbR, fbG, fbB, fbA). - * Each 8-bit color component is expanded into a float in [0.0, 1.0]. - */ - { - int mask_reg = spe_allocate_available_register(f); - - /* mask = {0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff} */ - spe_load_int(f, mask_reg, 0xff); - - /* XXX there may be more clever ways to implement the following code */ - switch (color_format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - /* fbB = fbB & mask */ - spe_and(f, fbB_reg, fbRGBA_reg, mask_reg); - /* mask = mask << 8 */ - spe_roti(f, mask_reg, mask_reg, 8); - - /* fbG = fbRGBA & mask */ - spe_and(f, fbG_reg, fbRGBA_reg, mask_reg); - /* fbG = fbG >> 8 */ - spe_roti(f, fbG_reg, fbG_reg, -8); - /* mask = mask << 8 */ - spe_roti(f, mask_reg, mask_reg, 8); - - /* fbR = fbRGBA & mask */ - spe_and(f, fbR_reg, fbRGBA_reg, mask_reg); - /* fbR = fbR >> 16 */ - spe_roti(f, fbR_reg, fbR_reg, -16); - /* mask = mask << 8 */ - spe_roti(f, mask_reg, mask_reg, 8); - - /* fbA = fbRGBA & mask */ - spe_and(f, fbA_reg, fbRGBA_reg, mask_reg); - /* fbA = fbA >> 24 */ - spe_roti(f, fbA_reg, fbA_reg, -24); - break; - - case PIPE_FORMAT_B8G8R8A8_UNORM: - /* fbA = fbA & mask */ - spe_and(f, fbA_reg, fbRGBA_reg, mask_reg); - /* mask = mask << 8 */ - spe_roti(f, mask_reg, mask_reg, 8); - - /* fbR = fbRGBA & mask */ - spe_and(f, fbR_reg, fbRGBA_reg, mask_reg); - /* fbR = fbR >> 8 */ - spe_roti(f, fbR_reg, fbR_reg, -8); - /* mask = mask << 8 */ - spe_roti(f, mask_reg, mask_reg, 8); - - /* fbG = fbRGBA & mask */ - spe_and(f, fbG_reg, fbRGBA_reg, mask_reg); - /* fbG = fbG >> 16 */ - spe_roti(f, fbG_reg, fbG_reg, -16); - /* mask = mask << 8 */ - spe_roti(f, mask_reg, mask_reg, 8); - - /* fbB = fbRGBA & mask */ - spe_and(f, fbB_reg, fbRGBA_reg, mask_reg); - /* fbB = fbB >> 24 */ - spe_roti(f, fbB_reg, fbB_reg, -24); - break; - - default: - ASSERT(0); - } - - /* convert int[4] in [0,255] to float[4] in [0.0, 1.0] */ - spe_cuflt(f, fbR_reg, fbR_reg, 8); - spe_cuflt(f, fbG_reg, fbG_reg, 8); - spe_cuflt(f, fbB_reg, fbB_reg, 8); - spe_cuflt(f, fbA_reg, fbA_reg, 8); - - spe_release_register(f, mask_reg); - } + /* packed RGBA -> float colors */ + unpack_colors(f, color_format, fbRGBA_reg, + fbR_reg, fbG_reg, fbB_reg, fbA_reg); /* * Compute Src RGB terms. We're actually looking for the value @@ -476,9 +495,9 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_CONST_COLOR: /* We need the optional constant color registers */ - setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); - setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); - setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + setup_const_register(f, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg, blend_color->color[2]); /* now, factor = (Rc,Gc,Bc), so term = (R*Rc,G*Gc,B*Bc) */ spe_fm(f, term1R_reg, fragR_reg, constR_reg); spe_fm(f, term1G_reg, fragG_reg, constG_reg); @@ -486,7 +505,7 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_CONST_ALPHA: /* we'll need the optional constant alpha register */ - setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + setup_const_register(f, &constA_reg, blend_color->color[3]); /* factor = (Ac,Ac,Ac), so term = (R*Ac,G*Ac,B*Ac) */ spe_fm(f, term1R_reg, fragR_reg, constA_reg); spe_fm(f, term1G_reg, fragG_reg, constA_reg); @@ -494,9 +513,9 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_INV_CONST_COLOR: /* We need the optional constant color registers */ - setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); - setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); - setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + setup_const_register(f, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg, blend_color->color[2]); /* factor = (1-Rc,1-Gc,1-Bc), so term = (R*(1-Rc),G*(1-Gc),B*(1-Bc)) * or term = (R-R*Rc, G-G*Gc, B-B*Bc) * fnms(a,b,c,d) computes a = d - b*c @@ -507,9 +526,9 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_INV_CONST_ALPHA: /* We need the optional constant color registers */ - setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); - setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); - setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + setup_const_register(f, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg, blend_color->color[2]); /* factor = (1-Ac,1-Ac,1-Ac), so term = (R*(1-Ac),G*(1-Ac),B*(1-Ac)) * or term = (R-R*Ac,G-G*Ac,B-B*Ac) * fnms(a,b,c,d) computes a = d - b*c @@ -520,7 +539,7 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* We'll need the optional {1,1,1,1} register */ - setup_const_register(f, &one_reg_set, &one_reg, 1.0f); + setup_const_register(f, &one_reg, 1.0f); /* factor = (min(A,1-Afb),min(A,1-Afb),min(A,1-Afb)), so * term = (R*min(A,1-Afb), G*min(A,1-Afb), B*min(A,1-Afb)) * We could expand the term (as a*min(b,c) == min(a*b,a*c) @@ -598,7 +617,7 @@ gen_blend(const struct pipe_blend_state *blend, case PIPE_BLENDFACTOR_CONST_ALPHA: /* fall through */ case PIPE_BLENDFACTOR_CONST_COLOR: /* We need the optional constA_reg register */ - setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + setup_const_register(f, &constA_reg, blend_color->color[3]); /* factor = Ac, so term = A*Ac */ spe_fm(f, term1A_reg, fragA_reg, constA_reg); break; @@ -606,7 +625,7 @@ gen_blend(const struct pipe_blend_state *blend, case PIPE_BLENDFACTOR_INV_CONST_ALPHA: /* fall through */ case PIPE_BLENDFACTOR_INV_CONST_COLOR: /* We need the optional constA_reg register */ - setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + setup_const_register(f, &constA_reg, blend_color->color[3]); /* factor = 1-Ac, so term = A*(1-Ac) = A-A*Ac */ /* fnms(a,b,c,d) computes a = d - b*c */ spe_fnms(f, term1A_reg, fragA_reg, constA_reg, fragA_reg); @@ -703,9 +722,9 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_CONST_COLOR: /* We need the optional constant color registers */ - setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); - setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); - setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + setup_const_register(f, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg, blend_color->color[2]); /* now, factor = (Rc,Gc,Bc), so term = (Rfb*Rc,Gfb*Gc,Bfb*Bc) */ spe_fm(f, term2R_reg, fbR_reg, constR_reg); spe_fm(f, term2G_reg, fbG_reg, constG_reg); @@ -713,7 +732,7 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_CONST_ALPHA: /* we'll need the optional constant alpha register */ - setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + setup_const_register(f, &constA_reg, blend_color->color[3]); /* factor = (Ac,Ac,Ac), so term = (Rfb*Ac,Gfb*Ac,Bfb*Ac) */ spe_fm(f, term2R_reg, fbR_reg, constA_reg); spe_fm(f, term2G_reg, fbG_reg, constA_reg); @@ -721,9 +740,9 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_INV_CONST_COLOR: /* We need the optional constant color registers */ - setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); - setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); - setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + setup_const_register(f, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg, blend_color->color[2]); /* factor = (1-Rc,1-Gc,1-Bc), so term = (Rfb*(1-Rc),Gfb*(1-Gc),Bfb*(1-Bc)) * or term = (Rfb-Rfb*Rc, Gfb-Gfb*Gc, Bfb-Bfb*Bc) * fnms(a,b,c,d) computes a = d - b*c @@ -734,9 +753,9 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_INV_CONST_ALPHA: /* We need the optional constant color registers */ - setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); - setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); - setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + setup_const_register(f, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg, blend_color->color[2]); /* factor = (1-Ac,1-Ac,1-Ac), so term = (Rfb*(1-Ac),Gfb*(1-Ac),Bfb*(1-Ac)) * or term = (Rfb-Rfb*Ac,Gfb-Gfb*Ac,Bfb-Bfb*Ac) * fnms(a,b,c,d) computes a = d - b*c @@ -806,7 +825,7 @@ gen_blend(const struct pipe_blend_state *blend, case PIPE_BLENDFACTOR_CONST_ALPHA: /* fall through */ case PIPE_BLENDFACTOR_CONST_COLOR: /* We need the optional constA_reg register */ - setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + setup_const_register(f, &constA_reg, blend_color->color[3]); /* factor = Ac, so term = Afb*Ac */ spe_fm(f, term2A_reg, fbA_reg, constA_reg); break; @@ -814,7 +833,7 @@ gen_blend(const struct pipe_blend_state *blend, case PIPE_BLENDFACTOR_INV_CONST_ALPHA: /* fall through */ case PIPE_BLENDFACTOR_INV_CONST_COLOR: /* We need the optional constA_reg register */ - setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + setup_const_register(f, &constA_reg, blend_color->color[3]); /* factor = 1-Ac, so term = Afb*(1-Ac) = Afb-Afb*Ac */ /* fnms(a,b,c,d) computes a = d - b*c */ spe_fnms(f, term2A_reg, fbA_reg, constA_reg, fbA_reg); @@ -910,11 +929,11 @@ gen_blend(const struct pipe_blend_state *blend, spe_release_register(f, tmp_reg); /* Free any optional registers that actually got used */ - release_const_register(f, &one_reg_set, one_reg); - release_const_register(f, &constR_reg_set, constR_reg); - release_const_register(f, &constG_reg_set, constG_reg); - release_const_register(f, &constB_reg_set, constB_reg); - release_const_register(f, &constA_reg_set, constA_reg); + release_const_register(f, one_reg); + release_const_register(f, constR_reg); + release_const_register(f, constG_reg); + release_const_register(f, constB_reg); + release_const_register(f, constA_reg); } @@ -1055,6 +1074,7 @@ gen_pack_colors(struct spe_function *f, spe_release_register(f, ba_reg); } + static void gen_colormask(struct spe_function *f, uint colormask, @@ -1067,10 +1087,10 @@ gen_colormask(struct spe_function *f, * are packed according to the given color format, not * necessarily RGBA... */ - unsigned int r_mask; - unsigned int g_mask; - unsigned int b_mask; - unsigned int a_mask; + uint r_mask; + uint g_mask; + uint b_mask; + uint a_mask; /* Calculate exactly where the bits for any particular color * end up, so we can mask them correctly. @@ -1111,11 +1131,13 @@ gen_colormask(struct spe_function *f, a_mask = 0; } - /* Get a temporary register to hold the mask that will be applied to the fragment */ + /* Get a temporary register to hold the mask that will be applied + * to the fragment + */ int colormask_reg = spe_allocate_available_register(f); - /* The actual mask we're going to use is an OR of the remaining R, G, B, and A - * masks. Load the result value into our temporary register. + /* The actual mask we're going to use is an OR of the remaining R, G, B, + * and A masks. Load the result value into our temporary register. */ spe_load_uint(f, colormask_reg, r_mask | g_mask | b_mask | a_mask); @@ -1135,7 +1157,9 @@ gen_colormask(struct spe_function *f, spe_release_register(f, colormask_reg); } -/* This function is annoyingly similar to gen_depth_test(), above, except + +/** + * This function is annoyingly similar to gen_depth_test(), above, except * that instead of comparing two varying values (i.e. fragment and buffer), * we're comparing a varying value with a static value. As such, we have * access to the Compare Immediate instructions where we don't in @@ -1146,16 +1170,20 @@ gen_colormask(struct spe_function *f, * * The return value in the stencil_pass_reg is a bitmask of valid * fragments that also passed the stencil test. The bitmask of valid - * fragments that failed would be found in (fragment_mask_reg & ~stencil_pass_reg). + * fragments that failed would be found in + * (fragment_mask_reg & ~stencil_pass_reg). */ static void -gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, - unsigned int stencil_max_value, - unsigned int fragment_mask_reg, unsigned int fbS_reg, - unsigned int stencil_pass_reg) +gen_stencil_test(struct spe_function *f, + const struct pipe_stencil_state *state, + uint stencil_max_value, + int fragment_mask_reg, + int fbS_reg, + int stencil_pass_reg) { - /* Generate code that puts the set of passing fragments into the stencil_pass_reg - * register, taking into account whether each fragment was active to begin with. + /* Generate code that puts the set of passing fragments into the + * stencil_pass_reg register, taking into account whether each fragment + * was active to begin with. */ switch (state->func) { case PIPE_FUNC_EQUAL: @@ -1166,9 +1194,10 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, } else { /* stencil_pass = fragment_mask & ((s&mask) == (reference&mask)) */ - unsigned int tmp_masked_stencil = spe_allocate_available_register(f); + uint tmp_masked_stencil = spe_allocate_available_register(f); spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->value_mask); - spe_compare_equal_uint(f, stencil_pass_reg, tmp_masked_stencil, state->value_mask & state->ref_value); + spe_compare_equal_uint(f, stencil_pass_reg, tmp_masked_stencil, + state->value_mask & state->ref_value); spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg); spe_release_register(f, tmp_masked_stencil); } @@ -1182,9 +1211,10 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, } else { /* stencil_pass = fragment_mask & ~((s&mask) == (reference&mask)) */ - unsigned int tmp_masked_stencil = spe_allocate_available_register(f); + int tmp_masked_stencil = spe_allocate_available_register(f); spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->value_mask); - spe_compare_equal_uint(f, stencil_pass_reg, tmp_masked_stencil, state->value_mask & state->ref_value); + spe_compare_equal_uint(f, stencil_pass_reg, tmp_masked_stencil, + state->value_mask & state->ref_value); spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg); spe_release_register(f, tmp_masked_stencil); } @@ -1198,9 +1228,10 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, } else { /* stencil_pass = fragment_mask & ((reference&mask) < (s & mask)) */ - unsigned int tmp_masked_stencil = spe_allocate_available_register(f); + int tmp_masked_stencil = spe_allocate_available_register(f); spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->value_mask); - spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil, state->value_mask & state->ref_value); + spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil, + state->value_mask & state->ref_value); spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg); spe_release_register(f, tmp_masked_stencil); } @@ -1214,7 +1245,7 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, * comparing directly. Compare Logical Greater Than Word (clgt) * treats its operands as unsigned - no sign extension. */ - unsigned int tmp_reg = spe_allocate_available_register(f); + int tmp_reg = spe_allocate_available_register(f); spe_load_uint(f, tmp_reg, state->ref_value); spe_clgt(f, stencil_pass_reg, tmp_reg, fbS_reg); spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg); @@ -1222,8 +1253,8 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, } else { /* stencil_pass = fragment_mask & ((reference&mask) > (s&mask)) */ - unsigned int tmp_reg = spe_allocate_available_register(f); - unsigned int tmp_masked_stencil = spe_allocate_available_register(f); + int tmp_reg = spe_allocate_available_register(f); + int tmp_masked_stencil = spe_allocate_available_register(f); spe_load_uint(f, tmp_reg, state->value_mask & state->ref_value); spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->value_mask); spe_clgt(f, stencil_pass_reg, tmp_reg, tmp_masked_stencil); @@ -1237,14 +1268,16 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, if (state->value_mask == stencil_max_value) { /* stencil_pass = fragment_mask & (reference >= s) * = fragment_mask & ~(s > reference) */ - spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg, state->ref_value); + spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg, + state->ref_value); spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg); } else { /* stencil_pass = fragment_mask & ~((s&mask) > (reference&mask)) */ - unsigned int tmp_masked_stencil = spe_allocate_available_register(f); + int tmp_masked_stencil = spe_allocate_available_register(f); spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->value_mask); - spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil, state->value_mask & state->ref_value); + spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil, + state->value_mask & state->ref_value); spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg); spe_release_register(f, tmp_masked_stencil); } @@ -1255,7 +1288,7 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, /* stencil_pass = fragment_mask & (reference <= s) ] * = fragment_mask & ~(reference > s) */ /* As above, we have to do this by loading a register */ - unsigned int tmp_reg = spe_allocate_available_register(f); + int tmp_reg = spe_allocate_available_register(f); spe_load_uint(f, tmp_reg, state->ref_value); spe_clgt(f, stencil_pass_reg, tmp_reg, fbS_reg); spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg); @@ -1263,8 +1296,8 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, } else { /* stencil_pass = fragment_mask & ~((reference&mask) > (s&mask)) */ - unsigned int tmp_reg = spe_allocate_available_register(f); - unsigned int tmp_masked_stencil = spe_allocate_available_register(f); + int tmp_reg = spe_allocate_available_register(f); + int tmp_masked_stencil = spe_allocate_available_register(f); spe_load_uint(f, tmp_reg, state->ref_value & state->value_mask); spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->value_mask); spe_clgt(f, stencil_pass_reg, tmp_reg, tmp_masked_stencil); @@ -1290,7 +1323,9 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, */ } -/* This function generates code that calculates a set of new stencil values + +/** + * This function generates code that calculates a set of new stencil values * given the earlier values and the operation to apply. It does not * apply any tests. It is intended to be called up to 3 times * (for the stencil fail operation, for the stencil pass-z fail operation, @@ -1302,9 +1337,12 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state, * in the stencil buffer - in other words, it should be usable as a mask. */ static void -gen_stencil_values(struct spe_function *f, unsigned int stencil_op, - unsigned int stencil_ref_value, unsigned int stencil_max_value, - unsigned int fbS_reg, unsigned int newS_reg) +gen_stencil_values(struct spe_function *f, + uint stencil_op, + uint stencil_ref_value, + uint stencil_max_value, + int fbS_reg, + int newS_reg) { /* The code below assumes that newS_reg and fbS_reg are not the same * register; if they can be, the calculations below will have to use @@ -1346,7 +1384,7 @@ gen_stencil_values(struct spe_function *f, unsigned int stencil_op, case PIPE_STENCIL_OP_INCR: { /* newS = (s == max ? max : s + 1) */ - unsigned int equals_reg = spe_allocate_available_register(f); + int equals_reg = spe_allocate_available_register(f); spe_compare_equal_uint(f, equals_reg, fbS_reg, stencil_max_value); /* Add Word Immediate computes rT = rA + 10-bit signed immediate */ @@ -1359,7 +1397,7 @@ gen_stencil_values(struct spe_function *f, unsigned int stencil_op, } case PIPE_STENCIL_OP_DECR: { /* newS = (s == 0 ? 0 : s - 1) */ - unsigned int equals_reg = spe_allocate_available_register(f); + int equals_reg = spe_allocate_available_register(f); spe_compare_equal_uint(f, equals_reg, fbS_reg, 0); /* Add Word Immediate with a (-1) value works */ @@ -1397,7 +1435,8 @@ gen_stencil_values(struct spe_function *f, unsigned int stencil_op, } -/* This function generates code to get all the necessary possible +/** + * This function generates code to get all the necessary possible * stencil values. For each of the output registers (fail_reg, * zfail_reg, and zpass_reg), it either allocates a new register * and calculates a new set of values based on the stencil operation, @@ -1412,13 +1451,15 @@ gen_stencil_values(struct spe_function *f, unsigned int stencil_op, * and released by the corresponding spe_release_register_set() call. */ static void -gen_get_stencil_values(struct spe_function *f, const struct pipe_stencil_state *stencil, - const unsigned int depth_enabled, - unsigned int fbS_reg, - unsigned int *fail_reg, unsigned int *zfail_reg, - unsigned int *zpass_reg) +gen_get_stencil_values(struct spe_function *f, + const struct pipe_stencil_state *stencil, + const uint depth_enabled, + int fbS_reg, + int *fail_reg, + int *zfail_reg, + int *zpass_reg) { - unsigned zfail_op; + uint zfail_op; /* Stenciling had better be enabled here */ ASSERT(stencil->enabled); @@ -1480,7 +1521,8 @@ gen_get_stencil_values(struct spe_function *f, const struct pipe_stencil_state * } } -/* Note that fbZ_reg may *not* be set on entry, if in fact +/** + * Note that fbZ_reg may *not* be set on entry, if in fact * the depth test is not enabled. This function must not use * the register if depth is not enabled. */ @@ -1494,7 +1536,7 @@ gen_stencil_depth_test(struct spe_function *f, /* True if we've generated code that could require writeback to the * depth and/or stencil buffers */ - boolean modified_buffers = false; + boolean modified_buffers = FALSE; boolean need_to_calculate_stencil_values; boolean need_to_writemask_stencil_values; @@ -1504,11 +1546,11 @@ gen_stencil_depth_test(struct spe_function *f, /* Registers. We may or may not actually allocate these, depending * on whether the state values indicate that we need them. */ - unsigned int stencil_pass_reg, stencil_fail_reg; - unsigned int stencil_fail_values, stencil_pass_depth_fail_values, stencil_pass_depth_pass_values; - unsigned int stencil_writemask_reg; - unsigned int zmask_reg; - unsigned int newS_reg; + int stencil_pass_reg, stencil_fail_reg; + int stencil_fail_values, stencil_pass_depth_fail_values, stencil_pass_depth_pass_values; + int stencil_writemask_reg; + int zmask_reg; + int newS_reg; /* Stenciling is quite complex: up to six different configurable stencil * operations/calculations can be required (three each for front-facing @@ -1555,27 +1597,27 @@ gen_stencil_depth_test(struct spe_function *f, if (stencil->fail_op == PIPE_STENCIL_OP_KEEP && stencil->zfail_op == PIPE_STENCIL_OP_KEEP && stencil->zpass_op == PIPE_STENCIL_OP_KEEP) { - need_to_calculate_stencil_values = false; - need_to_writemask_stencil_values = false; + need_to_calculate_stencil_values = FALSE; + need_to_writemask_stencil_values = FALSE; } else if (stencil->write_mask == 0x0) { /* All changes are writemasked out, so no need to calculate * what those changes might be, and no need to write anything back. */ - need_to_calculate_stencil_values = false; - need_to_writemask_stencil_values = false; + need_to_calculate_stencil_values = FALSE; + need_to_writemask_stencil_values = FALSE; } else if (stencil->write_mask == 0xff) { /* Still trivial, but a little less so. We need to write the stencil * values, but we don't need to mask them. */ - need_to_calculate_stencil_values = true; - need_to_writemask_stencil_values = false; + need_to_calculate_stencil_values = TRUE; + need_to_writemask_stencil_values = FALSE; } else { /* The general case: calculate, mask, and write */ - need_to_calculate_stencil_values = true; - need_to_writemask_stencil_values = true; + need_to_calculate_stencil_values = TRUE; + need_to_writemask_stencil_values = TRUE; /* While we're here, generate code that calculates what the * writemask should be. If backface stenciling is enabled, @@ -1633,7 +1675,9 @@ gen_stencil_depth_test(struct spe_function *f, * This function will allocate a variant number of registers that * will be released as part of the register set. */ - spe_comment(f, 0, facing == CELL_FACING_FRONT ? "Computing front-facing stencil values" : "Computing back-facing stencil values"); + spe_comment(f, 0, facing == CELL_FACING_FRONT + ? "Computing front-facing stencil values" + : "Computing back-facing stencil values"); gen_get_stencil_values(f, stencil, dsa->depth.enabled, fbS_reg, &stencil_fail_values, &stencil_pass_depth_fail_values, &stencil_pass_depth_pass_values); @@ -1652,7 +1696,8 @@ gen_stencil_depth_test(struct spe_function *f, if (dsa->depth.enabled) { spe_comment(f, 0, "Running stencil depth test"); zmask_reg = spe_allocate_available_register(f); - modified_buffers |= gen_depth_test(f, dsa, mask_reg, fragZ_reg, fbZ_reg, zmask_reg); + modified_buffers |= gen_depth_test(f, dsa, mask_reg, fragZ_reg, + fbZ_reg, zmask_reg); } if (need_to_calculate_stencil_values) { @@ -1675,7 +1720,7 @@ gen_stencil_depth_test(struct spe_function *f, if (stencil_fail_values != fbS_reg) { spe_comment(f, 0, "Loading stencil fail values"); spe_selb(f, newS_reg, newS_reg, stencil_fail_values, stencil_fail_reg); - modified_buffers = true; + modified_buffers = TRUE; } /* Same for the stencil pass/depth fail values. If this calculation @@ -1689,14 +1734,17 @@ gen_stencil_depth_test(struct spe_function *f, * depth passing mask. Note that zmask_reg *must* have been * set above if we're here. */ - unsigned int stencil_pass_depth_fail_mask = spe_allocate_available_register(f); + uint stencil_pass_depth_fail_mask = + spe_allocate_available_register(f); + spe_comment(f, 0, "Loading stencil pass/depth fail values"); spe_andc(f, stencil_pass_depth_fail_mask, stencil_pass_reg, zmask_reg); - spe_selb(f, newS_reg, newS_reg, stencil_pass_depth_fail_values, stencil_pass_depth_fail_mask); + spe_selb(f, newS_reg, newS_reg, stencil_pass_depth_fail_values, + stencil_pass_depth_fail_mask); spe_release_register(f, stencil_pass_depth_fail_mask); - modified_buffers = true; + modified_buffers = TRUE; } /* Same for the stencil pass/depth pass mask. Note that we @@ -1707,7 +1755,7 @@ gen_stencil_depth_test(struct spe_function *f, */ if (stencil_pass_depth_pass_values != fbS_reg) { if (dsa->depth.enabled) { - unsigned int stencil_pass_depth_pass_mask = spe_allocate_available_register(f); + uint stencil_pass_depth_pass_mask = spe_allocate_available_register(f); /* We'll need a separate register */ spe_comment(f, 0, "Loading stencil pass/depth pass values"); spe_and(f, stencil_pass_depth_pass_mask, stencil_pass_reg, zmask_reg); @@ -1719,7 +1767,7 @@ gen_stencil_depth_test(struct spe_function *f, spe_comment(f, 0, "Loading stencil pass values"); spe_selb(f, newS_reg, newS_reg, stencil_pass_depth_pass_values, stencil_pass_reg); } - modified_buffers = true; + modified_buffers = TRUE; } /* Almost done. If we need to writemask, do it now, leaving the @@ -1749,7 +1797,7 @@ gen_stencil_depth_test(struct spe_function *f, spe_comment(f, 0, "Releasing stencil register set"); spe_release_register_set(f); - /* Return true if we could have modified the stencil and/or + /* Return TRUE if we could have modified the stencil and/or * depth buffers. */ return modified_buffers; @@ -1757,6 +1805,200 @@ gen_stencil_depth_test(struct spe_function *f, /** + * Generate depth and/or stencil test code. + * \param cell context + * \param dsa depth/stencil/alpha state + * \param f spe function to emit + * \param facing either CELL_FACING_FRONT or CELL_FACING_BACK + * \param mask_reg register containing the pixel alive/dead mask + * \param depth_tile_reg register containing address of z/stencil tile + * \param quad_offset_reg offset to quad from start of tile + * \param fragZ_reg register containg fragment Z values + */ +static void +gen_depth_stencil(struct cell_context *cell, + const struct pipe_depth_stencil_alpha_state *dsa, + struct spe_function *f, + uint facing, + int mask_reg, + int depth_tile_reg, + int quad_offset_reg, + int fragZ_reg) + +{ + const enum pipe_format zs_format = cell->framebuffer.zsbuf->format; + boolean write_depth_stencil; + + /* framebuffer's combined z/stencil values register */ + int fbZS_reg = spe_allocate_available_register(f); + + /* Framebufer Z values register */ + int fbZ_reg = spe_allocate_available_register(f); + + /* Framebuffer stencil values register (may not be used) */ + int fbS_reg = spe_allocate_available_register(f); + + /* 24-bit mask register (may not be used) */ + int zmask_reg = spe_allocate_available_register(f); + + /** + * The following code: + * 1. fetch quad of packed Z/S values from the framebuffer tile. + * 2. extract the separate the Z and S values from packed values + * 3. convert fragment Z values from float in [0,1] to 32/24/16-bit ints + * + * The instructions for doing this are interleaved for better performance. + */ + spe_comment(f, 0, "Fetch Z/stencil quad from tile"); + + switch(zs_format) { + case PIPE_FORMAT_S8Z24_UNORM: /* fall through */ + case PIPE_FORMAT_X8Z24_UNORM: + /* prepare mask to extract Z vals from ZS vals */ + spe_load_uint(f, zmask_reg, 0x00ffffff); + + /* convert fragment Z from [0,1] to 32-bit ints */ + spe_cfltu(f, fragZ_reg, fragZ_reg, 32); + + /* Load: fbZS_reg = memory[depth_tile_reg + offset_reg] */ + spe_lqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg); + + /* right shift 32-bit fragment Z to 24 bits */ + spe_rotmi(f, fragZ_reg, fragZ_reg, -8); + + /* extract 24-bit Z values from ZS values by masking */ + spe_and(f, fbZ_reg, fbZS_reg, zmask_reg); + + /* extract 8-bit stencil values by shifting */ + spe_rotmi(f, fbS_reg, fbZS_reg, -24); + break; + + case PIPE_FORMAT_Z24S8_UNORM: /* fall through */ + case PIPE_FORMAT_Z24X8_UNORM: + /* convert fragment Z from [0,1] to 32-bit ints */ + spe_cfltu(f, fragZ_reg, fragZ_reg, 32); + + /* Load: fbZS_reg = memory[depth_tile_reg + offset_reg] */ + spe_lqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg); + + /* right shift 32-bit fragment Z to 24 bits */ + spe_rotmi(f, fragZ_reg, fragZ_reg, -8); + + /* extract 24-bit Z values from ZS values by shifting */ + spe_rotmi(f, fbZ_reg, fbZS_reg, -8); + + /* extract 8-bit stencil values by masking */ + spe_and_uint(f, fbS_reg, fbZS_reg, 0x000000ff); + break; + + case PIPE_FORMAT_Z32_UNORM: + /* Load: fbZ_reg = memory[depth_tile_reg + offset_reg] */ + spe_lqx(f, fbZ_reg, depth_tile_reg, quad_offset_reg); + + /* convert fragment Z from [0,1] to 32-bit ints */ + spe_cfltu(f, fragZ_reg, fragZ_reg, 32); + + /* No stencil, so can't do anything there */ + break; + + case PIPE_FORMAT_Z16_UNORM: + /* XXX This code for 16bpp Z is broken! */ + + /* Load: fbZS_reg = memory[depth_tile_reg + offset_reg] */ + spe_lqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg); + + /* Copy over 4 32-bit values */ + spe_move(f, fbZ_reg, fbZS_reg); + + /* convert Z from [0,1] to 16-bit ints */ + spe_cfltu(f, fragZ_reg, fragZ_reg, 32); + spe_rotmi(f, fragZ_reg, fragZ_reg, -16); + /* No stencil */ + break; + + default: + ASSERT(0); /* invalid format */ + } + + /* If stencil is enabled, use the stencil-specific code + * generator to generate both the stencil and depth (if needed) + * tests. Otherwise, if only depth is enabled, generate + * a quick depth test. The test generators themselves will + * report back whether the depth/stencil buffer has to be + * written back. + */ + if (dsa->stencil[0].enabled) { + /* This will perform the stencil and depth tests, and update + * the mask_reg, fbZ_reg, and fbS_reg as required by the + * tests. + */ + ASSERT(fbS_reg >= 0); + spe_comment(f, 0, "Perform stencil test"); + + /* Note that fbZ_reg may not be set on entry, if stenciling + * is enabled but there's no Z-buffer. The + * gen_stencil_depth_test() function must ignore the + * fbZ_reg register if depth is not enabled. + */ + write_depth_stencil = gen_stencil_depth_test(f, dsa, facing, + mask_reg, fragZ_reg, + fbZ_reg, fbS_reg); + } + else if (dsa->depth.enabled) { + int zmask_reg = spe_allocate_available_register(f); + ASSERT(fbZ_reg >= 0); + spe_comment(f, 0, "Perform depth test"); + write_depth_stencil = gen_depth_test(f, dsa, mask_reg, fragZ_reg, + fbZ_reg, zmask_reg); + spe_release_register(f, zmask_reg); + } + else { + write_depth_stencil = FALSE; + } + + if (write_depth_stencil) { + /* Merge latest Z and Stencil values into fbZS_reg. + * fbZ_reg has four Z vals in bits [23..0] or bits [15..0]. + * fbS_reg has four 8-bit Z values in bits [7..0]. + */ + spe_comment(f, 0, "Store quad's depth/stencil values in tile"); + if (zs_format == PIPE_FORMAT_S8Z24_UNORM || + zs_format == PIPE_FORMAT_X8Z24_UNORM) { + spe_shli(f, fbS_reg, fbS_reg, 24); /* fbS = fbS << 24 */ + spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */ + } + else if (zs_format == PIPE_FORMAT_Z24S8_UNORM || + zs_format == PIPE_FORMAT_Z24X8_UNORM) { + spe_shli(f, fbZ_reg, fbZ_reg, 8); /* fbZ = fbZ << 8 */ + spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */ + } + else if (zs_format == PIPE_FORMAT_Z32_UNORM) { + spe_move(f, fbZS_reg, fbZ_reg); /* fbZS = fbZ */ + } + else if (zs_format == PIPE_FORMAT_Z16_UNORM) { + spe_move(f, fbZS_reg, fbZ_reg); /* fbZS = fbZ */ + } + else if (zs_format == PIPE_FORMAT_S8_UNORM) { + ASSERT(0); /* XXX to do */ + } + else { + ASSERT(0); /* bad zs_format */ + } + + /* Store: memory[depth_tile_reg + quad_offset_reg] = fbZS */ + spe_stqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg); + } + + /* Don't need these any more */ + spe_release_register(f, fbZS_reg); + spe_release_register(f, fbZ_reg); + spe_release_register(f, fbS_reg); + spe_release_register(f, zmask_reg); +} + + + +/** * Generate SPE code to implement the fragment operations (alpha test, * depth test, stencil test, blending, colormask, and final * framebuffer write) as specified by the current context state. @@ -1782,7 +2024,9 @@ gen_stencil_depth_test(struct spe_function *f, * the fragment ops appended. */ void -cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct spe_function *f) +cell_gen_fragment_function(struct cell_context *cell, + const uint facing, + struct spe_function *f) { const struct pipe_depth_stencil_alpha_state *dsa = cell->depth_stencil; const struct pipe_blend_state *blend = cell->blend; @@ -1809,12 +2053,13 @@ cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct int quad_offset_reg; int fbRGBA_reg; /**< framebuffer's RGBA colors for quad */ - int fbZS_reg; /**< framebuffer's combined z/stencil values for quad */ if (cell->debug_flags & CELL_DEBUG_ASM) { - spe_print_code(f, true); + spe_print_code(f, TRUE); spe_indent(f, 8); - spe_comment(f, -4, facing == CELL_FACING_FRONT ? "Begin front-facing per-fragment ops": "Begin back-facing per-fragment ops"); + spe_comment(f, -4, facing == CELL_FACING_FRONT + ? "Begin front-facing per-fragment ops" + : "Begin back-facing per-fragment ops"); } spe_allocate_register(f, x_reg); @@ -1830,7 +2075,6 @@ cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct quad_offset_reg = spe_allocate_available_register(f); fbRGBA_reg = spe_allocate_available_register(f); - fbZS_reg = spe_allocate_available_register(f); /* compute offset of quad from start of tile, in bytes */ { @@ -1855,177 +2099,14 @@ cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct gen_alpha_test(dsa, f, mask_reg, fragA_reg); } - /* If we need the stencil buffers (because one- or two-sided stencil is - * enabled) or the depth buffer (because the depth test is enabled), - * go grab them. Note that if either one- or two-sided stencil is - * enabled, dsa->stencil[0].enabled will be true. - */ + /* generate depth and/or stencil test code */ if (dsa->depth.enabled || dsa->stencil[0].enabled) { - const enum pipe_format zs_format = cell->framebuffer.zsbuf->format; - boolean write_depth_stencil; - - /* We may or may not need to allocate a register for Z or stencil values */ - boolean fbS_reg_set = false, fbZ_reg_set = false; - unsigned int fbS_reg, fbZ_reg = 0; - - spe_comment(f, 0, "Fetching Z/stencil quad from tile"); - - /* fetch quad of depth/stencil values from tile at (x,y) */ - /* Load: fbZS_reg = memory[depth_tile_reg + offset_reg] */ - /* XXX Not sure this is allowed if we've only got a 16-bit Z buffer... */ - spe_lqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg); - - /* From the Z/stencil buffer format, pull out the bits we need for - * Z and/or stencil. We'll also convert the incoming fragment Z - * value in fragZ_reg from a floating point value in [0.0..1.0] to - * an unsigned integer value with the appropriate resolution. - * Note that even if depth or stencil is *not* enabled, if it's - * present in the buffer, we pull it out and put it back later; - * otherwise, we can inadvertently destroy the contents of - * buffers we're not supposed to touch (e.g., if the user is - * clearing the depth buffer but not the stencil buffer, a - * quad of constant depth is drawn over the surface; the stencil - * buffer must be maintained). - */ - switch(zs_format) { - - case PIPE_FORMAT_S8Z24_UNORM: /* fall through */ - case PIPE_FORMAT_X8Z24_UNORM: - /* Pull out both Z and stencil */ - setup_optional_register(f, &fbZ_reg_set, &fbZ_reg); - setup_optional_register(f, &fbS_reg_set, &fbS_reg); - - /* four 24-bit Z values in the low-order bits */ - spe_and_uint(f, fbZ_reg, fbZS_reg, 0x00ffffff); - - /* Incoming fragZ_reg value is a float in 0.0...1.0; convert - * to a 24-bit unsigned integer - */ - spe_cfltu(f, fragZ_reg, fragZ_reg, 32); - spe_rotmi(f, fragZ_reg, fragZ_reg, -8); - - /* four 8-bit stencil values in the high-order bits */ - spe_rotmi(f, fbS_reg, fbZS_reg, -24); - break; - - case PIPE_FORMAT_Z24S8_UNORM: /* fall through */ - case PIPE_FORMAT_Z24X8_UNORM: - setup_optional_register(f, &fbZ_reg_set, &fbZ_reg); - setup_optional_register(f, &fbS_reg_set, &fbS_reg); - - /* shift by 8 to get the upper 24-bit values */ - spe_rotmi(f, fbS_reg, fbZS_reg, -8); - - /* Incoming fragZ_reg value is a float in 0.0...1.0; convert - * to a 24-bit unsigned integer - */ - spe_cfltu(f, fragZ_reg, fragZ_reg, 32); - spe_rotmi(f, fragZ_reg, fragZ_reg, -8); - - /* 8-bit stencil in the low-order bits - mask them out */ - spe_and_uint(f, fbS_reg, fbZS_reg, 0x000000ff); - break; - - case PIPE_FORMAT_Z32_UNORM: - setup_optional_register(f, &fbZ_reg_set, &fbZ_reg); - /* Copy over 4 32-bit values */ - spe_move(f, fbZ_reg, fbZS_reg); - - /* Incoming fragZ_reg value is a float in 0.0...1.0; convert - * to a 32-bit unsigned integer - */ - spe_cfltu(f, fragZ_reg, fragZ_reg, 32); - /* No stencil, so can't do anything there */ - break; - - case PIPE_FORMAT_Z16_UNORM: - /* XXX Not sure this is correct, but it was here before, so we're - * going with it for now - */ - setup_optional_register(f, &fbZ_reg_set, &fbZ_reg); - /* Copy over 4 32-bit values */ - spe_move(f, fbZ_reg, fbZS_reg); - - /* Incoming fragZ_reg value is a float in 0.0...1.0; convert - * to a 16-bit unsigned integer - */ - spe_cfltu(f, fragZ_reg, fragZ_reg, 32); - spe_rotmi(f, fragZ_reg, fragZ_reg, -16); - /* No stencil */ - - default: - ASSERT(0); /* invalid format */ - } - - /* If stencil is enabled, use the stencil-specific code - * generator to generate both the stencil and depth (if needed) - * tests. Otherwise, if only depth is enabled, generate - * a quick depth test. The test generators themselves will - * report back whether the depth/stencil buffer has to be - * written back. - */ - if (dsa->stencil[0].enabled) { - /* This will perform the stencil and depth tests, and update - * the mask_reg, fbZ_reg, and fbS_reg as required by the - * tests. - */ - ASSERT(fbS_reg_set); - spe_comment(f, 0, "Perform stencil test"); - - /* Note that fbZ_reg may not be set on entry, if stenciling - * is enabled but there's no Z-buffer. The - * gen_stencil_depth_test() function must ignore the - * fbZ_reg register if depth is not enabled. - */ - write_depth_stencil = gen_stencil_depth_test(f, dsa, facing, mask_reg, fragZ_reg, fbZ_reg, fbS_reg); - } - else if (dsa->depth.enabled) { - int zmask_reg = spe_allocate_available_register(f); - ASSERT(fbZ_reg_set); - spe_comment(f, 0, "Perform depth test"); - write_depth_stencil = gen_depth_test(f, dsa, mask_reg, fragZ_reg, fbZ_reg, zmask_reg); - spe_release_register(f, zmask_reg); - } - else { - write_depth_stencil = false; - } - - if (write_depth_stencil) { - /* Merge latest Z and Stencil values into fbZS_reg. - * fbZ_reg has four Z vals in bits [23..0] or bits [15..0]. - * fbS_reg has four 8-bit Z values in bits [7..0]. - */ - spe_comment(f, 0, "Store quad's depth/stencil values in tile"); - if (zs_format == PIPE_FORMAT_S8Z24_UNORM || - zs_format == PIPE_FORMAT_X8Z24_UNORM) { - spe_shli(f, fbS_reg, fbS_reg, 24); /* fbS = fbS << 24 */ - spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */ - } - else if (zs_format == PIPE_FORMAT_Z24S8_UNORM || - zs_format == PIPE_FORMAT_Z24X8_UNORM) { - spe_shli(f, fbZ_reg, fbZ_reg, 8); /* fbZ = fbZ << 8 */ - spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */ - } - else if (zs_format == PIPE_FORMAT_Z32_UNORM) { - spe_move(f, fbZS_reg, fbZ_reg); /* fbZS = fbZ */ - } - else if (zs_format == PIPE_FORMAT_Z16_UNORM) { - spe_move(f, fbZS_reg, fbZ_reg); /* fbZS = fbZ */ - } - else if (zs_format == PIPE_FORMAT_S8_UNORM) { - ASSERT(0); /* XXX to do */ - } - else { - ASSERT(0); /* bad zs_format */ - } - - /* Store: memory[depth_tile_reg + quad_offset_reg] = fbZS */ - spe_stqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg); - } - - /* Don't need these any more */ - release_optional_register(f, &fbZ_reg_set, fbZ_reg); - release_optional_register(f, &fbS_reg_set, fbS_reg); + gen_depth_stencil(cell, dsa, f, + facing, + mask_reg, + depth_tile_reg, + quad_offset_reg, + fragZ_reg); } /* Get framebuffer quad/colors. We'll need these for blending, @@ -2089,7 +2170,6 @@ cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct spe_bi(f, SPE_REG_RA, 0, 0); /* return from function call */ spe_release_register(f, fbRGBA_reg); - spe_release_register(f, fbZS_reg); spe_release_register(f, quad_offset_reg); if (cell->debug_flags & CELL_DEBUG_ASM) { diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index 0a0af81f53f..39b85faeb86 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -133,7 +133,7 @@ lookup_fragment_ops(struct cell_context *cell) */ ops = CALLOC_VARIANT_LENGTH_STRUCT(cell_command_fragment_ops, total_code_size); /* populate the new cell_command_fragment_ops object */ - ops->opcode = CELL_CMD_STATE_FRAGMENT_OPS; + 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); @@ -178,10 +178,10 @@ static void emit_state_cmd(struct cell_context *cell, uint cmd, const void *state, uint state_size) { - uint64_t *dst = (uint64_t *) - cell_batch_alloc(cell, ROUNDUP8(sizeof(uint64_t) + state_size)); + uint32_t *dst = (uint32_t *) + cell_batch_alloc16(cell, ROUNDUP16(sizeof(opcode_t) + state_size)); *dst = cmd; - memcpy(dst + 1, state, state_size); + memcpy(dst + 4, state, state_size); } @@ -195,9 +195,10 @@ 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_alloc(cell, sizeof(*fb)); - fb->opcode = CELL_CMD_STATE_FRAMEBUFFER; + = 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; @@ -211,17 +212,19 @@ cell_emit_state(struct cell_context *cell) } if (cell->dirty & (CELL_NEW_RASTERIZER)) { + STATIC_ASSERT(sizeof(struct cell_command_rasterizer) % 16 == 0); struct cell_command_rasterizer *rast = - cell_batch_alloc(cell, sizeof(*rast)); - rast->opcode = CELL_CMD_STATE_RASTERIZER; + 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_alloc(cell, sizeof(*fp)); - fp->opcode = CELL_CMD_STATE_FRAGMENT_PROGRAM; + = 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); @@ -238,14 +241,14 @@ cell_emit_state(struct cell_context *cell) const uint shader = PIPE_SHADER_FRAGMENT; const uint num_const = cell->constants[shader].size / sizeof(float); uint i, j; - float *buf = cell_batch_alloc(cell, 16 + num_const * sizeof(float)); - uint64_t *ibuf = (uint64_t *) buf; + float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float))); + uint32_t *ibuf = (uint32_t *) buf; const float *constants = pipe_buffer_map(cell->pipe.screen, cell->constants[shader].buffer, PIPE_BUFFER_USAGE_CPU_READ); ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS; - ibuf[1] = num_const; - j = 4; + ibuf[4] = num_const; + j = 8; for (i = 0; i < num_const; i++) { buf[j++] = constants[i]; } @@ -258,7 +261,7 @@ cell_emit_state(struct cell_context *cell) 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_alloc(cell, sizeof(*fops_cmd) + fops->total_code_size); + fops_cmd = cell_batch_alloc16(cell, ROUNDUP16(sizeof(*fops_cmd) + fops->total_code_size)); memcpy(fops_cmd, fops, sizeof(*fops) + fops->total_code_size); } @@ -267,9 +270,10 @@ cell_emit_state(struct cell_context *cell) 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_alloc(cell, sizeof(*sampler)); - sampler->opcode = CELL_CMD_STATE_SAMPLER; + = cell_batch_alloc16(cell, sizeof(*sampler)); + sampler->opcode[0] = CELL_CMD_STATE_SAMPLER; sampler->unit = i; sampler->state = *cell->sampler[i]; } @@ -282,9 +286,10 @@ cell_emit_state(struct cell_context *cell) 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 - = cell_batch_alloc(cell, sizeof(*texture)); - texture->opcode = CELL_CMD_STATE_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]) { uint level; diff --git a/src/gallium/drivers/cell/ppu/cell_vbuf.c b/src/gallium/drivers/cell/ppu/cell_vbuf.c index 65ba51b6bb2..ab54e796895 100644 --- a/src/gallium/drivers/cell/ppu/cell_vbuf.c +++ b/src/gallium/drivers/cell/ppu/cell_vbuf.c @@ -116,10 +116,11 @@ cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices, /* 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_alloc(cell, sizeof(struct cell_command_release_verts)); - release->opcode = CELL_CMD_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; } @@ -210,15 +211,16 @@ cell_vbuf_draw(struct vbuf_render *vbr, /* build/insert batch RENDER command */ { - const uint index_bytes = ROUNDUP8(nr_indices * 2); - const uint vertex_bytes = nr_vertices * 4 * cell->vertex_info.size; + 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_alloc(cell, batch_size); + cell_batch_alloc16(cell, batch_size); - render->opcode = CELL_CMD_RENDER; + render->opcode[0] = CELL_CMD_RENDER; render->prim_type = cvbr->prim; render->num_indexes = nr_indices; @@ -236,7 +238,7 @@ cell_vbuf_draw(struct vbuf_render *vbr, min_index == 0 && vertex_bytes + 16 <= cell_batch_free_space(cell)) { /* vertex data inlined, after indices, at 16-byte boundary */ - void *dst = cell_batch_alloc_aligned(cell, vertex_bytes, 16); + void *dst = cell_batch_alloc16(cell, vertex_bytes); memcpy(dst, vertices, vertex_bytes); render->inline_verts = TRUE; render->vertex_buf = ~0; diff --git a/src/gallium/drivers/cell/spu/spu_command.c b/src/gallium/drivers/cell/spu/spu_command.c index 8500d19754e..5c0179d9546 100644 --- a/src/gallium/drivers/cell/spu/spu_command.c +++ b/src/gallium/drivers/cell/spu/spu_command.c @@ -292,10 +292,10 @@ cmd_state_fragment_program(const struct cell_command_fragment_program *fp) static uint -cmd_state_fs_constants(const uint64_t *buffer, uint pos) +cmd_state_fs_constants(const qword *buffer, uint pos) { - const uint num_const = buffer[pos + 1]; - const float *constants = (const float *) &buffer[pos + 2]; + 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); @@ -306,8 +306,8 @@ cmd_state_fs_constants(const uint64_t *buffer, uint pos) spu.constants[i] = spu_splats(constants[i]); } - /* return new buffer pos (in 8-byte words) */ - return pos + 2 + num_const / 2; + /* return new buffer pos (in 16-byte words) */ + return pos + 2 + (ROUNDUP16(num_const * sizeof(float)) / 16); } @@ -547,8 +547,8 @@ cmd_batch(uint opcode) { const uint buf = (opcode >> 8) & 0xff; uint size = (opcode >> 16); - uint64_t buffer[CELL_BUFFER_SIZE / 8] ALIGN16_ATTRIB; - const unsigned usize = size / sizeof(buffer[0]); + qword buffer[CELL_BUFFER_SIZE / 16] ALIGN16_ATTRIB; + const unsigned usize = ROUNDUP16(size) / sizeof(buffer[0]); uint pos; D_PRINTF(CELL_DEBUG_CMD, "BATCH buffer %u, len %u, from %p\n", @@ -578,7 +578,7 @@ cmd_batch(uint opcode) * Loop over commands in the batch buffer */ for (pos = 0; pos < usize; /* no incr */) { - switch (buffer[pos]) { + switch (si_to_uint(buffer[pos])) { /* * rendering commands */ @@ -587,7 +587,7 @@ cmd_batch(uint opcode) struct cell_command_clear_surface *clr = (struct cell_command_clear_surface *) &buffer[pos]; cmd_clear_surface(clr); - pos += sizeof(*clr) / 8; + pos += sizeof(*clr) / 16; } break; case CELL_CMD_RENDER: @@ -596,7 +596,7 @@ cmd_batch(uint opcode) = (struct cell_command_render *) &buffer[pos]; uint pos_incr; cmd_render(render, &pos_incr); - pos += pos_incr; + pos += ((pos_incr+1)&~1) / 2; // should 'fix' cmd_render return } break; /* @@ -607,7 +607,7 @@ cmd_batch(uint opcode) struct cell_command_framebuffer *fb = (struct cell_command_framebuffer *) &buffer[pos]; cmd_state_framebuffer(fb); - pos += sizeof(*fb) / 8; + pos += sizeof(*fb) / 16; } break; case CELL_CMD_STATE_FRAGMENT_OPS: @@ -616,7 +616,7 @@ cmd_batch(uint opcode) = (struct cell_command_fragment_ops *) &buffer[pos]; cmd_state_fragment_ops(fops); /* This is a variant-sized command */ - pos += (sizeof(*fops) + fops->total_code_size)/ 8; + pos += ROUNDUP16(sizeof(*fops) + fops->total_code_size) / 16; } break; case CELL_CMD_STATE_FRAGMENT_PROGRAM: @@ -624,7 +624,7 @@ cmd_batch(uint opcode) struct cell_command_fragment_program *fp = (struct cell_command_fragment_program *) &buffer[pos]; cmd_state_fragment_program(fp); - pos += sizeof(*fp) / 8; + pos += sizeof(*fp) / 16; } break; case CELL_CMD_STATE_FS_CONSTANTS: @@ -635,7 +635,7 @@ cmd_batch(uint opcode) struct cell_command_rasterizer *rast = (struct cell_command_rasterizer *) &buffer[pos]; spu.rasterizer = rast->rasterizer; - pos += sizeof(*rast) / 8; + pos += sizeof(*rast) / 16; } break; case CELL_CMD_STATE_SAMPLER: @@ -643,7 +643,7 @@ cmd_batch(uint opcode) struct cell_command_sampler *sampler = (struct cell_command_sampler *) &buffer[pos]; cmd_state_sampler(sampler); - pos += sizeof(*sampler) / 8; + pos += sizeof(*sampler) / 16; } break; case CELL_CMD_STATE_TEXTURE: @@ -651,37 +651,37 @@ cmd_batch(uint opcode) struct cell_command_texture *texture = (struct cell_command_texture *) &buffer[pos]; cmd_state_texture(texture); - pos += sizeof(*texture) / 8; + pos += sizeof(*texture) / 16; } break; case CELL_CMD_STATE_VERTEX_INFO: cmd_state_vertex_info((struct vertex_info *) &buffer[pos+1]); - pos += (1 + ROUNDUP8(sizeof(struct vertex_info)) / 8); + 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 + ROUNDUP8(sizeof(struct pipe_viewport_state)) / 8); + pos += 1 + ROUNDUP16(sizeof(struct pipe_viewport_state)) / 16; break; case CELL_CMD_STATE_UNIFORMS: - draw.constants = (const float (*)[4]) (uintptr_t) buffer[pos + 1]; + 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 + ROUNDUP8(sizeof(struct cell_array_info)) / 8); + 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 + ROUNDUP8(sizeof(struct cell_shader_info)) / 8); + 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 + ROUNDUP8(sizeof(struct cell_attribute_fetch_code)) / 8); + pos += 1 + ROUNDUP16(sizeof(struct cell_attribute_fetch_code)) / 16; break; /* * misc commands @@ -695,7 +695,7 @@ cmd_batch(uint opcode) struct cell_command_fence *fence_cmd = (struct cell_command_fence *) &buffer[pos]; cmd_fence(fence_cmd); - pos += sizeof(*fence_cmd) / 8; + pos += sizeof(*fence_cmd) / 16; } break; case CELL_CMD_RELEASE_VERTS: @@ -703,7 +703,7 @@ cmd_batch(uint opcode) struct cell_command_release_verts *release = (struct cell_command_release_verts *) &buffer[pos]; cmd_release_verts(release); - pos += sizeof(*release) / 8; + pos += sizeof(*release) / 16; } break; case CELL_CMD_FLUSH_BUFFER_RANGE: { @@ -711,11 +711,11 @@ cmd_batch(uint opcode) &buffer[pos+1]; spu_dcache_mark_dirty((unsigned) br->base, br->size); - pos += (1 + ROUNDUP8(sizeof(struct cell_buffer_range)) / 8); + pos += 1 + ROUNDUP16(sizeof(struct cell_buffer_range)) / 16; break; } default: - printf("SPU %u: bad opcode: 0x%llx\n", spu.init.id, buffer[pos]); + printf("SPU %u: bad opcode: 0x%x\n", spu.init.id, si_to_uint(buffer[pos])); ASSERT(0); break; } diff --git a/src/gallium/drivers/cell/spu/spu_shuffle.h b/src/gallium/drivers/cell/spu/spu_shuffle.h index 7cbdb814d28..74f2a0b6d2e 100644 --- a/src/gallium/drivers/cell/spu/spu_shuffle.h +++ b/src/gallium/drivers/cell/spu/spu_shuffle.h @@ -171,7 +171,7 @@ SHUFFLE_PATTERN_16_##M##__, \ SHUFFLE_PATTERN_16_##N##__, \ SHUFFLE_PATTERN_16_##O##__, \ - SHUFFLE_PATTERN_16_##P + 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){ \ diff --git a/src/gallium/drivers/cell/spu/spu_tri.c b/src/gallium/drivers/cell/spu/spu_tri.c index 322be1252e9..0d9fcb99970 100644 --- a/src/gallium/drivers/cell/spu/spu_tri.c +++ b/src/gallium/drivers/cell/spu/spu_tri.c @@ -57,7 +57,7 @@ struct vertex_header { /* XXX fix this */ #undef CEILF -#define CEILF(X) ((float) (int) ((X) + 0.99999)) +#define CEILF(X) ((float) (int) ((X) + 0.99999f)) #define QUAD_TOP_LEFT 0 diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 0958bba334a..061a4c064b6 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -67,11 +67,18 @@ struct nv50_rasterizer_stateobj { struct nouveau_stateobj *so; }; +struct nv50_miptree_level { + struct pipe_buffer **image; + int *image_offset; + unsigned image_dirty_cpu[512/32]; + unsigned image_dirty_gpu[512/32]; +}; + struct nv50_miptree { struct pipe_texture base; struct pipe_buffer *buffer; - int *image_offset; + struct nv50_miptree_level level[PIPE_MAX_TEXTURE_LEVELS]; int image_nr; int total_size; }; @@ -84,7 +91,6 @@ nv50_miptree(struct pipe_texture *pt) struct nv50_surface { struct pipe_surface base; - struct pipe_buffer *untiled; }; static INLINE struct nv50_surface * @@ -186,4 +192,8 @@ extern boolean nv50_state_validate(struct nv50_context *nv50); /* nv50_tex.c */ extern void nv50_tex_validate(struct nv50_context *); +/* nv50_miptree.c */ +extern void nv50_miptree_sync(struct pipe_screen *, struct nv50_miptree *, + unsigned level, unsigned image); + #endif diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index 24973712324..63a23d06b89 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -27,14 +27,16 @@ #include "nv50_context.h" static struct pipe_texture * -nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) +nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) { struct pipe_winsys *ws = pscreen->winsys; struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree); - unsigned usage, width = pt->width[0], height = pt->height[0]; - int i; + struct pipe_texture *pt = &mt->base; + unsigned usage, width = tmp->width[0], height = tmp->height[0]; + unsigned depth = tmp->depth[0]; + int i, l; - mt->base = *pt; + mt->base = *tmp; mt->base.refcount = 1; mt->base.screen = pscreen; @@ -59,17 +61,38 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) mt->image_nr = 1; break; } - mt->image_offset = CALLOC(mt->image_nr, sizeof(int)); + + for (l = 0; l <= pt->last_level; l++) { + struct nv50_miptree_level *lvl = &mt->level[l]; + + pt->width[l] = width; + pt->height[l] = height; + pt->depth[l] = depth; + pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width); + pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); + + lvl->image_offset = CALLOC(mt->image_nr, sizeof(int)); + lvl->image = CALLOC(mt->image_nr, sizeof(struct pipe_buffer *)); + + width = MAX2(1, width >> 1); + height = MAX2(1, height >> 1); + depth = MAX2(1, depth >> 1); + } for (i = 0; i < mt->image_nr; i++) { - int image_size; + for (l = 0; l <= pt->last_level; l++) { + struct nv50_miptree_level *lvl = &mt->level[l]; + int size; + + size = align(pt->width[l], 8) * pt->block.size; + size = align(size, 64); + size *= align(pt->height[l], 8) * pt->block.size; - image_size = align(width, 8) * pt->block.size; - image_size = align(image_size, 64); - image_size *= align(height, 8) * pt->block.size; + lvl->image[i] = ws->buffer_create(ws, 256, 0, size); + lvl->image_offset[i] = mt->total_size; - mt->image_offset[i] = mt->total_size; - mt->total_size += image_size; + mt->total_size += size; + } } mt->buffer = ws->buffer_create(ws, 256, usage, mt->total_size); @@ -81,6 +104,24 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) return &mt->base; } +static INLINE void +mark_dirty(uint32_t *flags, unsigned image) +{ + flags[image / 32] |= (1 << (image % 32)); +} + +static INLINE void +mark_clean(uint32_t *flags, unsigned image) +{ + flags[image / 32] &= ~(1 << (image % 32)); +} + +static INLINE int +is_dirty(uint32_t *flags, unsigned image) +{ + return !!(flags[image / 32] & (1 << (image % 32))); +} + static void nv50_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt) { @@ -96,12 +137,86 @@ nv50_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt) } } +void +nv50_miptree_sync(struct pipe_screen *pscreen, struct nv50_miptree *mt, + unsigned level, unsigned image) +{ + struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws; + struct nv50_miptree_level *lvl = &mt->level[level]; + struct pipe_surface *dst, *src; + unsigned face = 0, zslice = 0; + + if (!is_dirty(lvl->image_dirty_cpu, image)) + return; + + if (mt->base.target == PIPE_TEXTURE_CUBE) + face = image; + else + if (mt->base.target == PIPE_TEXTURE_3D) + zslice = image; + + /* Mark as clean already - so we don't continually call this function + * trying to get a GPU_WRITE pipe_surface! + */ + mark_clean(lvl->image_dirty_cpu, image); + + /* Pretend we're doing CPU access so we get the backing pipe_surface + * and not a view into the larger miptree. + */ + src = pscreen->get_tex_surface(pscreen, &mt->base, face, level, zslice, + PIPE_BUFFER_USAGE_CPU_READ); + + /* Pretend we're only reading with the GPU so surface doesn't get marked + * as dirtied by the GPU. + */ + dst = pscreen->get_tex_surface(pscreen, &mt->base, face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + + nvws->surface_copy(nvws, dst, 0, 0, src, 0, 0, dst->width, dst->height); + + pscreen->tex_surface_release(pscreen, &dst); + pscreen->tex_surface_release(pscreen, &src); +} + +/* The reverse of the above */ +void +nv50_miptree_sync_cpu(struct pipe_screen *pscreen, struct nv50_miptree *mt, + unsigned level, unsigned image) +{ + struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws; + struct nv50_miptree_level *lvl = &mt->level[level]; + struct pipe_surface *dst, *src; + unsigned face = 0, zslice = 0; + + if (!is_dirty(lvl->image_dirty_gpu, image)) + return; + + if (mt->base.target == PIPE_TEXTURE_CUBE) + face = image; + else + if (mt->base.target == PIPE_TEXTURE_3D) + zslice = image; + + mark_clean(lvl->image_dirty_gpu, image); + + src = pscreen->get_tex_surface(pscreen, &mt->base, face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + dst = pscreen->get_tex_surface(pscreen, &mt->base, face, level, zslice, + PIPE_BUFFER_USAGE_CPU_READ); + + nvws->surface_copy(nvws, dst, 0, 0, src, 0, 0, dst->width, dst->height); + + pscreen->tex_surface_release(pscreen, &dst); + pscreen->tex_surface_release(pscreen, &src); +} + static struct pipe_surface * nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { struct nv50_miptree *mt = nv50_miptree(pt); + struct nv50_miptree_level *lvl = &mt->level[level]; struct nv50_surface *s; struct pipe_surface *ps; int img; @@ -128,12 +243,29 @@ nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, ps->nblocksx = pt->nblocksx[level]; ps->nblocksy = pt->nblocksy[level]; ps->stride = ps->width * ps->block.size; - ps->offset = mt->image_offset[img]; ps->usage = flags; ps->status = PIPE_SURFACE_STATUS_DEFINED; - pipe_texture_reference(&ps->texture, pt); - pipe_buffer_reference(pscreen, &ps->buffer, mt->buffer); + if (flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) { + assert(!(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE)); + nv50_miptree_sync_cpu(pscreen, mt, level, img); + + ps->offset = 0; + pipe_texture_reference(&ps->texture, pt); + pipe_buffer_reference(pscreen, &ps->buffer, lvl->image[img]); + + if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) + mark_dirty(lvl->image_dirty_cpu, img); + } else { + nv50_miptree_sync(pscreen, mt, level, img); + + ps->offset = lvl->image_offset[img]; + pipe_texture_reference(&ps->texture, pt); + pipe_buffer_reference(pscreen, &ps->buffer, mt->buffer); + + if (flags & PIPE_BUFFER_USAGE_GPU_WRITE) + mark_dirty(lvl->image_dirty_gpu, img); + } return ps; } diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index d66e1d0949d..7686f746eb2 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -32,7 +32,7 @@ #include "nv50_context.h" #define NV50_SU_MAX_TEMP 64 -#define NV50_PROGRAM_DUMP +//#define NV50_PROGRAM_DUMP /* ARL - gallium craps itself on progs/vp/arl.txt * @@ -841,6 +841,28 @@ emit_neg(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) emit(pc, e); } +static void +emit_kil(struct nv50_pc *pc, struct nv50_reg *src) +{ + struct nv50_program_exec *e; + const int r_pred = 1; + + /* Sets predicate reg ? */ + e = exec(pc); + e->inst[0] = 0xa00001fd; + e->inst[1] = 0xc4014788; + set_src_0(pc, src, e); + set_pred_wr(pc, 1, r_pred, e); + emit(pc, e); + + /* This is probably KILP */ + e = exec(pc); + e->inst[0] = 0x000001fe; + set_long(pc, e); + set_pred(pc, 1 /* LT? */, r_pred, e); + emit(pc, e); +} + static struct nv50_reg * tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst) { @@ -1069,6 +1091,12 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } free_temp(pc, temp); break; + case TGSI_OPCODE_KIL: + emit_kil(pc, src[0][0]); + emit_kil(pc, src[0][1]); + emit_kil(pc, src[0][2]); + emit_kil(pc, src[0][3]); + break; case TGSI_OPCODE_LIT: emit_lit(pc, &dst[0], mask, &src[0][0]); break; @@ -1602,13 +1630,19 @@ nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) if (!upload) return; +#ifdef NV50_PROGRAM_DUMP NOUVEAU_ERR("-------\n"); up = ptr = MALLOC(p->exec_size * 4); for (e = p->exec_head; e; e = e->next) { NOUVEAU_ERR("0x%08x\n", e->inst[0]); if (is_long(e)) NOUVEAU_ERR("0x%08x\n", e->inst[1]); + } +#endif + + up = ptr = MALLOC(p->exec_size * 4); + for (e = p->exec_head; e; e = e->next) { *(ptr++) = e->inst[0]; if (is_long(e)) *(ptr++) = e->inst[1]; @@ -1705,7 +1739,7 @@ nv50_fragprog_validate(struct nv50_context *nv50) so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); so_method(so, tesla, 0x1904, 4); - so_data (so, 0x01040404); /* p: 0x01000404 */ + so_data (so, 0x00040404); /* p: 0x01000404 */ so_data (so, 0x00000004); so_data (so, 0x00000000); so_data (so, 0x00000000); diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 777e77906d5..b923c820eba 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -21,41 +21,101 @@ */ #include "pipe/p_context.h" +#include "pipe/p_inlines.h" #include "nv50_context.h" +struct nv50_query { + struct pipe_buffer *buffer; + unsigned type; + boolean ready; + uint64_t result; +}; + +static INLINE struct nv50_query * +nv50_query(struct pipe_query *pipe) +{ + return (struct nv50_query *)pipe; +} + static struct pipe_query * nv50_query_create(struct pipe_context *pipe, unsigned type) { - NOUVEAU_ERR("unimplemented\n"); - return NULL; + struct pipe_winsys *ws = pipe->winsys; + struct nv50_query *q = CALLOC_STRUCT(nv50_query); + + assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER); + q->type = type; + + q->buffer = ws->buffer_create(ws, 256, 0, 16); + if (!q->buffer) { + FREE(q); + return NULL; + } + + return (struct pipe_query *)q; } static void -nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *q) +nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) { - NOUVEAU_ERR("unimplemented\n"); + struct nv50_query *q = nv50_query(pq); + + if (q) { + pipe_buffer_reference(pipe, &q->buffer, NULL); + FREE(q); + } } static void -nv50_query_begin(struct pipe_context *pipe, struct pipe_query *q) +nv50_query_begin(struct pipe_context *pipe, struct pipe_query *pq) { - NOUVEAU_ERR("unimplemented\n"); + struct nv50_context *nv50 = nv50_context(pipe); + struct nv50_query *q = nv50_query(pq); + + BEGIN_RING(tesla, 0x1530, 1); + OUT_RING (1); + BEGIN_RING(tesla, 0x1514, 1); + OUT_RING (1); + + q->ready = FALSE; } static void -nv50_query_end(struct pipe_context *pipe, struct pipe_query *q) +nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) { - NOUVEAU_ERR("unimplemented\n"); + struct nv50_context *nv50 = nv50_context(pipe); + struct nv50_query *q = nv50_query(pq); + + BEGIN_RING(tesla, 0x1b00, 4); + OUT_RELOCh(q->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCl(q->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RING (0x00000000); + OUT_RING (0x0100f002); + FIRE_RING (NULL); } static boolean -nv50_query_result(struct pipe_context *pipe, struct pipe_query *q, +nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq, boolean wait, uint64_t *result) { - NOUVEAU_ERR("unimplemented\n"); - *result = 0xdeadcafe; - return TRUE; + struct pipe_winsys *ws = pipe->winsys; + struct nv50_query *q = nv50_query(pq); + + /*XXX: Want to be able to return FALSE here instead of blocking + * until the result is available.. + */ + + if (!q->ready) { + uint32_t *map = ws->buffer_map(ws, q->buffer, + PIPE_BUFFER_USAGE_CPU_READ); + q->result = map[1]; + q->ready = TRUE; + ws->buffer_unmap(ws, q->buffer); + } + + *result = q->result; + return q->ready; } void diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 52f6a406882..ef46233f839 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -57,6 +57,10 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_A8L8_UNORM: + case PIPE_FORMAT_DXT1_RGB: + case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT5_RGBA: return TRUE; default: break; @@ -90,23 +94,23 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: return 32; case PIPE_CAP_NPOT_TEXTURES: - return 0; + return 1; case PIPE_CAP_TWO_SIDED_STENCIL: return 1; case PIPE_CAP_GLSL: return 0; case PIPE_CAP_S3TC: - return 0; + return 1; case PIPE_CAP_ANISOTROPIC_FILTER: - return 0; + return 1; case PIPE_CAP_POINT_SPRITE: return 0; case PIPE_CAP_MAX_RENDER_TARGETS: return 8; case PIPE_CAP_OCCLUSION_QUERY: - return 0; + return 1; case PIPE_CAP_TEXTURE_SHADOW_MAP: - return 0; + return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return 13; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index 95f9d408b5e..38c1d938b8e 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -175,6 +175,32 @@ nv50_sampler_state_create(struct pipe_context *pipe, break; } + if (cso->max_anisotropy >= 16.0) + tsc[0] |= (7 << 20); + else + if (cso->max_anisotropy >= 12.0) + tsc[0] |= (6 << 20); + else + if (cso->max_anisotropy >= 10.0) + tsc[0] |= (5 << 20); + else + if (cso->max_anisotropy >= 8.0) + tsc[0] |= (4 << 20); + else + if (cso->max_anisotropy >= 6.0) + tsc[0] |= (3 << 20); + else + if (cso->max_anisotropy >= 4.0) + tsc[0] |= (2 << 20); + else + if (cso->max_anisotropy >= 2.0) + tsc[0] |= (1 << 20); + + if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { + tsc[0] |= (1 << 8); + tsc[0] |= (nvgl_comparison_op(cso->compare_func) & 0x7); + } + return (void *)tsc; } diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index 5bf97d3a6bf..3f45a2fe186 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -63,48 +63,17 @@ static void * nv50_surface_map(struct pipe_screen *screen, struct pipe_surface *ps, unsigned flags ) { - struct nouveau_winsys *nvws = nv50_screen(screen)->nvws; struct pipe_winsys *ws = screen->winsys; - struct nv50_surface *s = nv50_surface(ps); - struct nv50_surface m = *s; - void *map; - if (!s->untiled) { - s->untiled = ws->buffer_create(ws, 0, 0, ps->buffer->size); - - m.base.buffer = s->untiled; - nvws->surface_copy(nvws, &m.base, 0, 0, &s->base, 0, 0, - ps->width, ps->height); - } - - /* Map original tiled surface to disallow it being validated while - * untiled mirror is mapped. - */ - ws->buffer_map(ws, ps->buffer, flags); - - map = ws->buffer_map(ws, s->untiled, flags); - if (!map) - return NULL; - - return map; + return ws->buffer_map(ws, ps->buffer, flags); } static void nv50_surface_unmap(struct pipe_screen *pscreen, struct pipe_surface *ps) { - struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws; struct pipe_winsys *ws = pscreen->winsys; - struct nv50_surface *s = nv50_surface(ps); - struct nv50_surface m = *s; - ws->buffer_unmap(ws, s->untiled); ws->buffer_unmap(ws, ps->buffer); - - m.base.buffer = s->untiled; - nvws->surface_copy(nvws, &s->base, 0, 0, &m.base, 0, 0, - ps->width, ps->height); - - pipe_buffer_reference(pscreen, &s->untiled, NULL); } void diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index fde3c97c059..239407c92bb 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -85,6 +85,34 @@ nv50_tex_construct(struct nouveau_stateobj *so, struct nv50_miptree *mt) NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_FMT_8_8); break; + case PIPE_FORMAT_DXT1_RGB: + so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_FMT_DXT1); + break; + case PIPE_FORMAT_DXT1_RGBA: + so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_FMT_DXT1); + break; + case PIPE_FORMAT_DXT3_RGBA: + so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_FMT_DXT3); + break; + case PIPE_FORMAT_DXT5_RGBA: + so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_FMT_DXT5); + break; default: return 1; } @@ -105,14 +133,23 @@ nv50_tex_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; struct nouveau_stateobj *so; - int i; + int unit, level, image; so = so_new(nv50->miptree_nr * 8 + 3, nv50->miptree_nr * 2); so_method(so, tesla, 0x0f00, 1); so_data (so, NV50_CB_TIC); so_method(so, tesla, 0x40000f04, nv50->miptree_nr * 8); - for (i = 0; i < nv50->miptree_nr; i++) { - if (nv50_tex_construct(so, nv50->miptree[i])) { + for (unit = 0; unit < nv50->miptree_nr; unit++) { + struct nv50_miptree *mt = nv50->miptree[unit]; + + for (level = 0; level <= mt->base.last_level; level++) { + for (image = 0; image < mt->image_nr; image++) { + nv50_miptree_sync(&nv50->screen->pipe, mt, + level, image); + } + } + + if (nv50_tex_construct(so, mt)) { NOUVEAU_ERR("failed tex validate\n"); so_ref(NULL, &so); return; diff --git a/src/gallium/drivers/nv50/nv50_texture.h b/src/gallium/drivers/nv50/nv50_texture.h index 6861d67b4d5..aca622c73b1 100644 --- a/src/gallium/drivers/nv50/nv50_texture.h +++ b/src/gallium/drivers/nv50/nv50_texture.h @@ -50,6 +50,9 @@ #define NV50TIC_0_0_FMT_5_6_5 0x00000015 #define NV50TIC_0_0_FMT_8_8 0x00000018 #define NV50TIC_0_0_FMT_8 0x0000001d +#define NV50TIC_0_0_FMT_DXT1 0x00000024 +#define NV50TIC_0_0_FMT_DXT3 0x00000025 +#define NV50TIC_0_0_FMT_DXT5 0x00000026 #define NV50TIC_0_1_OFFSET_LOW_MASK 0xffffffff #define NV50TIC_0_1_OFFSET_LOW_SHIFT 0 diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 584336682e4..435dc9777da 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -60,6 +60,10 @@ nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, OUT_RING (0); BEGIN_RING(tesla, 0x142c, 1); OUT_RING (0); + BEGIN_RING(tesla, 0x1440, 1); + OUT_RING (0); + BEGIN_RING(tesla, 0x1334, 1); + OUT_RING (0); BEGIN_RING(tesla, NV50TCL_VERTEX_BEGIN, 1); OUT_RING (nv50_prim(mode)); diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 5c6a92b53bc..4f0b301f317 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -204,6 +204,7 @@ enum pipe_texture_target { #define PIPE_BUFFER_USAGE_VERTEX (1 << 5) #define PIPE_BUFFER_USAGE_INDEX (1 << 6) #define PIPE_BUFFER_USAGE_CONSTANT (1 << 7) +#define PIPE_BUFFER_USAGE_DISCARD (1 << 8) /** Pipe driver custom usage flags should be greater or equal to this value */ #define PIPE_BUFFER_USAGE_CUSTOM (1 << 16) diff --git a/src/gallium/include/state_tracker/drm_api.h b/src/gallium/include/state_tracker/drm_api.h new file mode 100644 index 00000000000..54480fa0477 --- /dev/null +++ b/src/gallium/include/state_tracker/drm_api.h @@ -0,0 +1,33 @@ + +#ifndef _DRM_API_H_ +#define _DRM_API_H_ + +struct pipe_screen; +struct pipe_winsys; +struct pipe_context; + +struct drm_api +{ + /** + * Special buffer function + */ + /*@{*/ + struct pipe_screen* (*create_screen)(int drmFB, int pciID); + struct pipe_context* (*create_context)(struct pipe_screen *screen); + /*@}*/ + + /** + * Special buffer function + */ + /*@{*/ + struct pipe_buffer* (*buffer_from_handle)(struct pipe_winsys *winsys, const char *name, unsigned handle); + unsigned (*handle_from_buffer)(struct pipe_winsys *winsys, struct pipe_buffer *buffer); + /*@}*/ +}; + +/** + * A driver needs to export this symbol + */ +extern struct drm_api drm_api_hocks; + +#endif diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile new file mode 100644 index 00000000000..17d1a7a8e40 --- /dev/null +++ b/src/gallium/state_trackers/egl/Makefile @@ -0,0 +1,29 @@ +TARGET = libegldrm.a +CFILES = $(wildcard ./*.c) +OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES)) +GALLIUMDIR = ../.. +TOP = ../../../.. + +include ${TOP}/configs/current + +CFLAGS += -g -Wall -Werror=implicit-function-declaration -fPIC \ + $(shell pkg-config --cflags pixman-1 xorg-server) \ + -I${GALLIUMDIR}/include \ + -I${GALLIUMDIR}/auxiliary \ + -I${TOP}/src/mesa/drivers/dri/common \ + -I${TOP}/src/mesa \ + -I$(TOP)/include \ + -I$(TOP)/src/egl/main \ + ${LIBDRM_CFLAGS} + +############################################# + +.PHONY = all clean + +all: ${TARGET} + +${TARGET}: ${OBJECTS} + ar rcs $@ $^ + +clean: + rm -rf ${OBJECTS} ${TARGET} diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c new file mode 100644 index 00000000000..217fe00338e --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_context.c @@ -0,0 +1,194 @@ + +#include "utils.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "egl_tracker.h" + +#include "egllog.h" + + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_winsys.h" + +#include "state_tracker/st_public.h" +#include "state_tracker/drm_api.h" + +#include "GL/internal/glcore.h" + +#define need_GL_ARB_multisample +#define need_GL_ARB_point_parameters +#define need_GL_ARB_texture_compression +#define need_GL_ARB_vertex_buffer_object +#define need_GL_ARB_vertex_program +#define need_GL_ARB_window_pos +#define need_GL_EXT_blend_color +#define need_GL_EXT_blend_equation_separate +#define need_GL_EXT_blend_func_separate +#define need_GL_EXT_blend_minmax +#define need_GL_EXT_cull_vertex +#define need_GL_EXT_fog_coord +#define need_GL_EXT_framebuffer_object +#define need_GL_EXT_multi_draw_arrays +#define need_GL_EXT_secondary_color +#define need_GL_NV_vertex_program +#include "extension_helper.h" + +/** + * TODO HACK! FUGLY! + * Copied for intel extentions. + */ +const struct dri_extension card_extensions[] = { + {"GL_ARB_multisample", GL_ARB_multisample_functions}, + {"GL_ARB_multitexture", NULL}, + {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, + {"GL_ARB_texture_border_clamp", NULL}, + {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, + {"GL_ARB_texture_cube_map", NULL}, + {"GL_ARB_texture_env_add", NULL}, + {"GL_ARB_texture_env_combine", NULL}, + {"GL_ARB_texture_env_dot3", NULL}, + {"GL_ARB_texture_mirrored_repeat", NULL}, + {"GL_ARB_texture_rectangle", NULL}, + {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, + {"GL_ARB_pixel_buffer_object", NULL}, + {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, + {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, + {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, + {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, + {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, + {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, + {"GL_EXT_blend_subtract", NULL}, + {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, + {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, + {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, + {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, + {"GL_EXT_packed_depth_stencil", NULL}, + {"GL_EXT_pixel_buffer_object", NULL}, + {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions}, + {"GL_EXT_stencil_wrap", NULL}, + {"GL_EXT_texture_edge_clamp", NULL}, + {"GL_EXT_texture_env_combine", NULL}, + {"GL_EXT_texture_env_dot3", NULL}, + {"GL_EXT_texture_filter_anisotropic", NULL}, + {"GL_EXT_texture_lod_bias", NULL}, + {"GL_3DFX_texture_compression_FXT1", NULL}, + {"GL_APPLE_client_storage", NULL}, + {"GL_MESA_pack_invert", NULL}, + {"GL_MESA_ycbcr_texture", NULL}, + {"GL_NV_blend_square", NULL}, + {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, + {"GL_NV_vertex_program1_1", NULL}, + {"GL_SGIS_generate_mipmap", NULL }, + {NULL, NULL} +}; + +EGLContext +drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) +{ + struct drm_device *dev = (struct drm_device *)drv; + struct drm_context *ctx; + struct drm_context *share = NULL; + struct st_context *st_share = NULL; + _EGLConfig *conf; + int i; + __GLcontextModes *visual; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreateContext"); + return EGL_NO_CONTEXT; + } + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + /* no attribs defined for now */ + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext"); + return EGL_NO_CONTEXT; + } + } + + ctx = (struct drm_context *) calloc(1, sizeof(struct drm_context)); + if (!ctx) + goto err_c; + + _eglInitContext(drv, dpy, &ctx->base, config, attrib_list); + + ctx->pipe = drm_api_hocks.create_context(dev->screen); + if (!ctx->pipe) + goto err_pipe; + + if (share) + st_share = share->st; + + visual = drm_visual_from_config(conf); + ctx->st = st_create_context(ctx->pipe, visual, st_share); + drm_visual_modes_destroy(visual); + + if (!ctx->st) + goto err_gl; + + /* generate handle and insert into hash table */ + _eglSaveContext(&ctx->base); + assert(_eglGetContextHandle(&ctx->base)); + + return _eglGetContextHandle(&ctx->base); + +err_gl: + ctx->pipe->destroy(ctx->pipe); +err_pipe: + free(ctx); +err_c: + return EGL_NO_CONTEXT; +} + +EGLBoolean +drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) +{ + struct drm_context *c = lookup_drm_context(context); + _eglRemoveContext(&c->base); + if (c->base.IsBound) { + c->base.DeletePending = EGL_TRUE; + } else { + st_destroy_context(c->st); + c->pipe->destroy(c->pipe); + free(c); + } + return EGL_TRUE; +} + +EGLBoolean +drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context) +{ + struct drm_surface *readSurf = lookup_drm_surface(read); + struct drm_surface *drawSurf = lookup_drm_surface(draw); + struct drm_context *ctx = lookup_drm_context(context); + EGLBoolean b; + + b = _eglMakeCurrent(drv, dpy, draw, read, context); + if (!b) + return EGL_FALSE; + + if (ctx) { + if (!drawSurf || !readSurf) + return EGL_FALSE; + + drawSurf->user = ctx; + readSurf->user = ctx; + + st_make_current(ctx->st, drawSurf->stfb, readSurf->stfb); + + /* st_resize_framebuffer needs a bound context to work */ + st_resize_framebuffer(drawSurf->stfb, drawSurf->w, drawSurf->h); + st_resize_framebuffer(readSurf->stfb, readSurf->w, readSurf->h); + } else { + drawSurf->user = NULL; + readSurf->user = NULL; + + st_make_current(NULL, NULL, NULL); + } + + return EGL_TRUE; +} diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c new file mode 100644 index 00000000000..71292bf2a91 --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_surface.c @@ -0,0 +1,418 @@ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "egl_tracker.h" + +#include "egllog.h" + +#include "pipe/p_inlines.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" + +#include "state_tracker/drm_api.h" + +/* + * Util functions + */ + +static struct drm_mode_modeinfo * +drm_find_mode(drmModeConnectorPtr connector, _EGLMode *mode) +{ + int i; + struct drm_mode_modeinfo *m = NULL; + + for (i = 0; i < connector->count_modes; i++) { + m = &connector->modes[i]; + if (m->hdisplay == mode->Width && m->vdisplay == mode->Height && m->vrefresh == mode->RefreshRate) + break; + m = &connector->modes[0]; /* if we can't find one, return first */ + } + + return m; +} + +static struct st_framebuffer * +drm_create_framebuffer(const __GLcontextModes *visual, + unsigned width, + unsigned height, + void *priv) +{ + enum pipe_format colorFormat, depthFormat, stencilFormat; + + if (visual->redBits == 5) + colorFormat = PIPE_FORMAT_R5G6B5_UNORM; + else + colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM; + + if (visual->depthBits == 16) + depthFormat = PIPE_FORMAT_Z16_UNORM; + else if (visual->depthBits == 24) + depthFormat = PIPE_FORMAT_S8Z24_UNORM; + else + depthFormat = PIPE_FORMAT_NONE; + + if (visual->stencilBits == 8) + stencilFormat = PIPE_FORMAT_S8Z24_UNORM; + else + stencilFormat = PIPE_FORMAT_NONE; + + return st_create_framebuffer(visual, + colorFormat, + depthFormat, + stencilFormat, + width, + height, + priv); +} + +static void +drm_create_texture(_EGLDriver *drv, + struct drm_screen *scrn, + unsigned w, unsigned h) +{ + struct drm_device *dev = (struct drm_device *)drv; + struct pipe_screen *screen = dev->screen; + struct pipe_surface *surface; + struct pipe_texture *texture; + struct pipe_texture templat; + struct pipe_buffer *buf; + unsigned stride = 1024; + unsigned pitch = 0; + unsigned size = 0; + void *ptr; + + /* ugly */ + if (stride < w) + stride = 2048; + + pitch = stride * 4; + size = h * 2 * pitch; + + buf = pipe_buffer_create(screen, + 0, /* alignment */ + PIPE_BUFFER_USAGE_GPU_READ_WRITE | + PIPE_BUFFER_USAGE_CPU_READ_WRITE, + size); + + if (!buf) + goto err_buf; + +#if DEBUG + ptr = pipe_buffer_map(screen, buf, PIPE_BUFFER_USAGE_CPU_WRITE); + memset(ptr, 0xFF, size); + pipe_buffer_unmap(screen, buf); +#else + (void)ptr; +#endif + + memset(&templat, 0, sizeof(templat)); + templat.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; + templat.target = PIPE_TEXTURE_2D; + templat.last_level = 0; + templat.depth[0] = 1; + templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templat.width[0] = w; + templat.height[0] = h; + pf_get_block(templat.format, &templat.block); + + texture = screen->texture_blanket(dev->screen, + &templat, + &pitch, + buf); + if (!texture) + goto err_tex; + + surface = screen->get_tex_surface(screen, + texture, + 0, + 0, + 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + if (!surface) + goto err_surf; + + + scrn->tex = texture; + scrn->surface = surface; + scrn->buffer = buf; + scrn->front.width = w; + scrn->front.height = h; + scrn->front.pitch = pitch; + scrn->front.handle = drm_api_hocks.handle_from_buffer(dev->winsys, scrn->buffer); + if (0) + goto err_handle; + + return; + +err_handle: + pipe_surface_reference(&surface, NULL); +err_surf: + pipe_texture_reference(&texture, NULL); +err_tex: + pipe_buffer_reference(screen, &buf, NULL); +err_buf: + return; +} + +/* + * Exported functions + */ + +void +drm_takedown_shown_screen(_EGLDriver *drv, struct drm_screen *screen) +{ + struct drm_device *dev = (struct drm_device *)drv; + + screen->surf = NULL; + + drmModeSetCrtc( + dev->drmFD, + screen->crtcID, + 0, // FD + 0, 0, + NULL, 0, // List of output ids + NULL); + + drmModeRmFB(dev->drmFD, screen->fbID); + drmModeFreeFB(screen->fb); + screen->fb = NULL; + + pipe_surface_reference(&screen->surface, NULL); + pipe_texture_reference(&screen->tex, NULL); + pipe_buffer_reference(dev->screen, &screen->buffer, NULL); + + screen->shown = 0; +} + +EGLSurface +drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) +{ + return EGL_NO_SURFACE; +} + + +EGLSurface +drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) +{ + return EGL_NO_SURFACE; +} + + +EGLSurface +drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + int i; + int width = -1; + int height = -1; + struct drm_surface *surf = NULL; + __GLcontextModes *visual; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface"); + return EGL_NO_CONTEXT; + } + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + case EGL_WIDTH: + width = attrib_list[++i]; + break; + case EGL_HEIGHT: + height = attrib_list[++i]; + break; + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface"); + return EGL_NO_SURFACE; + } + } + + if (width < 1 || height < 1) { + _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface"); + return EGL_NO_SURFACE; + } + + surf = (struct drm_surface *) calloc(1, sizeof(struct drm_surface)); + if (!surf) + goto err; + + if (!_eglInitSurface(drv, dpy, &surf->base, EGL_PBUFFER_BIT, config, attrib_list)) + goto err_surf; + + surf->w = width; + surf->h = height; + + visual = drm_visual_from_config(conf); + surf->stfb = drm_create_framebuffer(visual, + width, + height, + (void*)surf); + drm_visual_modes_destroy(visual); + + _eglSaveSurface(&surf->base); + return surf->base.Handle; + +err_surf: + free(surf); +err: + return EGL_NO_SURFACE; +} + +EGLSurface +drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, + const EGLint *attrib_list) +{ + EGLSurface surf = drm_create_pbuffer_surface(drv, dpy, cfg, attrib_list); + + return surf; +} + +EGLBoolean +drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, + EGLScreenMESA screen, + EGLSurface surface, EGLModeMESA m) +{ + struct drm_device *dev = (struct drm_device *)drv; + struct drm_surface *surf = lookup_drm_surface(surface); + struct drm_screen *scrn = lookup_drm_screen(dpy, screen); + _EGLMode *mode = _eglLookupMode(dpy, m); + int ret; + unsigned int i, k; + + if (scrn->shown) + drm_takedown_shown_screen(drv, scrn); + + + drm_create_texture(drv, scrn, mode->Width, mode->Height); + if (!scrn->buffer) + return EGL_FALSE; + + ret = drmModeAddFB(dev->drmFD, + scrn->front.width, scrn->front.height, + 32, 32, scrn->front.pitch, + scrn->front.handle, + &scrn->fbID); + + if (ret) + goto err_bo; + + scrn->fb = drmModeGetFB(dev->drmFD, scrn->fbID); + if (!scrn->fb) + goto err_bo; + + /* find a fitting crtc */ + { + drmModeConnector *con = scrn->connector; + + scrn->mode = drm_find_mode(con, mode); + if (!scrn->mode) + goto err_fb; + + for (k = 0; k < con->count_encoders; k++) { + drmModeEncoder *enc = drmModeGetEncoder(dev->drmFD, con->encoders[k]); + for (i = 0; i < dev->res->count_crtcs; i++) { + if (enc->possible_crtcs & (1<<i)) { + /* save the ID */ + scrn->crtcID = dev->res->crtcs[i]; + + /* skip the rest */ + i = dev->res->count_crtcs; + k = dev->res->count_encoders; + } + } + drmModeFreeEncoder(enc); + } + } + + ret = drmModeSetCrtc(dev->drmFD, + scrn->crtcID, + scrn->fbID, + 0, 0, + &scrn->connectorID, 1, + scrn->mode); + + if (ret) + goto err_crtc; + + surf->screen = scrn; + + scrn->surf = surf; + scrn->shown = 1; + + return EGL_TRUE; + +err_crtc: + scrn->crtcID = 0; + +err_fb: + drmModeRmFB(dev->drmFD, scrn->fbID); + drmModeFreeFB(scrn->fb); + scrn->fb = NULL; + +err_bo: + pipe_surface_reference(&scrn->surface, NULL); + pipe_texture_reference(&scrn->tex, NULL); + pipe_buffer_reference(dev->screen, &scrn->buffer, NULL); + + return EGL_FALSE; +} + +EGLBoolean +drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +{ + struct drm_surface *surf = lookup_drm_surface(surface); + _eglRemoveSurface(&surf->base); + if (surf->base.IsBound) { + surf->base.DeletePending = EGL_TRUE; + } else { + if (surf->screen) + drm_takedown_shown_screen(drv, surf->screen); + st_unreference_framebuffer(surf->stfb); + free(surf); + } + return EGL_TRUE; +} + +EGLBoolean +drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +{ + struct drm_surface *surf = lookup_drm_surface(draw); + struct pipe_surface *back_surf; + + if (!surf) + return EGL_FALSE; + + /* error checking */ + if (!_eglSwapBuffers(drv, dpy, draw)) + return EGL_FALSE; + + back_surf = st_get_framebuffer_surface(surf->stfb, + ST_SURFACE_BACK_LEFT); + + if (back_surf) { + + st_notify_swapbuffers(surf->stfb); + + if (surf->screen) { + surf->user->pipe->flush(surf->user->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL); + surf->user->pipe->surface_copy(surf->user->pipe, + 0, + surf->screen->surface, + 0, 0, + back_surf, + 0, 0, + surf->w, surf->h); + surf->user->pipe->flush(surf->user->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL); + /* TODO stuff here */ + } + + st_notify_swapbuffers_complete(surf->stfb); + } + + return EGL_TRUE; +} diff --git a/src/gallium/state_trackers/egl/egl_tracker.c b/src/gallium/state_trackers/egl/egl_tracker.c new file mode 100644 index 00000000000..3ca5acb68bf --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_tracker.c @@ -0,0 +1,217 @@ + +#include "utils.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "egl_tracker.h" + +#include "egllog.h" +#include "state_tracker/drm_api.h" + +#include "pipe/p_screen.h" +#include "pipe/p_winsys.h" + +/** HACK */ +void* driDriverAPI; +extern const struct dri_extension card_extensions[]; + + +/* + * Exported functions + */ + +/** + * The bootstrap function. Return a new drm_driver object and + * plug in API functions. + */ +_EGLDriver * +_eglMain(_EGLDisplay *dpy, const char *args) +{ + struct drm_device *drm; + + drm = (struct drm_device *) calloc(1, sizeof(struct drm_device)); + if (!drm) { + return NULL; + } + + /* First fill in the dispatch table with defaults */ + _eglInitDriverFallbacks(&drm->base); + /* then plug in our Drm-specific functions */ + drm->base.API.Initialize = drm_initialize; + drm->base.API.Terminate = drm_terminate; + drm->base.API.CreateContext = drm_create_context; + drm->base.API.MakeCurrent = drm_make_current; + drm->base.API.CreateWindowSurface = drm_create_window_surface; + drm->base.API.CreatePixmapSurface = drm_create_pixmap_surface; + drm->base.API.CreatePbufferSurface = drm_create_pbuffer_surface; + drm->base.API.DestroySurface = drm_destroy_surface; + drm->base.API.DestroyContext = drm_destroy_context; + drm->base.API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa; + drm->base.API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa; + drm->base.API.SwapBuffers = drm_swap_buffers; + + drm->base.ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/; + drm->base.Name = "DRM/Gallium/Win"; + + /* enable supported extensions */ + drm->base.Extensions.MESA_screen_surface = EGL_TRUE; + drm->base.Extensions.MESA_copy_context = EGL_TRUE; + + return &drm->base; +} + +static void +drm_get_device_id(struct drm_device *device) +{ + char path[512]; + FILE *file; + + /* TODO get the real minor */ + int minor = 0; + + snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/device", minor); + file = fopen(path, "r"); + if (!file) { + _eglLog(_EGL_WARNING, "Could not retrive device ID\n"); + return; + } + + fgets(path, sizeof( path ), file); + sscanf(path, "%x", &device->deviceID); + fclose(file); +} + +static void +drm_update_res(struct drm_device *dev) +{ + drmModeFreeResources(dev->res); + dev->res = drmModeGetResources(dev->drmFD); +} + +static void +drm_add_modes_from_connector(_EGLScreen *screen, drmModeConnectorPtr connector) +{ + struct drm_mode_modeinfo *m; + int i; + + for (i = 0; i < connector->count_modes; i++) { + m = &connector->modes[i]; + _eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name); + } +} + +EGLBoolean +drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct drm_device *dev = (struct drm_device *)drv; + struct drm_screen *screen = NULL; + drmModeConnectorPtr connector = NULL; + drmModeResPtr res = NULL; + unsigned count_connectors = 0; + int num_screens = 0; + EGLint i; + int fd; + + fd = drmOpen("i915", NULL); + if (fd < 0) + goto err_fd; + + dev->drmFD = fd; + drm_get_device_id(dev); + + dev->screen = drm_api_hocks.create_screen(dev->drmFD, dev->deviceID); + if (!dev->screen) + goto err_screen; + dev->winsys = dev->screen->winsys; + + /* TODO HACK */ + driInitExtensions(NULL, card_extensions, GL_FALSE); + + drm_update_res(dev); + res = dev->res; + if (res) + count_connectors = res->count_connectors; + else + _eglLog(_EGL_WARNING, "Could not retrive kms information\n"); + + for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) { + connector = drmModeGetConnector(fd, res->connectors[i]); + + if (!connector) + continue; + + if (connector->connection != DRM_MODE_CONNECTED) { + drmModeFreeConnector(connector); + continue; + } + + screen = malloc(sizeof(struct drm_screen)); + memset(screen, 0, sizeof(*screen)); + screen->connector = connector; + screen->connectorID = connector->connector_id; + _eglInitScreen(&screen->base); + _eglAddScreen(disp, &screen->base); + drm_add_modes_from_connector(&screen->base, connector); + dev->screens[num_screens++] = screen; + } + dev->count_screens = num_screens; + + /* for now we only have one config */ + _EGLConfig *config = calloc(1, sizeof(*config)); + memset(config, 1, sizeof(*config)); + _eglInitConfig(config, 1); + _eglSetConfigAttrib(config, EGL_RED_SIZE, 8); + _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8); + _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8); + _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8); + _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32); + _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24); + _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8); + _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); + _eglAddConfig(disp, config); + + drv->Initialized = EGL_TRUE; + + *major = 1; + *minor = 4; + + return EGL_TRUE; + +err_screen: + drmClose(fd); +err_fd: + return EGL_FALSE; +} + +EGLBoolean +drm_terminate(_EGLDriver *drv, EGLDisplay dpy) +{ + struct drm_device *dev = (struct drm_device *)drv; + struct drm_screen *screen; + int i = 0; + + drmFreeVersion(dev->version); + + for (i = 0; i < dev->count_screens; i++) { + screen = dev->screens[i]; + + if (screen->shown) + drm_takedown_shown_screen(drv, screen); + + drmModeFreeConnector(screen->connector); + _eglDestroyScreen(&screen->base); + dev->screens[i] = NULL; + } + + dev->screen->destroy(dev->screen); + dev->winsys = NULL; + + drmClose(dev->drmFD); + + _eglCleanupDisplay(_eglLookupDisplay(dpy)); + free(dev); + + return EGL_TRUE; +} diff --git a/src/gallium/state_trackers/egl/egl_tracker.h b/src/gallium/state_trackers/egl/egl_tracker.h new file mode 100644 index 00000000000..0b4dd9797d5 --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_tracker.h @@ -0,0 +1,191 @@ + +#ifndef _EGL_TRACKER_H_ +#define _EGL_TRACKER_H_ + +#include <stdint.h> + +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "eglmode.h" +#include "eglscreen.h" +#include "eglsurface.h" + +#include "xf86drm.h" +#include "xf86drmMode.h" + +#include "pipe/p_compiler.h" + +#include "state_tracker/st_public.h" + +#define MAX_SCREENS 16 + +struct pipe_winsys; +struct pipe_screen; +struct pipe_context; +struct state_tracker; + +struct drm_screen; +struct drm_context; + +struct drm_device +{ + _EGLDriver base; /* base class/object */ + + /* + * pipe + */ + + struct pipe_winsys *winsys; + struct pipe_screen *screen; + + /* + * drm + */ + + int drmFD; + drmVersionPtr version; + int deviceID; + + drmModeResPtr res; + + struct drm_screen *screens[MAX_SCREENS]; + size_t count_screens; +}; + +struct drm_surface +{ + _EGLSurface base; /* base class/object */ + + /* + * pipe + */ + + + struct st_framebuffer *stfb; + + /* + * drm + */ + + struct drm_context *user; + struct drm_screen *screen; + + int w; + int h; +}; + +struct drm_context +{ + _EGLContext base; /* base class/object */ + + /* pipe */ + + struct pipe_context *pipe; + struct st_context *st; +}; + +struct drm_screen +{ + _EGLScreen base; + + /* + * pipe + */ + + struct pipe_buffer *buffer; + struct pipe_texture *tex; + struct pipe_surface *surface; + + /* + * drm + */ + + struct { + unsigned height; + unsigned width; + unsigned pitch; + unsigned handle; + } front; + + /* currently only support one connector */ + drmModeConnectorPtr connector; + uint32_t connectorID; + + /* Has this screen been shown */ + int shown; + + /* Surface that is currently attached to this screen */ + struct drm_surface *surf; + + /* framebuffer */ + drmModeFBPtr fb; + uint32_t fbID; + + /* crtc and mode used */ + /*drmModeCrtcPtr crtc;*/ + uint32_t crtcID; + + struct drm_mode_modeinfo *mode; +}; + + +static INLINE struct drm_context * +lookup_drm_context(EGLContext context) +{ + _EGLContext *c = _eglLookupContext(context); + return (struct drm_context *) c; +} + + +static INLINE struct drm_surface * +lookup_drm_surface(EGLSurface surface) +{ + _EGLSurface *s = _eglLookupSurface(surface); + return (struct drm_surface *) s; +} + +static INLINE struct drm_screen * +lookup_drm_screen(EGLDisplay dpy, EGLScreenMESA screen) +{ + _EGLScreen *s = _eglLookupScreen(dpy, screen); + return (struct drm_screen *) s; +} + +/** + * egl_visual.h + */ +/*@{*/ +void drm_visual_modes_destroy(__GLcontextModes *modes); +__GLcontextModes* drm_visual_modes_create(unsigned count, size_t minimum_size); +__GLcontextModes* drm_visual_from_config(_EGLConfig *conf); +/*@}*/ + +/** + * egl_surface.h + */ +/*@{*/ +void drm_takedown_shown_screen(_EGLDriver *drv, struct drm_screen *screen); +/*@}*/ + +/** + * All function exported to the egl side. + */ +/*@{*/ +EGLBoolean drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor); +EGLBoolean drm_terminate(_EGLDriver *drv, EGLDisplay dpy); +EGLContext drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list); +EGLBoolean drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context); +EGLSurface drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list); +EGLSurface drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list); +EGLSurface drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +EGLSurface drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, const EGLint *attrib_list); +EGLBoolean drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA m); +EGLBoolean drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface); +EGLBoolean drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context); +EGLBoolean drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw); +/*@}*/ + +#endif diff --git a/src/gallium/state_trackers/egl/egl_visual.c b/src/gallium/state_trackers/egl/egl_visual.c new file mode 100644 index 00000000000..e59f893851e --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_visual.c @@ -0,0 +1,85 @@ + +#include "egl_tracker.h" + +#include "egllog.h" + +void +drm_visual_modes_destroy(__GLcontextModes *modes) +{ + _eglLog(_EGL_DEBUG, "%s", __FUNCTION__); + + while (modes) { + __GLcontextModes * const next = modes->next; + free(modes); + modes = next; + } +} + +__GLcontextModes * +drm_visual_modes_create(unsigned count, size_t minimum_size) +{ + /* This code copied from libGLX, and modified */ + const size_t size = (minimum_size > sizeof(__GLcontextModes)) + ? minimum_size : sizeof(__GLcontextModes); + __GLcontextModes * head = NULL; + __GLcontextModes ** next; + unsigned i; + + _eglLog(_EGL_DEBUG, "%s %d %d", __FUNCTION__, count, minimum_size); + + next = & head; + for (i = 0 ; i < count ; i++) { + *next = (__GLcontextModes *) calloc(1, size); + if (*next == NULL) { + drm_visual_modes_destroy(head); + head = NULL; + break; + } + + (*next)->doubleBufferMode = 1; + (*next)->visualID = GLX_DONT_CARE; + (*next)->visualType = GLX_DONT_CARE; + (*next)->visualRating = GLX_NONE; + (*next)->transparentPixel = GLX_NONE; + (*next)->transparentRed = GLX_DONT_CARE; + (*next)->transparentGreen = GLX_DONT_CARE; + (*next)->transparentBlue = GLX_DONT_CARE; + (*next)->transparentAlpha = GLX_DONT_CARE; + (*next)->transparentIndex = GLX_DONT_CARE; + (*next)->xRenderable = GLX_DONT_CARE; + (*next)->fbconfigID = GLX_DONT_CARE; + (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; + (*next)->bindToTextureRgb = GLX_DONT_CARE; + (*next)->bindToTextureRgba = GLX_DONT_CARE; + (*next)->bindToMipmapTexture = GLX_DONT_CARE; + (*next)->bindToTextureTargets = 0; + (*next)->yInverted = GLX_DONT_CARE; + + next = & ((*next)->next); + } + + return head; +} + +__GLcontextModes * +drm_visual_from_config(_EGLConfig *conf) +{ + __GLcontextModes *visual; + (void)conf; + + visual = drm_visual_modes_create(1, sizeof(*visual)); + visual->redBits = 8; + visual->greenBits = 8; + visual->blueBits = 8; + visual->alphaBits = 8; + + visual->rgbBits = 32; + visual->doubleBufferMode = 1; + + visual->depthBits = 24; + visual->haveDepthBuffer = visual->depthBits > 0; + visual->stencilBits = 8; + visual->haveStencilBuffer = visual->stencilBits > 0; + + return visual; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c index 3ce93cf49d1..da119ff1bdb 100644 --- a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c +++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c @@ -71,7 +71,10 @@ static int vlResizeFrameBuffer basic_csc->viewport.translate[3] = 0; if (basic_csc->framebuffer_tex) - pipe_texture_release(&basic_csc->framebuffer_tex); + { + pipe_surface_reference(&basic_csc->framebuffer.cbufs[0], NULL); + pipe_texture_reference(&basic_csc->framebuffer_tex, NULL); + } memset(&template, 0, sizeof(struct pipe_texture)); template.target = PIPE_TEXTURE_2D; @@ -153,11 +156,11 @@ static int vlPutPictureCSC basic_csc = (struct vlBasicCSC*)csc; pipe = basic_csc->pipe; - vs_consts = pipe->winsys->buffer_map + vs_consts = pipe_buffer_map ( - pipe->winsys, + pipe->screen, basic_csc->vs_const_buf.buffer, - PIPE_BUFFER_USAGE_CPU_WRITE + PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD ); vs_consts->dst_scale.x = destw / (float)basic_csc->framebuffer.cbufs[0]->width; @@ -178,7 +181,7 @@ static int vlPutPictureCSC vs_consts->src_trans.z = 0; vs_consts->src_trans.w = 0; - pipe->winsys->buffer_unmap(pipe->winsys, basic_csc->vs_const_buf.buffer); + pipe_buffer_unmap(pipe->screen, basic_csc->vs_const_buf.buffer); pipe->set_sampler_textures(pipe, 1, &surface->texture); pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4); @@ -225,17 +228,20 @@ static int vlDestroy pipe = basic_csc->pipe; if (basic_csc->framebuffer_tex) - pipe_texture_release(&basic_csc->framebuffer_tex); + { + pipe_surface_reference(&basic_csc->framebuffer.cbufs[0], NULL); + pipe_texture_reference(&basic_csc->framebuffer_tex, NULL); + } pipe->delete_sampler_state(pipe, basic_csc->sampler); pipe->delete_vs_state(pipe, basic_csc->vertex_shader); pipe->delete_fs_state(pipe, basic_csc->fragment_shader); for (i = 0; i < 2; ++i) - pipe->winsys->buffer_destroy(pipe->winsys, basic_csc->vertex_bufs[i].buffer); + pipe_buffer_reference(pipe->screen, &basic_csc->vertex_bufs[i].buffer, NULL); - pipe->winsys->buffer_destroy(pipe->winsys, basic_csc->vs_const_buf.buffer); - pipe->winsys->buffer_destroy(pipe->winsys, basic_csc->fs_const_buf.buffer); + pipe_buffer_reference(pipe->screen, &basic_csc->vs_const_buf.buffer, NULL); + pipe_buffer_reference(pipe->screen, &basic_csc->fs_const_buf.buffer, NULL); FREE(basic_csc); @@ -542,9 +548,9 @@ static int vlCreateDataBufs csc->vertex_bufs[0].pitch = sizeof(struct vlVertex2f); csc->vertex_bufs[0].max_index = 3; csc->vertex_bufs[0].buffer_offset = 0; - csc->vertex_bufs[0].buffer = pipe->winsys->buffer_create + csc->vertex_bufs[0].buffer = pipe_buffer_create ( - pipe->winsys, + pipe->screen, 1, PIPE_BUFFER_USAGE_VERTEX, sizeof(struct vlVertex2f) * 4 @@ -552,12 +558,12 @@ static int vlCreateDataBufs memcpy ( - pipe->winsys->buffer_map(pipe->winsys, csc->vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), + pipe_buffer_map(pipe->screen, csc->vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), surface_verts, sizeof(struct vlVertex2f) * 4 ); - pipe->winsys->buffer_unmap(pipe->winsys, csc->vertex_bufs[0].buffer); + pipe_buffer_unmap(pipe->screen, csc->vertex_bufs[0].buffer); csc->vertex_elems[0].src_offset = 0; csc->vertex_elems[0].vertex_buffer_index = 0; @@ -571,9 +577,9 @@ static int vlCreateDataBufs csc->vertex_bufs[1].pitch = sizeof(struct vlVertex2f); csc->vertex_bufs[1].max_index = 3; csc->vertex_bufs[1].buffer_offset = 0; - csc->vertex_bufs[1].buffer = pipe->winsys->buffer_create + csc->vertex_bufs[1].buffer = pipe_buffer_create ( - pipe->winsys, + pipe->screen, 1, PIPE_BUFFER_USAGE_VERTEX, sizeof(struct vlVertex2f) * 4 @@ -581,12 +587,12 @@ static int vlCreateDataBufs memcpy ( - pipe->winsys->buffer_map(pipe->winsys, csc->vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), + pipe_buffer_map(pipe->screen, csc->vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), surface_texcoords, sizeof(struct vlVertex2f) * 4 ); - pipe->winsys->buffer_unmap(pipe->winsys, csc->vertex_bufs[1].buffer); + pipe_buffer_unmap(pipe->screen, csc->vertex_bufs[1].buffer); csc->vertex_elems[1].src_offset = 0; csc->vertex_elems[1].vertex_buffer_index = 1; @@ -598,11 +604,11 @@ static int vlCreateDataBufs * Const buffer contains scaling and translation vectors */ csc->vs_const_buf.size = sizeof(struct vlVertexShaderConsts); - csc->vs_const_buf.buffer = pipe->winsys->buffer_create + csc->vs_const_buf.buffer = pipe_buffer_create ( - pipe->winsys, + pipe->screen, 1, - PIPE_BUFFER_USAGE_CONSTANT, + PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD, csc->vs_const_buf.size ); @@ -611,9 +617,9 @@ static int vlCreateDataBufs * Const buffer contains the color conversion matrix and bias vectors */ csc->fs_const_buf.size = sizeof(struct vlFragmentShaderConsts); - csc->fs_const_buf.buffer = pipe->winsys->buffer_create + csc->fs_const_buf.buffer = pipe_buffer_create ( - pipe->winsys, + pipe->screen, 1, PIPE_BUFFER_USAGE_CONSTANT, csc->fs_const_buf.size @@ -625,12 +631,12 @@ static int vlCreateDataBufs */ memcpy ( - pipe->winsys->buffer_map(pipe->winsys, csc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), + pipe_buffer_map(pipe->screen, csc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), &bt_601_full, sizeof(struct vlFragmentShaderConsts) ); - pipe->winsys->buffer_unmap(pipe->winsys, csc->fs_const_buf.buffer); + pipe_buffer_unmap(pipe->screen, csc->fs_const_buf.buffer); return 0; } diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c index c5a73b2bf2a..f0f82944737 100644 --- a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c +++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c @@ -297,6 +297,7 @@ static inline int vlGrabMacroBlock { assert(mc); assert(macroblock); + assert(mc->num_macroblocks < mc->macroblocks_per_picture); mc->macroblocks[mc->num_macroblocks].mbx = macroblock->mbx; mc->macroblocks[mc->num_macroblocks].mby = macroblock->mby; @@ -330,6 +331,7 @@ static inline int vlGrabMacroBlock } #define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, zb) \ + do { \ (vb)[0].pos.x = (mbx) * (unitx) + (ofsx); (vb)[0].pos.y = (mby) * (unity) + (ofsy); \ (vb)[1].pos.x = (mbx) * (unitx) + (ofsx); (vb)[1].pos.y = (mby) * (unity) + (ofsy) + (hy); \ (vb)[2].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].pos.y = (mby) * (unity) + (ofsy); \ @@ -392,7 +394,8 @@ static inline int vlGrabMacroBlock (vb)[3].cr_tc.x = (zb)[2].x + (hx); (vb)[3].cr_tc.y = (zb)[2].y; \ (vb)[4].cr_tc.x = (zb)[2].x; (vb)[4].cr_tc.y = (zb)[2].y + (hy); \ (vb)[5].cr_tc.x = (zb)[2].x + (hx); (vb)[5].cr_tc.y = (zb)[2].y + (hy); \ - } + } \ + } while (0) static inline int vlGenMacroblockVerts ( @@ -409,6 +412,7 @@ static inline int vlGenMacroblockVerts assert(mc); assert(macroblock); assert(ycbcr_vb); + assert(pos < mc->macroblocks_per_picture); switch (macroblock->mb_type) { @@ -581,6 +585,8 @@ static int vlFlush if (mc->num_macroblocks < mc->macroblocks_per_picture) return 0; + assert(mc->num_macroblocks <= mc->macroblocks_per_picture); + pipe = mc->pipe; for (i = 0; i < mc->num_macroblocks; ++i) @@ -599,19 +605,19 @@ static int vlFlush struct vlMacroBlockVertexStream0 *ycbcr_vb; struct vlVertex2f *ref_vb[2]; - ycbcr_vb = (struct vlMacroBlockVertexStream0*)mc->pipe->winsys->buffer_map + ycbcr_vb = (struct vlMacroBlockVertexStream0*)pipe_buffer_map ( - mc->pipe->winsys, + pipe->screen, mc->vertex_bufs.ycbcr.buffer, - PIPE_BUFFER_USAGE_CPU_WRITE + PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD ); for (i = 0; i < 2; ++i) - ref_vb[i] = (struct vlVertex2f*)mc->pipe->winsys->buffer_map + ref_vb[i] = (struct vlVertex2f*)pipe_buffer_map ( - mc->pipe->winsys, + pipe->screen, mc->vertex_bufs.ref[i].buffer, - PIPE_BUFFER_USAGE_CPU_WRITE + PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD ); for (i = 0; i < mc->num_macroblocks; ++i) @@ -623,15 +629,15 @@ static int vlFlush offset[mb_type_ex]++; } - mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs.ycbcr.buffer); + pipe_buffer_unmap(pipe->screen, mc->vertex_bufs.ycbcr.buffer); for (i = 0; i < 2; ++i) - mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs.ref[i].buffer); + pipe_buffer_unmap(pipe->screen, mc->vertex_bufs.ref[i].buffer); } for (i = 0; i < 3; ++i) { pipe_surface_unmap(mc->tex_surface[i]); - mc->pipe->screen->tex_surface_release(mc->pipe->screen, &mc->tex_surface[i]); + pipe_surface_reference(&mc->tex_surface[i], NULL); } mc->render_target.cbufs[0] = pipe->screen->get_tex_surface @@ -647,13 +653,13 @@ static int vlFlush ( pipe->winsys, mc->vs_const_buf.buffer, - PIPE_BUFFER_USAGE_CPU_WRITE + PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD ); vs_consts->denorm.x = mc->buffered_surface->texture->width[0]; vs_consts->denorm.y = mc->buffered_surface->texture->height[0]; - pipe->winsys->buffer_unmap(pipe->winsys, mc->vs_const_buf.buffer); + pipe_buffer_unmap(pipe->screen, mc->vs_const_buf.buffer); pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &mc->vs_const_buf); pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &mc->fs_const_buf); @@ -757,7 +763,7 @@ static int vlFlush } pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &mc->buffered_surface->render_fence); - pipe->screen->tex_surface_release(pipe->screen, &mc->render_target.cbufs[0]); + pipe_surface_reference(&mc->render_target.cbufs[0], NULL); for (i = 0; i < 3; ++i) mc->zero_block[i].x = -1.0f; @@ -808,10 +814,10 @@ static int vlRenderMacroBlocksMpeg2R16SnormBuffered ( mc->pipe->screen, mc->textures.all[i], - 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE + 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD ); - mc->texels[i] = pipe_surface_map(mc->tex_surface[i], PIPE_BUFFER_USAGE_CPU_WRITE); + mc->texels[i] = pipe_surface_map(mc->tex_surface[i], PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD); } } @@ -849,11 +855,11 @@ static int vlDestroy pipe->delete_sampler_state(pipe, mc->samplers.all[i]); for (i = 0; i < 3; ++i) - pipe->winsys->buffer_destroy(pipe->winsys, mc->vertex_bufs.all[i].buffer); + pipe_buffer_reference(pipe->screen, &mc->vertex_bufs.all[i].buffer, NULL); /* Textures 3 & 4 are not created directly, no need to release them here */ for (i = 0; i < 3; ++i) - pipe_texture_release(&mc->textures.all[i]); + pipe_texture_reference(&mc->textures.all[i], NULL); pipe->delete_vs_state(pipe, mc->i_vs); pipe->delete_fs_state(pipe, mc->i_fs); @@ -866,8 +872,8 @@ static int vlDestroy pipe->delete_fs_state(pipe, mc->b_fs[i]); } - pipe->winsys->buffer_destroy(pipe->winsys, mc->vs_const_buf.buffer); - pipe->winsys->buffer_destroy(pipe->winsys, mc->fs_const_buf.buffer); + pipe_buffer_reference(pipe->screen, &mc->vs_const_buf.buffer, NULL); + pipe_buffer_reference(pipe->screen, &mc->fs_const_buf.buffer, NULL); FREE(mc->macroblocks); FREE(mc); @@ -909,11 +915,11 @@ static int vlCreateDataBufs mc->vertex_bufs.ycbcr.pitch = sizeof(struct vlVertex2f) * 4; mc->vertex_bufs.ycbcr.max_index = 24 * mc->macroblocks_per_picture - 1; mc->vertex_bufs.ycbcr.buffer_offset = 0; - mc->vertex_bufs.ycbcr.buffer = pipe->winsys->buffer_create + mc->vertex_bufs.ycbcr.buffer = pipe_buffer_create ( - pipe->winsys, + pipe->screen, DEFAULT_BUF_ALIGNMENT, - PIPE_BUFFER_USAGE_VERTEX, + PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_DISCARD, sizeof(struct vlVertex2f) * 4 * 24 * mc->macroblocks_per_picture ); @@ -922,11 +928,11 @@ static int vlCreateDataBufs mc->vertex_bufs.all[i].pitch = sizeof(struct vlVertex2f) * 2; mc->vertex_bufs.all[i].max_index = 24 * mc->macroblocks_per_picture - 1; mc->vertex_bufs.all[i].buffer_offset = 0; - mc->vertex_bufs.all[i].buffer = pipe->winsys->buffer_create + mc->vertex_bufs.all[i].buffer = pipe_buffer_create ( - pipe->winsys, + pipe->screen, DEFAULT_BUF_ALIGNMENT, - PIPE_BUFFER_USAGE_VERTEX, + PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_DISCARD, sizeof(struct vlVertex2f) * 2 * 24 * mc->macroblocks_per_picture ); } @@ -981,18 +987,18 @@ static int vlCreateDataBufs /* Create our constant buffer */ mc->vs_const_buf.size = sizeof(struct vlVertexShaderConsts); - mc->vs_const_buf.buffer = pipe->winsys->buffer_create + mc->vs_const_buf.buffer = pipe_buffer_create ( - pipe->winsys, + pipe->screen, DEFAULT_BUF_ALIGNMENT, - PIPE_BUFFER_USAGE_CONSTANT, + PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD, mc->vs_const_buf.size ); mc->fs_const_buf.size = sizeof(struct vlFragmentShaderConsts); - mc->fs_const_buf.buffer = pipe->winsys->buffer_create + mc->fs_const_buf.buffer = pipe_buffer_create ( - pipe->winsys, + pipe->screen, DEFAULT_BUF_ALIGNMENT, PIPE_BUFFER_USAGE_CONSTANT, mc->fs_const_buf.size @@ -1000,12 +1006,12 @@ static int vlCreateDataBufs memcpy ( - pipe->winsys->buffer_map(pipe->winsys, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), + pipe_buffer_map(pipe->screen, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), &fs_consts, sizeof(struct vlFragmentShaderConsts) ); - pipe->winsys->buffer_unmap(pipe->winsys, mc->fs_const_buf.buffer); + pipe_buffer_unmap(pipe->screen, mc->fs_const_buf.buffer); mc->macroblocks = MALLOC(sizeof(struct vlMpeg2MacroBlock) * mc->macroblocks_per_picture); diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.c b/src/gallium/state_trackers/g3dvl/vl_surface.c index 911469f966a..0fa7b25b92e 100644 --- a/src/gallium/state_trackers/g3dvl/vl_surface.c +++ b/src/gallium/state_trackers/g3dvl/vl_surface.c @@ -51,6 +51,12 @@ int vlCreateSurface sfc->texture = vlGetPipeScreen(screen)->texture_create(vlGetPipeScreen(screen), &template); + if (!sfc->texture) + { + FREE(sfc); + return 1; + } + *surface = sfc; return 0; @@ -63,7 +69,7 @@ int vlDestroySurface { assert(surface); - pipe_texture_release(&surface->texture); + pipe_texture_reference(&surface->texture, NULL); FREE(surface); return 0; diff --git a/src/gallium/winsys/drm/Makefile.template b/src/gallium/winsys/drm/Makefile.template index 80e817b8082..211f4d875ed 100644 --- a/src/gallium/winsys/drm/Makefile.template +++ b/src/gallium/winsys/drm/Makefile.template @@ -84,14 +84,14 @@ default: depend symlinks $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME) $(LIBNAME_EGL) $(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/bin/mklib -noprefix -o $@ \ - $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS) + $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS) $(DRIVER_EXTRAS) $(LIBNAME_EGL): $(WINSYS_OBJECTS) $(LIBS) $(TOP)/bin/mklib -o $(LIBNAME_EGL) \ -linker "$(CC)" \ -noprefix \ $(OBJECTS) $(MKLIB_OPTIONS) $(WINSYS_OBJECTS) $(PIPE_DRIVERS) $(WINOBJ) $(DRI_LIB_DEPS) \ - --whole-archive $(LIBS) $(GALLIUM_AUXILIARIES) --no-whole-archive + --whole-archive $(LIBS) $(GALLIUM_AUXILIARIES) --no-whole-archive $(DRIVER_EXTRAS) $(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME) $(INSTALL) $(LIBNAME) $(TOP)/$(LIB_DIR) diff --git a/src/gallium/winsys/drm/intel/Makefile b/src/gallium/winsys/drm/intel/Makefile index a670ac044d0..eede9fc866c 100644 --- a/src/gallium/winsys/drm/intel/Makefile +++ b/src/gallium/winsys/drm/intel/Makefile @@ -2,7 +2,7 @@ TOP = ../../../../.. include $(TOP)/configs/current -SUBDIRS = common dri egl +SUBDIRS = gem egl default: subdirs diff --git a/src/gallium/winsys/drm/intel/egl/Makefile b/src/gallium/winsys/drm/intel/egl/Makefile index f0b5a443894..4b22d17ccfe 100644 --- a/src/gallium/winsys/drm/intel/egl/Makefile +++ b/src/gallium/winsys/drm/intel/egl/Makefile @@ -6,21 +6,23 @@ LIBNAME = EGL_i915.so PIPE_DRIVERS = \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a \ - ../common/libinteldrm.a + $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ + ../gem/libinteldrm.a DRIVER_SOURCES = \ - intel_swapbuffers.c \ intel_context.c \ intel_device.c \ - intel_egl.c + intel_api.c C_SOURCES = \ $(COMMON_GALLIUM_SOURCES) \ $(DRIVER_SOURCES) +DRIVER_EXTRAS = -ldrm_intel + ASM_SOURCES = -DRIVER_DEFINES = -I../common $(shell pkg-config libdrm --atleast-version=2.3.1 \ +DRIVER_DEFINES = -I../gem $(shell pkg-config libdrm --atleast-version=2.3.1 \ && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") include ../../Makefile.template diff --git a/src/gallium/winsys/drm/intel/egl/SConscript b/src/gallium/winsys/drm/intel/egl/SConscript deleted file mode 100644 index 0ad19d42a85..00000000000 --- a/src/gallium/winsys/drm/intel/egl/SConscript +++ /dev/null @@ -1,39 +0,0 @@ -Import('*') - -env = drienv.Clone() - -env.Append(CPPPATH = [ - '../intel', - 'server' -]) - -#MINIGLX_SOURCES = server/intel_dri.c - -DRIVER_SOURCES = [ - 'intel_winsys_pipe.c', - 'intel_winsys_softpipe.c', - 'intel_winsys_i915.c', - 'intel_batchbuffer.c', - 'intel_swapbuffers.c', - 'intel_context.c', - 'intel_lock.c', - 'intel_screen.c', - 'intel_batchpool.c', -] - -sources = \ - COMMON_GALLIUM_SOURCES + \ - COMMON_BM_SOURCES + \ - DRIVER_SOURCES - -drivers = [ - softpipe, - i915simple -] - -# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions -env.SharedLibrary( - target ='i915tex_dri.so', - source = sources, - LIBS = drivers + mesa + auxiliaries + env['LIBS'], -)
\ No newline at end of file diff --git a/src/gallium/winsys/drm/intel/egl/intel_api.c b/src/gallium/winsys/drm/intel/egl/intel_api.c new file mode 100644 index 00000000000..5dc4a7b052b --- /dev/null +++ b/src/gallium/winsys/drm/intel/egl/intel_api.c @@ -0,0 +1,10 @@ + +#include "intel_api.h" + +struct drm_api drm_api_hocks = +{ + .create_screen = intel_create_screen, + .create_context = intel_create_context, + .buffer_from_handle = intel_be_buffer_from_handle, + .handle_from_buffer = intel_be_handle_from_buffer, +}; diff --git a/src/gallium/winsys/drm/intel/egl/intel_api.h b/src/gallium/winsys/drm/intel/egl/intel_api.h new file mode 100644 index 00000000000..8ec165ab017 --- /dev/null +++ b/src/gallium/winsys/drm/intel/egl/intel_api.h @@ -0,0 +1,14 @@ + +#ifndef _INTEL_API_H_ +#define _INTEL_API_H_ + +#include "pipe/p_compiler.h" + +#include "state_tracker/drm_api.h" + +#include "intel_be_device.h" + +struct pipe_screen *intel_create_screen(int drmFD, int pciID); +struct pipe_context *intel_create_context(struct pipe_screen *screen); + +#endif diff --git a/src/gallium/winsys/drm/intel/egl/intel_batchbuffer.h b/src/gallium/winsys/drm/intel/egl/intel_batchbuffer.h deleted file mode 100644 index 3e953261689..00000000000 --- a/src/gallium/winsys/drm/intel/egl/intel_batchbuffer.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef INTEL_BATCHBUFFER_H -#define INTEL_BATCHBUFFER_H - -#include "intel_be_batchbuffer.h" - -/* - * Need to redefine the BATCH defines - */ - -#undef BEGIN_BATCH -#define BEGIN_BATCH(dwords, relocs) \ - (i915_batchbuffer_check(&intel->base.batch->base, dwords, relocs)) - -#undef OUT_BATCH -#define OUT_BATCH(d) \ - i915_batchbuffer_dword(&intel->base.batch->base, d) - -#undef OUT_RELOC -#define OUT_RELOC(buf,flags,mask,delta) do { \ - assert((delta) >= 0); \ - intel_be_offset_relocation(intel->base.batch, delta, buf, flags, mask); \ -} while (0) - -#endif diff --git a/src/gallium/winsys/drm/intel/egl/intel_context.c b/src/gallium/winsys/drm/intel/egl/intel_context.c index 927addb834c..57e5ff7bc12 100644 --- a/src/gallium/winsys/drm/intel/egl/intel_context.c +++ b/src/gallium/winsys/drm/intel/egl/intel_context.c @@ -1,119 +1,21 @@ -/************************************************************************** - * - * Copyright 2003 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 "i915simple/i915_screen.h" -#include "intel_device.h" -#include "intel_context.h" -#include "intel_batchbuffer.h" +#include "intel_be_device.h" +#include "intel_be_context.h" -#include "state_tracker/st_public.h" #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "intel_egl.h" -#include "utils.h" -#ifdef DEBUG -int __intel_debug = 0; -#endif +#include "intel_api.h" +struct intel_context +{ + struct intel_be_context base; -#define need_GL_ARB_multisample -#define need_GL_ARB_point_parameters -#define need_GL_ARB_texture_compression -#define need_GL_ARB_vertex_buffer_object -#define need_GL_ARB_vertex_program -#define need_GL_ARB_window_pos -#define need_GL_EXT_blend_color -#define need_GL_EXT_blend_equation_separate -#define need_GL_EXT_blend_func_separate -#define need_GL_EXT_blend_minmax -#define need_GL_EXT_cull_vertex -#define need_GL_EXT_fog_coord -#define need_GL_EXT_framebuffer_object -#define need_GL_EXT_multi_draw_arrays -#define need_GL_EXT_secondary_color -#define need_GL_NV_vertex_program -#include "extension_helper.h" - - -/** - * Extension strings exported by the intel driver. - * - * \note - * It appears that ARB_texture_env_crossbar has "disappeared" compared to the - * old i830-specific driver. - */ -const struct dri_extension card_extensions[] = { - {"GL_ARB_multisample", GL_ARB_multisample_functions}, - {"GL_ARB_multitexture", NULL}, - {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, - {"GL_ARB_texture_border_clamp", NULL}, - {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, - {"GL_ARB_texture_cube_map", NULL}, - {"GL_ARB_texture_env_add", NULL}, - {"GL_ARB_texture_env_combine", NULL}, - {"GL_ARB_texture_env_dot3", NULL}, - {"GL_ARB_texture_mirrored_repeat", NULL}, - {"GL_ARB_texture_rectangle", NULL}, - {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, - {"GL_ARB_pixel_buffer_object", NULL}, - {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, - {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, - {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, - {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, - {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, - {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, - {"GL_EXT_blend_subtract", NULL}, - {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, - {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, - {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, - {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, - {"GL_EXT_packed_depth_stencil", NULL}, - {"GL_EXT_pixel_buffer_object", NULL}, - {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions}, - {"GL_EXT_stencil_wrap", NULL}, - {"GL_EXT_texture_edge_clamp", NULL}, - {"GL_EXT_texture_env_combine", NULL}, - {"GL_EXT_texture_env_dot3", NULL}, - {"GL_EXT_texture_filter_anisotropic", NULL}, - {"GL_EXT_texture_lod_bias", NULL}, - {"GL_3DFX_texture_compression_FXT1", NULL}, - {"GL_APPLE_client_storage", NULL}, - {"GL_MESA_pack_invert", NULL}, - {"GL_MESA_ycbcr_texture", NULL}, - {"GL_NV_blend_square", NULL}, - {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, - {"GL_NV_vertex_program1_1", NULL}, - {"GL_SGIS_generate_mipmap", NULL }, - {NULL, NULL} + /* stuff */ }; - /* * Hardware lock functions. * Doesn't do anything in EGL @@ -142,101 +44,40 @@ intel_locked_hardware(struct intel_be_context *context) /* * Misc functions. */ +static void +intel_destroy_be_context(struct i915_winsys *winsys) +{ + struct intel_context *intel = (struct intel_context *)winsys; + + intel_be_destroy_context(&intel->base); + free(intel); +} -int -intel_create_context(struct egl_drm_context *egl_context, const __GLcontextModes *visual, void *sharedContextPrivate) +struct pipe_context * +intel_create_context(struct pipe_screen *screen) { - struct intel_context *intel = CALLOC_STRUCT(intel_context); - struct intel_device *device = (struct intel_device *)egl_context->device->priv; + struct intel_context *intel; struct pipe_context *pipe; - struct st_context *st_share = NULL; + struct intel_be_device *device = (struct intel_be_device *)screen->winsys; - egl_context->priv = intel; - - intel->intel_device = device; - intel->egl_context = egl_context; - intel->egl_device = egl_context->device; + intel = (struct intel_context *)malloc(sizeof(*intel)); + memset(intel, 0, sizeof(*intel)); intel->base.hardware_lock = intel_lock_hardware; intel->base.hardware_unlock = intel_unlock_hardware; intel->base.hardware_locked = intel_locked_hardware; - intel_be_init_context(&intel->base, &device->base); + intel_be_init_context(&intel->base, device); + + intel->base.base.destroy = intel_destroy_be_context; #if 0 pipe = intel_create_softpipe(intel, screen->winsys); #else - pipe = i915_create_context(device->pipe, &device->base.base, &intel->base.base); + pipe = i915_create_context(screen, &device->base, &intel->base.base); #endif pipe->priv = intel; - intel->st = st_create_context(pipe, visual, st_share); - - device->dummy = intel; - - return TRUE; -} - -int -intel_destroy_context(struct egl_drm_context *egl_context) -{ - struct intel_context *intel = egl_context->priv; - - if (intel->intel_device->dummy == intel) - intel->intel_device->dummy = NULL; - - st_destroy_context(intel->st); - intel_be_destroy_context(&intel->base); - free(intel); - return TRUE; -} - -void -intel_make_current(struct egl_drm_context *context, struct egl_drm_drawable *draw, struct egl_drm_drawable *read) -{ - if (context) { - struct intel_context *intel = (struct intel_context *)context->priv; - struct intel_framebuffer *draw_fb = (struct intel_framebuffer *)draw->priv; - struct intel_framebuffer *read_fb = (struct intel_framebuffer *)read->priv; - - assert(draw_fb->stfb); - assert(read_fb->stfb); - - st_make_current(intel->st, draw_fb->stfb, read_fb->stfb); - - intel->egl_drawable = draw; - - st_resize_framebuffer(draw_fb->stfb, draw->w, draw->h); - - if (draw != read) - st_resize_framebuffer(read_fb->stfb, read->w, read->h); - - } else { - st_make_current(NULL, NULL, NULL); - } -} - -void -intel_bind_frontbuffer(struct egl_drm_drawable *draw, struct egl_drm_frontbuffer *front) -{ - struct intel_device *device = (struct intel_device *)draw->device->priv; - struct intel_framebuffer *draw_fb = (struct intel_framebuffer *)draw->priv; - - if (draw_fb->front_buffer) - driBOUnReference(draw_fb->front_buffer); - - draw_fb->front_buffer = NULL; - draw_fb->front = NULL; - - /* to unbind just call this function with front == NULL */ - if (!front) - return; - - draw_fb->front = front; - - driGenBuffers(device->base.staticPool, "front", 1, &draw_fb->front_buffer, 0, 0, 0); - driBOSetReferenced(draw_fb->front_buffer, front->handle); - - st_resize_framebuffer(draw_fb->stfb, draw->w, draw->h); + return pipe; } diff --git a/src/gallium/winsys/drm/intel/egl/intel_context.h b/src/gallium/winsys/drm/intel/egl/intel_context.h deleted file mode 100644 index 477fdec7f70..00000000000 --- a/src/gallium/winsys/drm/intel/egl/intel_context.h +++ /dev/null @@ -1,118 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 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 INTEL_CONTEXT_H -#define INTEL_CONTEXT_H - -#include "pipe/p_debug.h" -#include "intel_be_context.h" - - -struct st_context; -struct egl_drm_device; -struct egl_drm_context; -struct egl_drm_frontbuffer; - - -/** - * Intel rendering context, contains a state tracker and intel-specific info. - */ -struct intel_context -{ - struct intel_be_context base; - - struct st_context *st; - - struct intel_device *intel_device; - - /* new egl stuff */ - struct egl_drm_device *egl_device; - struct egl_drm_context *egl_context; - struct egl_drm_drawable *egl_drawable; -}; - - - -/** - * Intel framebuffer. - */ -struct intel_framebuffer -{ - struct st_framebuffer *stfb; - - struct intel_device *device; - struct _DriBufferObject *front_buffer; - struct egl_drm_frontbuffer *front; -}; - - - - -/* These are functions now: - */ -void LOCK_HARDWARE( struct intel_context *intel ); -void UNLOCK_HARDWARE( struct intel_context *intel ); - -extern char *__progname; - - - -/* ================================================================ - * Debugging: - */ -#ifdef DEBUG -extern int __intel_debug; - -#define DEBUG_SWAP 0x1 -#define DEBUG_LOCK 0x2 -#define DEBUG_IOCTL 0x4 -#define DEBUG_BATCH 0x8 - -#define DBG(flag, ...) do { \ - if (__intel_debug & (DEBUG_##flag)) \ - printf(__VA_ARGS__); \ -} while(0) - -#else -#define DBG(flag, ...) -#endif - - -#define PCI_CHIP_845_G 0x2562 -#define PCI_CHIP_I830_M 0x3577 -#define PCI_CHIP_I855_GM 0x3582 -#define PCI_CHIP_I865_G 0x2572 -#define PCI_CHIP_I915_G 0x2582 -#define PCI_CHIP_I915_GM 0x2592 -#define PCI_CHIP_I945_G 0x2772 -#define PCI_CHIP_I945_GM 0x27A2 -#define PCI_CHIP_I945_GME 0x27AE -#define PCI_CHIP_G33_G 0x29C2 -#define PCI_CHIP_Q35_G 0x29B2 -#define PCI_CHIP_Q33_G 0x29D2 - -#endif diff --git a/src/gallium/winsys/drm/intel/egl/intel_device.c b/src/gallium/winsys/drm/intel/egl/intel_device.c index 1964745c994..6b281402d53 100644 --- a/src/gallium/winsys/drm/intel/egl/intel_device.c +++ b/src/gallium/winsys/drm/intel/egl/intel_device.c @@ -1,137 +1,48 @@ -/************************************************************************** - * - * Copyright 2003 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 "utils.h" - -#include "state_tracker/st_public.h" +#include <stdio.h> +#include "pipe/p_defines.h" +#include "intel_be_device.h" #include "i915simple/i915_screen.h" -#include "intel_context.h" -#include "intel_device.h" -#include "intel_batchbuffer.h" -#include "intel_egl.h" - - -extern const struct dri_extension card_extensions[]; - +#include "intel_api.h" -int -intel_create_device(struct egl_drm_device *device) +struct intel_device { - struct intel_device *intel_device; - - /* Allocate the private area */ - intel_device = CALLOC_STRUCT(intel_device); - if (!intel_device) - return FALSE; - - device->priv = (void *)intel_device; - intel_device->device = device; - - intel_device->deviceID = device->deviceID; - - intel_be_init_device(&intel_device->base, device->drmFD, intel_device->deviceID); + struct intel_be_device base; - intel_device->pipe = i915_create_screen(&intel_device->base.base, intel_device->deviceID); + int deviceID; +}; - /* hack */ - driInitExtensions(NULL, card_extensions, GL_FALSE); - - return TRUE; -} - -int -intel_destroy_device(struct egl_drm_device *device) +static void +intel_destroy_winsys(struct pipe_winsys *winsys) { - struct intel_device *intel_device = (struct intel_device *)device->priv; - - intel_be_destroy_device(&intel_device->base); + struct intel_device *dev = (struct intel_device *)winsys; - free(intel_device); - device->priv = NULL; + intel_be_destroy_device(&dev->base); - return TRUE; + free(dev); } -int -intel_create_drawable(struct egl_drm_drawable *drawable, - const __GLcontextModes * visual) +struct pipe_screen * +intel_create_screen(int drmFD, int deviceID) { - enum pipe_format colorFormat, depthFormat, stencilFormat; - struct intel_framebuffer *intelfb = CALLOC_STRUCT(intel_framebuffer); - - if (!intelfb) - return GL_FALSE; - - intelfb->device = drawable->device->priv; + struct intel_device *dev; + struct pipe_screen *screen; - if (visual->redBits == 5) - colorFormat = PIPE_FORMAT_R5G6B5_UNORM; - else - colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM; - - if (visual->depthBits == 16) - depthFormat = PIPE_FORMAT_Z16_UNORM; - else if (visual->depthBits == 24) - depthFormat = PIPE_FORMAT_S8Z24_UNORM; - else - depthFormat = PIPE_FORMAT_NONE; + /* Allocate the private area */ + dev = malloc(sizeof(*dev)); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); - if (visual->stencilBits == 8) - stencilFormat = PIPE_FORMAT_S8Z24_UNORM; - else - stencilFormat = PIPE_FORMAT_NONE; + dev->deviceID = deviceID; - intelfb->stfb = st_create_framebuffer(visual, - colorFormat, - depthFormat, - stencilFormat, - drawable->w, - drawable->h, - (void*) intelfb); + intel_be_init_device(&dev->base, drmFD, deviceID); - if (!intelfb->stfb) { - free(intelfb); - return GL_FALSE; - } + /* we need to hock our own destroy function in here */ + dev->base.base.destroy = intel_destroy_winsys; - drawable->priv = (void *) intelfb; - return GL_TRUE; -} - -int -intel_destroy_drawable(struct egl_drm_drawable *drawable) -{ - struct intel_framebuffer *intelfb = (struct intel_framebuffer *)drawable->priv; - drawable->priv = NULL; + screen = i915_create_screen(&dev->base.base, deviceID); - assert(intelfb->stfb); - st_unreference_framebuffer(intelfb->stfb); - free(intelfb); - return TRUE; + return screen; } diff --git a/src/gallium/winsys/drm/intel/egl/intel_device.h b/src/gallium/winsys/drm/intel/egl/intel_device.h deleted file mode 100644 index 323a7c2aef7..00000000000 --- a/src/gallium/winsys/drm/intel/egl/intel_device.h +++ /dev/null @@ -1,50 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 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 _INTEL_SCREEN_H_ -#define _INTEL_SCREEN_H_ - -#include "intel_be_device.h" - -#include "pipe/p_compiler.h" - -struct pipe_screen; -struct egl_drm_device; -struct intel_context; - -struct intel_device -{ - struct intel_be_device base; - struct pipe_screen *pipe; - - int deviceID; - struct egl_drm_device *device; - - struct intel_context *dummy; -}; - -#endif diff --git a/src/gallium/winsys/drm/intel/egl/intel_egl.c b/src/gallium/winsys/drm/intel/egl/intel_egl.c deleted file mode 100644 index ed464076ee3..00000000000 --- a/src/gallium/winsys/drm/intel/egl/intel_egl.c +++ /dev/null @@ -1,796 +0,0 @@ - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdint.h> - -#include "eglconfig.h" -#include "eglcontext.h" -#include "egldisplay.h" -#include "egldriver.h" -#include "eglglobals.h" -#include "eglmode.h" -#include "eglscreen.h" -#include "eglsurface.h" -#include "egllog.h" - -#include "intel_egl.h" - -#include "xf86drm.h" -#include "xf86drmMode.h" - -#include "intel_context.h" - -#include "state_tracker/st_public.h" - -#define MAX_SCREENS 16 - -static void -drm_get_device_id(struct egl_drm_device *device) -{ - char path[512]; - FILE *file; - - /* TODO get the real minor */ - int minor = 0; - - snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/device", minor); - file = fopen(path, "r"); - if (!file) { - _eglLog(_EGL_WARNING, "Could not retrive device ID\n"); - return; - } - - fgets(path, sizeof( path ), file); - sscanf(path, "%x", &device->deviceID); - fclose(file); -} - -static struct egl_drm_device* -egl_drm_create_device(int drmFD) -{ - struct egl_drm_device *device = malloc(sizeof(*device)); - memset(device, 0, sizeof(*device)); - device->drmFD = drmFD; - - device->version = drmGetVersion(device->drmFD); - - drm_get_device_id(device); - - if (!intel_create_device(device)) { - free(device); - return NULL; - } - - return device; -} - -static void -_egl_context_modes_destroy(__GLcontextModes *modes) -{ - _eglLog(_EGL_DEBUG, "%s", __FUNCTION__); - - while (modes) { - __GLcontextModes * const next = modes->next; - free(modes); - modes = next; - } -} -/** - * Create a linked list of 'count' GLcontextModes. - * These are used during the client/server visual negotiation phase, - * then discarded. - */ -static __GLcontextModes * -_egl_context_modes_create(unsigned count, size_t minimum_size) -{ - /* This code copied from libGLX, and modified */ - const size_t size = (minimum_size > sizeof(__GLcontextModes)) - ? minimum_size : sizeof(__GLcontextModes); - __GLcontextModes * head = NULL; - __GLcontextModes ** next; - unsigned i; - - _eglLog(_EGL_DEBUG, "%s %d %d", __FUNCTION__, count, minimum_size); - - next = & head; - for (i = 0 ; i < count ; i++) { - *next = (__GLcontextModes *) calloc(1, size); - if (*next == NULL) { - _egl_context_modes_destroy(head); - head = NULL; - break; - } - - (*next)->doubleBufferMode = 1; - (*next)->visualID = GLX_DONT_CARE; - (*next)->visualType = GLX_DONT_CARE; - (*next)->visualRating = GLX_NONE; - (*next)->transparentPixel = GLX_NONE; - (*next)->transparentRed = GLX_DONT_CARE; - (*next)->transparentGreen = GLX_DONT_CARE; - (*next)->transparentBlue = GLX_DONT_CARE; - (*next)->transparentAlpha = GLX_DONT_CARE; - (*next)->transparentIndex = GLX_DONT_CARE; - (*next)->xRenderable = GLX_DONT_CARE; - (*next)->fbconfigID = GLX_DONT_CARE; - (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; - (*next)->bindToTextureRgb = GLX_DONT_CARE; - (*next)->bindToTextureRgba = GLX_DONT_CARE; - (*next)->bindToMipmapTexture = GLX_DONT_CARE; - (*next)->bindToTextureTargets = 0; - (*next)->yInverted = GLX_DONT_CARE; - - next = & ((*next)->next); - } - - return head; -} - -struct drm_screen; - -struct drm_driver -{ - _EGLDriver base; /* base class/object */ - - drmModeResPtr res; - - struct drm_screen *screens[MAX_SCREENS]; - size_t count_screens; - - struct egl_drm_device *device; -}; - -struct drm_surface -{ - _EGLSurface base; /* base class/object */ - - struct egl_drm_drawable *drawable; -}; - -struct drm_context -{ - _EGLContext base; /* base class/object */ - - struct egl_drm_context *context; -}; - -struct drm_screen -{ - _EGLScreen base; - - /* currently only support one connector */ - drmModeConnectorPtr connector; - - /* Has this screen been shown */ - int shown; - - /* Surface that is currently attached to this screen */ - struct drm_surface *surf; - - /* backing buffer */ - drmBO buffer; - - /* framebuffer */ - drmModeFBPtr fb; - uint32_t fbID; - - /* crtc and mode used */ - drmModeCrtcPtr crtc; - uint32_t crtcID; - - struct drm_mode_modeinfo *mode; - - /* geometry of the screen */ - struct egl_drm_frontbuffer front; -}; - -static void -drm_update_res(struct drm_driver *drm_drv) -{ - drmModeFreeResources(drm_drv->res); - drm_drv->res = drmModeGetResources(drm_drv->device->drmFD); -} - -static void -drm_add_modes_from_connector(_EGLScreen *screen, drmModeConnectorPtr connector) -{ - struct drm_mode_modeinfo *m; - int i; - - for (i = 0; i < connector->count_modes; i++) { - m = &connector->modes[i]; - _eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name); - } -} - - -static EGLBoolean -drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) -{ - _EGLDisplay *disp = _eglLookupDisplay(dpy); - struct drm_driver *drm_drv = (struct drm_driver *)drv; - struct drm_screen *screen = NULL; - drmModeConnectorPtr connector = NULL; - drmModeResPtr res = NULL; - unsigned count_connectors = 0; - int num_screens = 0; - - EGLint i; - int fd; - - fd = drmOpen("i915", NULL); - if (fd < 0) { - return EGL_FALSE; - } - - drm_drv->device = egl_drm_create_device(fd); - if (!drm_drv->device) { - drmClose(fd); - return EGL_FALSE; - } - - drm_update_res(drm_drv); - res = drm_drv->res; - if (res) - count_connectors = res->count_connectors; - - for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) { - connector = drmModeGetConnector(fd, res->connectors[i]); - - if (!connector) - continue; - - if (connector->connection != DRM_MODE_CONNECTED) { - drmModeFreeConnector(connector); - continue; - } - - screen = malloc(sizeof(struct drm_screen)); - memset(screen, 0, sizeof(*screen)); - screen->connector = connector; - _eglInitScreen(&screen->base); - _eglAddScreen(disp, &screen->base); - drm_add_modes_from_connector(&screen->base, connector); - drm_drv->screens[num_screens++] = screen; - } - drm_drv->count_screens = num_screens; - - /* for now we only have one config */ - _EGLConfig *config = calloc(1, sizeof(*config)); - memset(config, 1, sizeof(*config)); - _eglInitConfig(config, 1); - _eglSetConfigAttrib(config, EGL_RED_SIZE, 8); - _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8); - _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8); - _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8); - _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32); - _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24); - _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8); - _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); - _eglAddConfig(disp, config); - - drv->Initialized = EGL_TRUE; - - *major = 1; - *minor = 4; - - return EGL_TRUE; -} - -static void -drm_takedown_shown_screen(_EGLDriver *drv, struct drm_screen *screen) -{ - struct drm_driver *drm_drv = (struct drm_driver *)drv; - unsigned int i; - - intel_bind_frontbuffer(screen->surf->drawable, NULL); - screen->surf = NULL; - - for (i = 0; i < drm_drv->res->count_crtcs; i++) { - drmModeSetCrtc( - drm_drv->device->drmFD, - drm_drv->res->crtcs[i], - 0, // FD - 0, 0, - NULL, 0, // List of output ids - NULL); - } - - drmModeRmFB(drm_drv->device->drmFD, screen->fbID); - drmModeFreeFB(screen->fb); - screen->fb = NULL; - - drmBOUnreference(drm_drv->device->drmFD, &screen->buffer); - - screen->shown = 0; -} - -static EGLBoolean -drm_terminate(_EGLDriver *drv, EGLDisplay dpy) -{ - struct drm_driver *drm_drv = (struct drm_driver *)drv; - struct drm_screen *screen; - int i = 0; - - intel_destroy_device(drm_drv->device); - drmFreeVersion(drm_drv->device->version); - - for (i = 0; i < drm_drv->count_screens; i++) { - screen = drm_drv->screens[i]; - - if (screen->shown) - drm_takedown_shown_screen(drv, screen); - - drmModeFreeConnector(screen->connector); - _eglDestroyScreen(&screen->base); - drm_drv->screens[i] = NULL; - } - - drmClose(drm_drv->device->drmFD); - - free(drm_drv->device); - - _eglCleanupDisplay(_eglLookupDisplay(dpy)); - free(drm_drv); - - return EGL_TRUE; -} - - -static struct drm_context * -lookup_drm_context(EGLContext context) -{ - _EGLContext *c = _eglLookupContext(context); - return (struct drm_context *) c; -} - - -static struct drm_surface * -lookup_drm_surface(EGLSurface surface) -{ - _EGLSurface *s = _eglLookupSurface(surface); - return (struct drm_surface *) s; -} - -static struct drm_screen * -lookup_drm_screen(EGLDisplay dpy, EGLScreenMESA screen) -{ - _EGLScreen *s = _eglLookupScreen(dpy, screen); - return (struct drm_screen *) s; -} - -static __GLcontextModes* -visual_from_config(_EGLConfig *conf) -{ - __GLcontextModes *visual; - (void)conf; - - visual = _egl_context_modes_create(1, sizeof(*visual)); - visual->redBits = 8; - visual->greenBits = 8; - visual->blueBits = 8; - visual->alphaBits = 8; - - visual->rgbBits = 32; - visual->doubleBufferMode = 1; - - visual->depthBits = 24; - visual->haveDepthBuffer = visual->depthBits > 0; - visual->stencilBits = 8; - visual->haveStencilBuffer = visual->stencilBits > 0; - - return visual; -} - - - -static EGLContext -drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) -{ - struct drm_driver *drm_drv = (struct drm_driver *)drv; - struct drm_context *c; - struct drm_egl_context *share = NULL; - _EGLConfig *conf; - int i; - int ret; - __GLcontextModes *visual; - struct egl_drm_context *context; - - conf = _eglLookupConfig(drv, dpy, config); - if (!conf) { - _eglError(EGL_BAD_CONFIG, "eglCreateContext"); - return EGL_NO_CONTEXT; - } - - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - /* no attribs defined for now */ - default: - _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext"); - return EGL_NO_CONTEXT; - } - } - - c = (struct drm_context *) calloc(1, sizeof(struct drm_context)); - if (!c) - return EGL_NO_CONTEXT; - - _eglInitContext(drv, dpy, &c->base, config, attrib_list); - - context = malloc(sizeof(*context)); - memset(context, 0, sizeof(*context)); - - if (!context) - goto err_c; - - context->device = drm_drv->device; - visual = visual_from_config(conf); - - ret = intel_create_context(context, visual, share); - free(visual); - - if (!ret) - goto err_gl; - - c->context = context; - - /* generate handle and insert into hash table */ - _eglSaveContext(&c->base); - assert(_eglGetContextHandle(&c->base)); - - return _eglGetContextHandle(&c->base); -err_gl: - free(context); -err_c: - free(c); - return EGL_NO_CONTEXT; -} - -static EGLBoolean -drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) -{ - struct drm_context *fc = lookup_drm_context(context); - _eglRemoveContext(&fc->base); - if (fc->base.IsBound) { - fc->base.DeletePending = EGL_TRUE; - } else { - intel_destroy_context(fc->context); - free(fc->context); - free(fc); - } - return EGL_TRUE; -} - - -static EGLSurface -drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) -{ - return EGL_NO_SURFACE; -} - - -static EGLSurface -drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) -{ - return EGL_NO_SURFACE; -} - - -static EGLSurface -drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, - const EGLint *attrib_list) -{ - struct drm_driver *drm_drv = (struct drm_driver *)drv; - int i; - int ret; - int width = -1; - int height = -1; - struct drm_surface *surf = NULL; - struct egl_drm_drawable *drawable = NULL; - __GLcontextModes *visual; - _EGLConfig *conf; - - conf = _eglLookupConfig(drv, dpy, config); - if (!conf) { - _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface"); - return EGL_NO_CONTEXT; - } - - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - case EGL_WIDTH: - width = attrib_list[++i]; - break; - case EGL_HEIGHT: - height = attrib_list[++i]; - break; - default: - _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface"); - return EGL_NO_SURFACE; - } - } - - if (width < 1 || height < 1) { - _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface"); - return EGL_NO_SURFACE; - } - - surf = (struct drm_surface *) calloc(1, sizeof(struct drm_surface)); - if (!surf) - goto err; - - if (!_eglInitSurface(drv, dpy, &surf->base, EGL_PBUFFER_BIT, config, attrib_list)) - goto err_surf; - - drawable = malloc(sizeof(*drawable)); - memset(drawable, 0, sizeof(*drawable)); - - drawable->w = width; - drawable->h = height; - - visual = visual_from_config(conf); - - drawable->device = drm_drv->device; - ret = intel_create_drawable(drawable, visual); - free(visual); - - if (!ret) - goto err_draw; - - surf->drawable = drawable; - - _eglSaveSurface(&surf->base); - return surf->base.Handle; - -err_draw: - free(drawable); -err_surf: - free(surf); -err: - return EGL_NO_SURFACE; -} - -static EGLSurface -drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, - const EGLint *attrib_list) -{ - EGLSurface surf = drm_create_pbuffer_surface(drv, dpy, cfg, attrib_list); - - return surf; -} - -static struct drm_mode_modeinfo * -drm_find_mode(drmModeConnectorPtr connector, _EGLMode *mode) -{ - int i; - struct drm_mode_modeinfo *m = NULL; - - for (i = 0; i < connector->count_modes; i++) { - m = &connector->modes[i]; - if (m->hdisplay == mode->Width && m->vdisplay == mode->Height && m->vrefresh == mode->RefreshRate) - break; - m = &connector->modes[0]; /* if we can't find one, return first */ - } - - return m; -} -static void -draw(size_t x, size_t y, size_t w, size_t h, size_t pitch, size_t v, unsigned int *ptr) -{ - int i, j; - - for (i = x; i < x + w; i++) - for(j = y; j < y + h; j++) - ptr[(i * pitch / 4) + j] = v; - -} - -static void -prettyColors(int fd, unsigned int handle, size_t pitch) -{ - drmBO bo; - unsigned int *ptr; - void *p; - int i; - - drmBOReference(fd, handle, &bo); - drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &p); - ptr = (unsigned int*)p; - - for (i = 0; i < (bo.size / 4); i++) - ptr[i] = 0xFFFFFFFF; - - for (i = 0; i < 4; i++) - draw(i * 40, i * 40, 40, 40, pitch, 0, ptr); - - - draw(200, 100, 40, 40, pitch, 0xff00ff, ptr); - draw(100, 200, 40, 40, pitch, 0xff00ff, ptr); - - drmBOUnmap(fd, &bo); -} - -static EGLBoolean -drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, - EGLScreenMESA screen, - EGLSurface surface, EGLModeMESA m) -{ - struct drm_driver *drm_drv = (struct drm_driver *)drv; - struct drm_surface *surf = lookup_drm_surface(surface); - struct drm_screen *scrn = lookup_drm_screen(dpy, screen); - _EGLMode *mode = _eglLookupMode(dpy, m); - size_t pitch = mode->Width * 4; - size_t size = mode->Height * pitch; - int ret; - unsigned int i,j,k; - - if (scrn->shown) - drm_takedown_shown_screen(drv, scrn); - - ret = drmBOCreate(drm_drv->device->drmFD, size, 0, 0, - DRM_BO_FLAG_READ | - DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_MEM_TT | - DRM_BO_FLAG_MEM_VRAM | - DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, &scrn->buffer); - - if (ret) - return EGL_FALSE; - - prettyColors(drm_drv->device->drmFD, scrn->buffer.handle, pitch); - - ret = drmModeAddFB(drm_drv->device->drmFD, mode->Width, mode->Height, - 32, 32, pitch, - scrn->buffer.handle, - &scrn->fbID); - - if (ret) - goto err_bo; - - scrn->fb = drmModeGetFB(drm_drv->device->drmFD, scrn->fbID); - if (!scrn->fb) - goto err_bo; - - for (j = 0; j < drm_drv->res->count_connectors; j++) { - drmModeConnector *con = drmModeGetConnector(drm_drv->device->drmFD, drm_drv->res->connectors[j]); - scrn->mode = drm_find_mode(con, mode); - if (!scrn->mode) - goto err_fb; - - for (k = 0; k < con->count_encoders; k++) { - drmModeEncoder *enc = drmModeGetEncoder(drm_drv->device->drmFD, con->encoders[k]); - for (i = 0; i < drm_drv->res->count_crtcs; i++) { - if (enc->possible_crtcs & (1<<i)) { - ret = drmModeSetCrtc( - drm_drv->device->drmFD, - drm_drv->res->crtcs[i], - scrn->fbID, - 0, 0, - &drm_drv->res->connectors[j], 1, - scrn->mode); - /* skip the other crtcs now */ - i = drm_drv->res->count_crtcs; - } - } - } - } - - scrn->front.handle = scrn->buffer.handle; - scrn->front.pitch = pitch; - scrn->front.width = mode->Width; - scrn->front.height = mode->Height; - - scrn->surf = surf; - intel_bind_frontbuffer(surf->drawable, &scrn->front); - - scrn->shown = 1; - - return EGL_TRUE; - -err_fb: - /* TODO remove fb */ - -err_bo: - drmBOUnreference(drm_drv->device->drmFD, &scrn->buffer); - return EGL_FALSE; -} - -static EGLBoolean -drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) -{ - struct drm_surface *fs = lookup_drm_surface(surface); - _eglRemoveSurface(&fs->base); - if (fs->base.IsBound) { - fs->base.DeletePending = EGL_TRUE; - } else { - intel_bind_frontbuffer(fs->drawable, NULL); - intel_destroy_drawable(fs->drawable); - free(fs->drawable); - free(fs); - } - return EGL_TRUE; -} - - -static EGLBoolean -drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context) -{ - struct drm_surface *readSurf = lookup_drm_surface(read); - struct drm_surface *drawSurf = lookup_drm_surface(draw); - struct drm_context *ctx = lookup_drm_context(context); - EGLBoolean b; - - b = _eglMakeCurrent(drv, dpy, draw, read, context); - if (!b) - return EGL_FALSE; - - if (ctx) { - if (!drawSurf || !readSurf) - return EGL_FALSE; - - intel_make_current(ctx->context, drawSurf->drawable, readSurf->drawable); - } else { - intel_make_current(NULL, NULL, NULL); - } - - return EGL_TRUE; -} - -static EGLBoolean -drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) -{ - struct drm_surface *surf = lookup_drm_surface(draw); - if (!surf) - return EGL_FALSE; - - /* error checking */ - if (!_eglSwapBuffers(drv, dpy, draw)) - return EGL_FALSE; - - intel_swap_buffers(surf->drawable); - return EGL_TRUE; -} - - -/** - * The bootstrap function. Return a new drm_driver object and - * plug in API functions. - */ -_EGLDriver * -_eglMain(_EGLDisplay *dpy, const char *args) -{ - struct drm_driver *drm; - - drm = (struct drm_driver *) calloc(1, sizeof(struct drm_driver)); - if (!drm) { - return NULL; - } - - /* First fill in the dispatch table with defaults */ - _eglInitDriverFallbacks(&drm->base); - /* then plug in our Drm-specific functions */ - drm->base.API.Initialize = drm_initialize; - drm->base.API.Terminate = drm_terminate; - drm->base.API.CreateContext = drm_create_context; - drm->base.API.MakeCurrent = drm_make_current; - drm->base.API.CreateWindowSurface = drm_create_window_surface; - drm->base.API.CreatePixmapSurface = drm_create_pixmap_surface; - drm->base.API.CreatePbufferSurface = drm_create_pbuffer_surface; - drm->base.API.DestroySurface = drm_destroy_surface; - drm->base.API.DestroyContext = drm_destroy_context; - drm->base.API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa; - drm->base.API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa; - drm->base.API.SwapBuffers = drm_swap_buffers; - - drm->base.ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/; - drm->base.Name = "DRM/Gallium"; - - /* enable supported extensions */ - drm->base.Extensions.MESA_screen_surface = EGL_TRUE; - drm->base.Extensions.MESA_copy_context = EGL_TRUE; - - return &drm->base; -} diff --git a/src/gallium/winsys/drm/intel/egl/intel_egl.h b/src/gallium/winsys/drm/intel/egl/intel_egl.h deleted file mode 100644 index 1ee27e0847a..00000000000 --- a/src/gallium/winsys/drm/intel/egl/intel_egl.h +++ /dev/null @@ -1,53 +0,0 @@ - -#ifndef _INTEL_EGL_H_ -#define _INTEL_EGL_H_ - -#include <xf86drm.h> - -struct egl_drm_device -{ - void *priv; - int drmFD; - - drmVersionPtr version; - int deviceID; -}; - -struct egl_drm_context -{ - void *priv; - struct egl_drm_device *device; -}; - -struct egl_drm_drawable -{ - void *priv; - struct egl_drm_device *device; - size_t h; - size_t w; -}; - -struct egl_drm_frontbuffer -{ - uint32_t handle; - uint32_t pitch; - uint32_t width; - uint32_t height; -}; - -#include "GL/internal/glcore.h" - -int intel_create_device(struct egl_drm_device *device); -int intel_destroy_device(struct egl_drm_device *device); - -int intel_create_context(struct egl_drm_context *context, const __GLcontextModes *visual, void *sharedContextPrivate); -int intel_destroy_context(struct egl_drm_context *context); - -int intel_create_drawable(struct egl_drm_drawable *drawable, const __GLcontextModes * visual); -int intel_destroy_drawable(struct egl_drm_drawable *drawable); - -void intel_make_current(struct egl_drm_context *context, struct egl_drm_drawable *draw, struct egl_drm_drawable *read); -void intel_swap_buffers(struct egl_drm_drawable *draw); -void intel_bind_frontbuffer(struct egl_drm_drawable *draw, struct egl_drm_frontbuffer *front); - -#endif diff --git a/src/gallium/winsys/drm/intel/egl/intel_reg.h b/src/gallium/winsys/drm/intel/egl/intel_reg.h deleted file mode 100644 index 4f33bee4385..00000000000 --- a/src/gallium/winsys/drm/intel/egl/intel_reg.h +++ /dev/null @@ -1,53 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 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 _INTEL_REG_H_ -#define _INTEL_REG_H_ - - -#define BR00_BITBLT_CLIENT 0x40000000 -#define BR00_OP_COLOR_BLT 0x10000000 -#define BR00_OP_SRC_COPY_BLT 0x10C00000 -#define BR13_SOLID_PATTERN 0x80000000 - -#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|0x4) -#define XY_COLOR_BLT_WRITE_ALPHA (1<<21) -#define XY_COLOR_BLT_WRITE_RGB (1<<20) - -#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) -#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) -#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) - -#define MI_WAIT_FOR_EVENT ((0x3<<23)) -#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) -#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) - -#define MI_BATCH_BUFFER_END (0xA<<23) - - -#endif diff --git a/src/gallium/winsys/drm/intel/egl/intel_swapbuffers.c b/src/gallium/winsys/drm/intel/egl/intel_swapbuffers.c deleted file mode 100644 index 2edcbc79fff..00000000000 --- a/src/gallium/winsys/drm/intel/egl/intel_swapbuffers.c +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 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 "intel_device.h" -#include "intel_context.h" -#include "intel_batchbuffer.h" -#include "intel_reg.h" - -#include "pipe/p_context.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_cb_fbo.h" -#include "intel_egl.h" - - -static void -intel_display_surface(struct egl_drm_drawable *draw, - struct pipe_surface *surf); - -void intel_swap_buffers(struct egl_drm_drawable *draw) -{ - struct intel_framebuffer *intel_fb = (struct intel_framebuffer *)draw->priv; - struct pipe_surface *back_surf; - - assert(intel_fb); - assert(intel_fb->stfb); - - back_surf = st_get_framebuffer_surface(intel_fb->stfb, ST_SURFACE_BACK_LEFT); - if (back_surf) { - st_notify_swapbuffers(intel_fb->stfb); - if (intel_fb->front) - intel_display_surface(draw, back_surf); - st_notify_swapbuffers_complete(intel_fb->stfb); - } -} - -static void -intel_display_surface(struct egl_drm_drawable *draw, - struct pipe_surface *surf) -{ - struct intel_context *intel = NULL; - struct intel_framebuffer *intel_fb = (struct intel_framebuffer *)draw->priv; - struct _DriFenceObject *fence; - - //const int srcWidth = surf->width; - //const int srcHeight = surf->height; - - intel = intel_fb->device->dummy; - if (!intel) { - printf("No dummy context\n"); - return; - } - - const int dstWidth = intel_fb->front->width; - const int dstHeight = intel_fb->front->height; - const int dstPitch = intel_fb->front->pitch / 4;//draw->front.cpp; - - const int cpp = 4;//intel_fb->front->cpp; - const int srcPitch = surf->stride / cpp; - - int BR13, CMD; - //int i; - - BR13 = (dstPitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); - CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - - BEGIN_BATCH(8, 2); - OUT_BATCH(CMD); - OUT_BATCH(BR13); - OUT_BATCH((0 << 16) | 0); - OUT_BATCH((dstHeight << 16) | dstWidth); - - OUT_RELOC(intel_fb->front_buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); - - OUT_BATCH((0 << 16) | 0); - OUT_BATCH((srcPitch * cpp) & 0xffff); - OUT_RELOC(dri_bo(surf->buffer), - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); - - fence = intel_be_batchbuffer_flush(intel->base.batch); - driFenceUnReference(&fence); - intel_be_batchbuffer_finish(intel->base.batch); -} diff --git a/src/gallium/winsys/drm/intel/gem/Makefile b/src/gallium/winsys/drm/intel/gem/Makefile new file mode 100644 index 00000000000..b25fc258f45 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/Makefile @@ -0,0 +1,18 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = inteldrm + +C_SOURCES = \ + intel_be_batchbuffer.c \ + intel_be_context.c \ + intel_be_device.c + + +include ./Makefile.template + +DRIVER_DEFINES = $(shell pkg-config libdrm --cflags \ + && pkg-config libdrm --atleast-version=2.3.1 \ + && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") +symlinks: + diff --git a/src/gallium/winsys/drm/intel/gem/Makefile.template b/src/gallium/winsys/drm/intel/gem/Makefile.template new file mode 100644 index 00000000000..557070ae02a --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/Makefile.template @@ -0,0 +1,64 @@ +# -*-makefile-*- + + +# We still have a dependency on the "dri" buffer manager. Most likely +# the interface can be reused in non-dri environments, and also as a +# frontend to simpler memory managers. +# +COMMON_SOURCES = + +OBJECTS = $(C_SOURCES:.c=.o) \ + $(CPP_SOURCES:.cpp=.o) \ + $(ASM_SOURCES:.S=.o) + + +### Include directories +INCLUDES = \ + -I. \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/include \ + $(DRIVER_INCLUDES) + + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + +.cpp.o: + $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@ + +.S.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + + +##### TARGETS ##### + +default: depend symlinks $(LIBNAME) + + +$(LIBNAME): $(OBJECTS) Makefile Makefile.template + $(TOP)/bin/mklib -o $@ -static $(OBJECTS) $(DRIVER_LIBS) + + +depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS) + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) $(CPP_SOURCES) \ + $(ASM_SOURCES) 2> /dev/null + + +# Emacs tags +tags: + etags `find . -name \*.[ch]` `find ../include` + + +# Remove .o and backup files +clean:: + -rm -f *.o */*.o *~ *.so *.a *~ server/*.o $(SYMLINKS) + -rm -f depend depend.bak + + +include depend diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c new file mode 100644 index 00000000000..e83a4c42cd0 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c @@ -0,0 +1,139 @@ + +#include "intel_be_batchbuffer.h" +#include "intel_be_context.h" +#include "intel_be_device.h" +#include "intel_be_fence.h" +#include <errno.h> + +#include "util/u_memory.h" + +struct intel_be_batchbuffer * +intel_be_batchbuffer_alloc(struct intel_be_context *intel) +{ + struct intel_be_batchbuffer *batch = CALLOC_STRUCT(intel_be_batchbuffer); + + + batch->base.buffer = NULL; + batch->base.winsys = &intel->base; + batch->base.map = NULL; + batch->base.ptr = NULL; + batch->base.size = 0; + batch->base.actual_size = intel->device->max_batch_size; + batch->base.relocs = 0; + batch->base.max_relocs = INTEL_DEFAULT_RELOCS; + + batch->base.map = malloc(batch->base.actual_size); + memset(batch->base.map, 0, batch->base.actual_size); + + batch->base.ptr = batch->base.map; + + intel_be_batchbuffer_reset(batch); + + return batch; +} + +void +intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch) +{ + struct intel_be_context *intel = intel_be_context(batch->base.winsys); + struct intel_be_device *dev = intel->device; + + if (batch->bo) + drm_intel_bo_unreference(batch->bo); + + memset(batch->base.map, 0, batch->base.actual_size); + batch->base.ptr = batch->base.map; + batch->base.size = batch->base.actual_size - BATCH_RESERVED; + + batch->base.relocs = 0; + batch->base.max_relocs = INTEL_DEFAULT_RELOCS; + + batch->bo = drm_intel_bo_alloc(dev->pools.gem, + "gallium3d_batch_buffer", + batch->base.actual_size, 0); +} + +int +intel_be_offset_relocation(struct intel_be_batchbuffer *batch, + unsigned pre_add, + drm_intel_bo *bo, + uint32_t read_domains, + uint32_t write_domain) +{ + unsigned offset; + int ret = 0; + + assert(batch->base.relocs < batch->base.max_relocs); + + offset = (unsigned)(batch->base.ptr - batch->base.map); + batch->base.ptr += 4; + + ret = drm_intel_bo_emit_reloc(bo, pre_add, + batch->bo, offset, + read_domains, + write_domain); + + if (!ret) + batch->base.relocs++; + + return ret; +} + +void +intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch, + struct intel_be_fence **fence) +{ + struct i915_batchbuffer *i915 = &batch->base; + unsigned used = 0; + int ret = 0; + + assert(i915_batchbuffer_space(i915) >= 0); + + used = batch->base.ptr - batch->base.map; + assert((used & 3) == 0); + + if (used & 4) { + ((uint32_t *) batch->base.ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH; + ((uint32_t *) batch->base.ptr)[1] = 0; + ((uint32_t *) batch->base.ptr)[2] = (0xA<<23); // MI_BATCH_BUFFER_END; + batch->base.ptr += 12; + } else { + ((uint32_t *) batch->base.ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH; + ((uint32_t *) batch->base.ptr)[1] = (0xA<<23); // MI_BATCH_BUFFER_END; + batch->base.ptr += 8; + } + + used = batch->base.ptr - batch->base.map; + + drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map); + ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); + + assert(ret == 0); + + intel_be_batchbuffer_reset(batch); + + if (fence) { + if (*fence) + intel_be_fence_unreference(*fence); + + (*fence) = CALLOC_STRUCT(intel_be_fence); + (*fence)->refcount = 1; + (*fence)->bo = NULL; + } +} + +void +intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch) +{ + +} + +void +intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch) +{ + if (batch->bo) + drm_intel_bo_unreference(batch->bo); + + free(batch->base.map); + free(batch); +} diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h new file mode 100644 index 00000000000..195bf8dee77 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h @@ -0,0 +1,55 @@ + +#ifndef INTEL_BE_BATCHBUFFER_H +#define INTEL_BE_BATCHBUFFER_H + +#include "i915simple/i915_batch.h" + +#include "drm.h" +#include "intel_bufmgr.h" + +#define BATCH_RESERVED 16 + +#define INTEL_DEFAULT_RELOCS 100 +#define INTEL_MAX_RELOCS 400 + +#define INTEL_BATCH_NO_CLIPRECTS 0x1 +#define INTEL_BATCH_CLIPRECTS 0x2 + +struct intel_be_context; +struct intel_be_device; +struct intel_be_fence; + +struct intel_be_batchbuffer +{ + struct i915_batchbuffer base; + + struct intel_be_context *intel; + struct intel_be_device *device; + + drm_intel_bo *bo; +}; + +struct intel_be_batchbuffer * +intel_be_batchbuffer_alloc(struct intel_be_context *intel); + +void +intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch); + +void +intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch); + +void +intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch, + struct intel_be_fence **fence); + +void +intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch); + +int +intel_be_offset_relocation(struct intel_be_batchbuffer *batch, + unsigned pre_add, + drm_intel_bo *bo, + uint32_t read_domains, + uint32_t write_doman); + +#endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_context.c b/src/gallium/winsys/drm/intel/gem/intel_be_context.c new file mode 100644 index 00000000000..3e472e1e433 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_be_context.c @@ -0,0 +1,78 @@ + +#include "intel_be_device.h" +#include "intel_be_context.h" +#include "intel_be_batchbuffer.h" + +#include "i915_drm.h" + +static struct i915_batchbuffer * +intel_be_batch_get(struct i915_winsys *sws) +{ + struct intel_be_context *intel = intel_be_context(sws); + return &intel->batch->base; +} + +static void +intel_be_batch_reloc(struct i915_winsys *sws, + struct pipe_buffer *buf, + unsigned access_flags, + unsigned delta) +{ + struct intel_be_context *intel = intel_be_context(sws); + drm_intel_bo *bo = intel_bo(buf); + int ret; + uint32_t read = 0; + uint32_t write = 0; + + if (access_flags & I915_BUFFER_ACCESS_WRITE) { + write = I915_GEM_DOMAIN_RENDER; + } + + if (access_flags & I915_BUFFER_ACCESS_READ) { + read = I915_GEM_DOMAIN_SAMPLER | + I915_GEM_DOMAIN_VERTEX; + } + + ret = intel_be_offset_relocation(intel->batch, + delta, + bo, + read, + write); + /* TODO change return type */ + /* return ret; */ +} + +static void +intel_be_batch_flush(struct i915_winsys *sws, + struct pipe_fence_handle **fence) +{ + struct intel_be_context *intel = intel_be_context(sws); + struct intel_be_fence **f = (struct intel_be_fence **)fence; + + if (fence && *fence) + assert(0); + + intel_be_batchbuffer_flush(intel->batch, f); +} + +boolean +intel_be_init_context(struct intel_be_context *intel, struct intel_be_device *device) +{ + assert(intel); + assert(device); + intel->device = device; + + intel->base.batch_get = intel_be_batch_get; + intel->base.batch_reloc = intel_be_batch_reloc; + intel->base.batch_flush = intel_be_batch_flush; + + intel->batch = intel_be_batchbuffer_alloc(intel); + + return true; +} + +void +intel_be_destroy_context(struct intel_be_context *intel) +{ + intel_be_batchbuffer_free(intel->batch); +} diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_context.h b/src/gallium/winsys/drm/intel/gem/intel_be_context.h new file mode 100644 index 00000000000..9cee1a4e52b --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_be_context.h @@ -0,0 +1,48 @@ + +#ifndef INTEL_BE_CONTEXT_H +#define INTEL_BE_CONTEXT_H + +#include "i915simple/i915_winsys.h" + +struct intel_be_context +{ + /** Interface to i915simple driver */ + struct i915_winsys base; + + struct intel_be_device *device; + struct intel_be_batchbuffer *batch; + + /* + * Hardware lock functions. + * + * Needs to be filled in by the winsys. + */ + void (*hardware_lock)(struct intel_be_context *context); + void (*hardware_unlock)(struct intel_be_context *context); + boolean (*hardware_locked)(struct intel_be_context *context); +}; + +static INLINE struct intel_be_context * +intel_be_context(struct i915_winsys *sws) +{ + return (struct intel_be_context *)sws; +} + +/** + * Intialize a allocated intel_be_context struct. + * + * Remember to set the hardware_* functions. + */ +boolean +intel_be_init_context(struct intel_be_context *intel, + struct intel_be_device *device); + +/** + * Destroy a intel_be_context. + * + * Does not free the struct that is up to the winsys. + */ +void +intel_be_destroy_context(struct intel_be_context *intel); + +#endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.c b/src/gallium/winsys/drm/intel/gem/intel_be_device.c new file mode 100644 index 00000000000..201a4850498 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_be_device.c @@ -0,0 +1,267 @@ + +#include "intel_be_device.h" + +#include "pipe/p_winsys.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" +#include "util/u_memory.h" + +#include "intel_be_fence.h" + +#include "i915simple/i915_screen.h" + + +/** + * Turn a pipe winsys into an intel/pipe winsys: + */ +static INLINE struct intel_be_device * +intel_be_device(struct pipe_winsys *winsys) +{ + return (struct intel_be_device *)winsys; +} + +/* + * Buffer + */ + +static void * +intel_be_buffer_map(struct pipe_winsys *winsys, + struct pipe_buffer *buf, + unsigned flags) +{ + drm_intel_bo *bo = intel_bo(buf); + int write = 0; + int ret; + + if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) + write = 1; + + ret = drm_intel_bo_map(bo, write); + + if (ret) + return NULL; + + return bo->virtual; +} + +static void +intel_be_buffer_unmap(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + drm_intel_bo_unmap(intel_bo(buf)); +} + +static void +intel_be_buffer_destroy(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + drm_intel_bo_unreference(intel_bo(buf)); + free(buf); +} + +static struct pipe_buffer * +intel_be_buffer_create(struct pipe_winsys *winsys, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer); + struct intel_be_device *dev = intel_be_device(winsys); + drm_intel_bufmgr *pool; + char *name; + + if (!buffer) + return NULL; + + buffer->base.refcount = 1; + buffer->base.alignment = alignment; + buffer->base.usage = usage; + buffer->base.size = size; + + if (usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_CONSTANT)) { + /* Local buffer */ + name = "gallium3d_local"; + pool = dev->pools.gem; + } else if (usage & PIPE_BUFFER_USAGE_CUSTOM) { + /* For vertex buffers */ + name = "gallium3d_internal_vertex"; + pool = dev->pools.gem; + } else { + /* Regular buffers */ + name = "gallium3d_regular"; + pool = dev->pools.gem; + } + + buffer->bo = drm_intel_bo_alloc(pool, name, size, alignment); + + if (!buffer->bo) + goto err; + + return &buffer->base; + +err: + free(buffer); + return NULL; +} + +static struct pipe_buffer * +intel_be_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes) +{ + struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer); + struct intel_be_device *dev = intel_be_device(winsys); + int ret; + + if (!buffer) + return NULL; + + buffer->base.refcount = 1; + buffer->base.alignment = 0; + buffer->base.usage = 0; + buffer->base.size = bytes; + + buffer->bo = drm_intel_bo_alloc(dev->pools.gem, + "gallium3d_user_buffer", + bytes, 0); + + if (!buffer->bo) + goto err; + + ret = drm_intel_bo_subdata(buffer->bo, + 0, bytes, ptr); + + if (ret) + goto err; + + return &buffer->base; + +err: + free(buffer); + return NULL; +} + +struct pipe_buffer * +intel_be_buffer_from_handle(struct pipe_winsys *winsys, + const char* name, unsigned handle) +{ + struct intel_be_device *dev = intel_be_device(winsys); + struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer); + + if (!buffer) + return NULL; + + buffer->bo = drm_intel_bo_gem_create_from_name(dev->pools.gem, name, handle); + + if (!buffer->bo) + goto err; + + buffer->base.refcount = 1; + buffer->base.alignment = buffer->bo->align; + buffer->base.usage = PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE | + PIPE_BUFFER_USAGE_CPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE; + buffer->base.size = buffer->bo->size; + + return &buffer->base; + +err: + free(buffer); + return NULL; +} + +unsigned +intel_be_handle_from_buffer(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + drm_intel_bo *bo = intel_bo(buf); + return bo->handle; +} + +/* + * Fence + */ + +static void +intel_be_fence_refunref(struct pipe_winsys *sws, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + struct intel_be_fence **p = (struct intel_be_fence **)ptr; + struct intel_be_fence *f = (struct intel_be_fence *)fence; + + assert(p); + + if (f) + intel_be_fence_reference(f); + + if (*p) + intel_be_fence_unreference(*p); + + *p = f; +} + +static int +intel_be_fence_signalled(struct pipe_winsys *sws, + struct pipe_fence_handle *fence, + unsigned flag) +{ + assert(0); + + return 0; +} + +static int +intel_be_fence_finish(struct pipe_winsys *sws, + struct pipe_fence_handle *fence, + unsigned flag) +{ + struct intel_be_fence *f = (struct intel_be_fence *)fence; + + /* fence already expired */ + if (!f->bo) + return 0; + + drm_intel_bo_wait_rendering(f->bo); + drm_intel_bo_unreference(f->bo); + f->bo = NULL; + + return 0; +} + +/* + * Misc functions + */ + +boolean +intel_be_init_device(struct intel_be_device *dev, int fd, unsigned id) +{ + dev->fd = fd; + dev->max_batch_size = 16 * 4096; + dev->max_vertex_size = 128 * 4096; + + dev->base.buffer_create = intel_be_buffer_create; + dev->base.user_buffer_create = intel_be_user_buffer_create; + dev->base.buffer_map = intel_be_buffer_map; + dev->base.buffer_unmap = intel_be_buffer_unmap; + dev->base.buffer_destroy = intel_be_buffer_destroy; + + /* Not used anymore */ + dev->base.surface_alloc = NULL; + dev->base.surface_alloc_storage = NULL; + dev->base.surface_release = NULL; + + dev->base.fence_reference = intel_be_fence_refunref; + dev->base.fence_signalled = intel_be_fence_signalled; + dev->base.fence_finish = intel_be_fence_finish; + + dev->pools.gem = drm_intel_bufmgr_gem_init(dev->fd, dev->max_batch_size); + + return true; +} + +void +intel_be_destroy_device(struct intel_be_device *dev) +{ + drm_intel_bufmgr_destroy(dev->pools.gem); +} diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.h b/src/gallium/winsys/drm/intel/gem/intel_be_device.h new file mode 100644 index 00000000000..96e94c47e71 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_be_device.h @@ -0,0 +1,74 @@ + +#ifndef INTEL_DRM_DEVICE_H +#define INTEL_DRM_DEVICE_H + +#include "pipe/p_winsys.h" +#include "pipe/p_context.h" + +#include "drm.h" +#include "intel_bufmgr.h" + +/* + * Device + */ + +struct intel_be_device +{ + struct pipe_winsys base; + + int fd; /**< Drm file discriptor */ + + size_t max_batch_size; + size_t max_vertex_size; + + struct { + drm_intel_bufmgr *gem; + } pools; +}; + +boolean +intel_be_init_device(struct intel_be_device *device, int fd, unsigned id); + +void +intel_be_destroy_device(struct intel_be_device *dev); + +/* + * Buffer + */ + +struct intel_be_buffer { + struct pipe_buffer base; + drm_intel_bo *bo; +}; + +/** + * Create a be buffer from a drm bo handle. + * + * Takes a reference. + */ +struct pipe_buffer * +intel_be_buffer_from_handle(struct pipe_winsys *winsys, + const char* name, unsigned handle); + +/** + * Gets a handle from a buffer. + * + * If buffer is destroyed handle may become invalid. + */ +unsigned +intel_be_handle_from_buffer(struct pipe_winsys *winsys, + struct pipe_buffer *buffer); + +static INLINE struct intel_be_buffer * +intel_be_buffer(struct pipe_buffer *buf) +{ + return (struct intel_be_buffer *)buf; +} + +static INLINE drm_intel_bo * +intel_bo(struct pipe_buffer *buf) +{ + return intel_be_buffer(buf)->bo; +} + +#endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_fence.h b/src/gallium/winsys/drm/intel/gem/intel_be_fence.h new file mode 100644 index 00000000000..0fe18f66f83 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_be_fence.h @@ -0,0 +1,38 @@ + +#ifndef INTEL_BE_FENCE_H +#define INTEL_BE_FENCE_H + +#include "pipe/p_defines.h" + +#include "drm.h" +#include "intel_bufmgr.h" + +/** + * Because gem does not have fence's we have to create our own fences. + * + * They work by keeping the batchbuffer around and checking if that has + * been idled. If bo is NULL fence has expired. + */ +struct intel_be_fence +{ + uint32_t refcount; + drm_intel_bo *bo; +}; + +static INLINE void +intel_be_fence_reference(struct intel_be_fence *f) +{ + f->refcount++; +} + +static INLINE void +intel_be_fence_unreference(struct intel_be_fence *f) +{ + if (!--f->refcount) { + if (f->bo) + drm_intel_bo_unreference(f->bo); + free(f); + } +} + +#endif diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c index 68951375066..5b3101fbba9 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c +++ b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c @@ -69,7 +69,7 @@ nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, nvbuf->base.usage = usage; nvbuf->base.size = size; - flags = nouveau_flags_from_usage(nv, flags); + flags = nouveau_flags_from_usage(nv, usage); if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) { FREE(nvbuf); @@ -121,14 +121,9 @@ nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf, if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) map_flags |= NOUVEAU_BO_WR; - /* XXX: Technically incorrect. If the client maps a buffer for write-only - * and leaves part of the buffer untouched it probably expects those parts - * to remain intact. This is violated because we allocate a whole new buffer - * and don't copy the previous buffer's contents, so this optimization is - * only valid if the client intends to overwrite the whole buffer. - */ - if ((map_flags & NOUVEAU_BO_RDWR) == NOUVEAU_BO_WR && - !nouveau_bo_busy(nvbuf->bo, map_flags)) { + if (flags & PIPE_BUFFER_USAGE_DISCARD && + !(flags & PIPE_BUFFER_USAGE_CPU_READ) && + nouveau_bo_busy(nvbuf->bo, map_flags)) { struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; struct nouveau_context *nv = nvpws->nv; struct nouveau_device *dev = nv->nv_screen->device; diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c index 006978b1821..aacfe984d18 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c @@ -42,7 +42,7 @@ nouveau_context_create(const __GLcontextModes *glVis, if (nouveau_context_init(&nv_screen->base, driContextPriv->hHWContext, (drmLock *)&driScrnPriv->pSAREA->lock, - nv_share, &nv->base)) { + &nv_share->base, &nv->base)) { return GL_FALSE; } |