mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-20 22:30:12 +01:00
Merge commit 'origin/master' into gallium-sampler-view
This branch already seems to have the nv50_tex.c fix. Conflicts: src/gallium/drivers/nv50/nv50_tex.c
This commit is contained in:
commit
8cdfd1219a
96 changed files with 3977 additions and 1079 deletions
|
|
@ -88,9 +88,9 @@ LoadSkyBoxCubeTexture(const char *filePosX,
|
||||||
return 0;
|
return 0;
|
||||||
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE))
|
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE))
|
||||||
return 0;
|
return 0;
|
||||||
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, 1+GL_FALSE, GL_TRUE))
|
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, GL_TRUE, GL_TRUE))
|
||||||
return 0;
|
return 0;
|
||||||
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, 1+GL_FALSE, GL_TRUE))
|
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, GL_TRUE, GL_TRUE))
|
||||||
return 0;
|
return 0;
|
||||||
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE))
|
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef OS_LLVM_H
|
#ifndef LP_BLD_H
|
||||||
#define OS_LLVM_H
|
#define LP_BLD_H
|
||||||
|
|
||||||
|
|
||||||
#include <llvm-c/Core.h>
|
#include <llvm-c/Core.h>
|
||||||
|
|
@ -40,8 +40,8 @@
|
||||||
|
|
||||||
/** Set version to 0 if missing to avoid #ifdef HAVE_LLVM everywhere */
|
/** Set version to 0 if missing to avoid #ifdef HAVE_LLVM everywhere */
|
||||||
#ifndef HAVE_LLVM
|
#ifndef HAVE_LLVM
|
||||||
#define HAVE_LLVM 0x0
|
#define HAVE_LLVM 0x0207
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* OS_LLVM_H */
|
#endif /* LP_BLD_H */
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
#define LP_BLD_ALPHA_H
|
#define LP_BLD_ALPHA_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
struct pipe_alpha_state;
|
struct pipe_alpha_state;
|
||||||
struct lp_type;
|
struct lp_type;
|
||||||
|
|
|
||||||
|
|
@ -361,12 +361,12 @@ lp_build_mul_u8n(LLVMBuilderRef builder,
|
||||||
LLVMValueRef c8;
|
LLVMValueRef c8;
|
||||||
LLVMValueRef ab;
|
LLVMValueRef ab;
|
||||||
|
|
||||||
c8 = lp_build_int_const_scalar(i16_type, 8);
|
c8 = lp_build_const_int_vec(i16_type, 8);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
/* a*b/255 ~= (a*(b + 1)) >> 256 */
|
/* a*b/255 ~= (a*(b + 1)) >> 256 */
|
||||||
b = LLVMBuildAdd(builder, b, lp_build_int_const_scalar(i16_type, 1), "");
|
b = LLVMBuildAdd(builder, b, lp_build_const_int_vec(i16_type, 1), "");
|
||||||
ab = LLVMBuildMul(builder, a, b, "");
|
ab = LLVMBuildMul(builder, a, b, "");
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
@ -374,7 +374,7 @@ lp_build_mul_u8n(LLVMBuilderRef builder,
|
||||||
/* ab/255 ~= (ab + (ab >> 8) + 0x80) >> 8 */
|
/* ab/255 ~= (ab + (ab >> 8) + 0x80) >> 8 */
|
||||||
ab = LLVMBuildMul(builder, a, b, "");
|
ab = LLVMBuildMul(builder, a, b, "");
|
||||||
ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c8, ""), "");
|
ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c8, ""), "");
|
||||||
ab = LLVMBuildAdd(builder, ab, lp_build_int_const_scalar(i16_type, 0x80), "");
|
ab = LLVMBuildAdd(builder, ab, lp_build_const_int_vec(i16_type, 0x80), "");
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -429,7 +429,7 @@ lp_build_mul(struct lp_build_context *bld,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type.fixed)
|
if(type.fixed)
|
||||||
shift = lp_build_int_const_scalar(type, type.width/2);
|
shift = lp_build_const_int_vec(type, type.width/2);
|
||||||
else
|
else
|
||||||
shift = NULL;
|
shift = NULL;
|
||||||
|
|
||||||
|
|
@ -491,7 +491,7 @@ lp_build_mul_imm(struct lp_build_context *bld,
|
||||||
* for Inf and NaN.
|
* for Inf and NaN.
|
||||||
*/
|
*/
|
||||||
unsigned mantissa = lp_mantissa(bld->type);
|
unsigned mantissa = lp_mantissa(bld->type);
|
||||||
factor = lp_build_int_const_scalar(bld->type, (unsigned long long)shift << mantissa);
|
factor = lp_build_const_int_vec(bld->type, (unsigned long long)shift << mantissa);
|
||||||
a = LLVMBuildBitCast(bld->builder, a, lp_build_int_vec_type(bld->type), "");
|
a = LLVMBuildBitCast(bld->builder, a, lp_build_int_vec_type(bld->type), "");
|
||||||
a = LLVMBuildAdd(bld->builder, a, factor, "");
|
a = LLVMBuildAdd(bld->builder, a, factor, "");
|
||||||
a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(bld->type), "");
|
a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(bld->type), "");
|
||||||
|
|
@ -499,12 +499,12 @@ lp_build_mul_imm(struct lp_build_context *bld,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
factor = lp_build_const_scalar(bld->type, shift);
|
factor = lp_build_const_vec(bld->type, shift);
|
||||||
return LLVMBuildShl(bld->builder, a, factor, "");
|
return LLVMBuildShl(bld->builder, a, factor, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
factor = lp_build_const_scalar(bld->type, (double)b);
|
factor = lp_build_const_vec(bld->type, (double)b);
|
||||||
return lp_build_mul(bld, a, factor);
|
return lp_build_mul(bld, a, factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -567,7 +567,7 @@ lp_build_lerp(struct lp_build_context *bld,
|
||||||
* but it will be wrong for other uses. Basically we need a more
|
* but it will be wrong for other uses. Basically we need a more
|
||||||
* powerful lp_type, capable of further distinguishing the values
|
* powerful lp_type, capable of further distinguishing the values
|
||||||
* interpretation from the value storage. */
|
* interpretation from the value storage. */
|
||||||
res = LLVMBuildAnd(bld->builder, res, lp_build_int_const_scalar(bld->type, (1 << bld->type.width/2) - 1), "");
|
res = LLVMBuildAnd(bld->builder, res, lp_build_const_int_vec(bld->type, (1 << bld->type.width/2) - 1), "");
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -689,7 +689,7 @@ lp_build_abs(struct lp_build_context *bld,
|
||||||
/* vector of floats */
|
/* vector of floats */
|
||||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||||
unsigned long long absMask = ~(1ULL << (type.width - 1));
|
unsigned long long absMask = ~(1ULL << (type.width - 1));
|
||||||
LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask));
|
LLVMValueRef mask = lp_build_const_int_vec(type, ((unsigned long long) absMask));
|
||||||
a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
||||||
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
||||||
a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
|
a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
|
||||||
|
|
@ -751,7 +751,7 @@ lp_build_sgn(struct lp_build_context *bld,
|
||||||
/* vector */
|
/* vector */
|
||||||
int_type = lp_build_int_vec_type(type);
|
int_type = lp_build_int_vec_type(type);
|
||||||
vec_type = lp_build_vec_type(type);
|
vec_type = lp_build_vec_type(type);
|
||||||
mask = lp_build_int_const_scalar(type, maskBit);
|
mask = lp_build_const_int_vec(type, maskBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Take the sign bit and add it to 1 constant */
|
/* Take the sign bit and add it to 1 constant */
|
||||||
|
|
@ -763,14 +763,14 @@ lp_build_sgn(struct lp_build_context *bld,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LLVMValueRef minus_one = lp_build_const_scalar(type, -1.0);
|
LLVMValueRef minus_one = lp_build_const_vec(type, -1.0);
|
||||||
cond = lp_build_cmp(bld, PIPE_FUNC_GREATER, a, bld->zero);
|
cond = lp_build_cmp(bld, PIPE_FUNC_GREATER, a, bld->zero);
|
||||||
res = lp_build_select(bld, cond, bld->one, minus_one);
|
res = lp_build_select(bld, cond, bld->one, minus_one);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle zero */
|
/* Handle zero */
|
||||||
cond = lp_build_cmp(bld, PIPE_FUNC_EQUAL, a, bld->zero);
|
cond = lp_build_cmp(bld, PIPE_FUNC_EQUAL, a, bld->zero);
|
||||||
res = lp_build_select(bld, cond, bld->zero, bld->one);
|
res = lp_build_select(bld, cond, bld->zero, res);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -789,8 +789,8 @@ lp_build_set_sign(struct lp_build_context *bld,
|
||||||
const struct lp_type type = bld->type;
|
const struct lp_type type = bld->type;
|
||||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||||
LLVMValueRef shift = lp_build_int_const_scalar(type, type.width - 1);
|
LLVMValueRef shift = lp_build_const_int_vec(type, type.width - 1);
|
||||||
LLVMValueRef mask = lp_build_int_const_scalar(type,
|
LLVMValueRef mask = lp_build_const_int_vec(type,
|
||||||
~((unsigned long long) 1 << (type.width - 1)));
|
~((unsigned long long) 1 << (type.width - 1)));
|
||||||
LLVMValueRef val, res;
|
LLVMValueRef val, res;
|
||||||
|
|
||||||
|
|
@ -930,7 +930,10 @@ lp_build_floor(struct lp_build_context *bld,
|
||||||
assert(type.floating);
|
assert(type.floating);
|
||||||
|
|
||||||
if (type.length == 1) {
|
if (type.length == 1) {
|
||||||
return LLVMBuildFPTrunc(bld->builder, a, LLVMFloatType(), "");
|
LLVMValueRef res;
|
||||||
|
res = lp_build_ifloor(bld, a);
|
||||||
|
res = LLVMBuildSIToFP(bld->builder, res, LLVMFloatType(), "");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(util_cpu_caps.has_sse4_1)
|
if(util_cpu_caps.has_sse4_1)
|
||||||
|
|
@ -993,7 +996,7 @@ lp_build_itrunc(struct lp_build_context *bld,
|
||||||
|
|
||||||
if (type.length == 1) {
|
if (type.length == 1) {
|
||||||
LLVMTypeRef int_type = LLVMIntType(type.width);
|
LLVMTypeRef int_type = LLVMIntType(type.width);
|
||||||
return LLVMBuildFPTrunc(bld->builder, a, int_type, "");
|
return LLVMBuildFPToSI(bld->builder, a, int_type, "");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||||
|
|
@ -1031,7 +1034,7 @@ lp_build_iround(struct lp_build_context *bld,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||||
LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1));
|
LLVMValueRef mask = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1));
|
||||||
LLVMValueRef sign;
|
LLVMValueRef sign;
|
||||||
LLVMValueRef half;
|
LLVMValueRef half;
|
||||||
|
|
||||||
|
|
@ -1040,7 +1043,7 @@ lp_build_iround(struct lp_build_context *bld,
|
||||||
sign = LLVMBuildAnd(bld->builder, sign, mask, "");
|
sign = LLVMBuildAnd(bld->builder, sign, mask, "");
|
||||||
|
|
||||||
/* sign * 0.5 */
|
/* sign * 0.5 */
|
||||||
half = lp_build_const_scalar(type, 0.5);
|
half = lp_build_const_vec(type, 0.5);
|
||||||
half = LLVMBuildBitCast(bld->builder, half, int_vec_type, "");
|
half = LLVMBuildBitCast(bld->builder, half, int_vec_type, "");
|
||||||
half = LLVMBuildOr(bld->builder, sign, half, "");
|
half = LLVMBuildOr(bld->builder, sign, half, "");
|
||||||
half = LLVMBuildBitCast(bld->builder, half, vec_type, "");
|
half = LLVMBuildBitCast(bld->builder, half, vec_type, "");
|
||||||
|
|
@ -1083,18 +1086,18 @@ lp_build_ifloor(struct lp_build_context *bld,
|
||||||
/* Take the sign bit and add it to 1 constant */
|
/* Take the sign bit and add it to 1 constant */
|
||||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||||
unsigned mantissa = lp_mantissa(type);
|
unsigned mantissa = lp_mantissa(type);
|
||||||
LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1));
|
LLVMValueRef mask = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1));
|
||||||
LLVMValueRef sign;
|
LLVMValueRef sign;
|
||||||
LLVMValueRef offset;
|
LLVMValueRef offset;
|
||||||
|
|
||||||
/* sign = a < 0 ? ~0 : 0 */
|
/* sign = a < 0 ? ~0 : 0 */
|
||||||
sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
||||||
sign = LLVMBuildAnd(bld->builder, sign, mask, "");
|
sign = LLVMBuildAnd(bld->builder, sign, mask, "");
|
||||||
sign = LLVMBuildAShr(bld->builder, sign, lp_build_int_const_scalar(type, type.width - 1), "");
|
sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), "");
|
||||||
lp_build_name(sign, "floor.sign");
|
lp_build_name(sign, "floor.sign");
|
||||||
|
|
||||||
/* offset = -0.99999(9)f */
|
/* offset = -0.99999(9)f */
|
||||||
offset = lp_build_const_scalar(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa));
|
offset = lp_build_const_vec(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa));
|
||||||
offset = LLVMConstBitCast(offset, int_vec_type);
|
offset = LLVMConstBitCast(offset, int_vec_type);
|
||||||
|
|
||||||
/* offset = a < 0 ? -0.99999(9)f : 0.0f */
|
/* offset = a < 0 ? -0.99999(9)f : 0.0f */
|
||||||
|
|
@ -1265,7 +1268,7 @@ lp_build_exp(struct lp_build_context *bld,
|
||||||
LLVMValueRef x)
|
LLVMValueRef x)
|
||||||
{
|
{
|
||||||
/* log2(e) = 1/log(2) */
|
/* log2(e) = 1/log(2) */
|
||||||
LLVMValueRef log2e = lp_build_const_scalar(bld->type, 1.4426950408889634);
|
LLVMValueRef log2e = lp_build_const_vec(bld->type, 1.4426950408889634);
|
||||||
|
|
||||||
return lp_build_mul(bld, log2e, lp_build_exp2(bld, x));
|
return lp_build_mul(bld, log2e, lp_build_exp2(bld, x));
|
||||||
}
|
}
|
||||||
|
|
@ -1279,7 +1282,7 @@ lp_build_log(struct lp_build_context *bld,
|
||||||
LLVMValueRef x)
|
LLVMValueRef x)
|
||||||
{
|
{
|
||||||
/* log(2) */
|
/* log(2) */
|
||||||
LLVMValueRef log2 = lp_build_const_scalar(bld->type, 0.69314718055994529);
|
LLVMValueRef log2 = lp_build_const_vec(bld->type, 0.69314718055994529);
|
||||||
|
|
||||||
return lp_build_mul(bld, log2, lp_build_exp2(bld, x));
|
return lp_build_mul(bld, log2, lp_build_exp2(bld, x));
|
||||||
}
|
}
|
||||||
|
|
@ -1315,7 +1318,7 @@ lp_build_polynomial(struct lp_build_context *bld,
|
||||||
if (type.length == 1)
|
if (type.length == 1)
|
||||||
coeff = LLVMConstReal(float_type, coeffs[i]);
|
coeff = LLVMConstReal(float_type, coeffs[i]);
|
||||||
else
|
else
|
||||||
coeff = lp_build_const_scalar(type, coeffs[i]);
|
coeff = lp_build_const_vec(type, coeffs[i]);
|
||||||
|
|
||||||
if(res)
|
if(res)
|
||||||
res = lp_build_add(bld, coeff, lp_build_mul(bld, x, res));
|
res = lp_build_add(bld, coeff, lp_build_mul(bld, x, res));
|
||||||
|
|
@ -1372,11 +1375,11 @@ lp_build_exp2_approx(struct lp_build_context *bld,
|
||||||
|
|
||||||
assert(type.floating && type.width == 32);
|
assert(type.floating && type.width == 32);
|
||||||
|
|
||||||
x = lp_build_min(bld, x, lp_build_const_scalar(type, 129.0));
|
x = lp_build_min(bld, x, lp_build_const_vec(type, 129.0));
|
||||||
x = lp_build_max(bld, x, lp_build_const_scalar(type, -126.99999));
|
x = lp_build_max(bld, x, lp_build_const_vec(type, -126.99999));
|
||||||
|
|
||||||
/* ipart = int(x - 0.5) */
|
/* ipart = int(x - 0.5) */
|
||||||
ipart = LLVMBuildSub(bld->builder, x, lp_build_const_scalar(type, 0.5f), "");
|
ipart = LLVMBuildSub(bld->builder, x, lp_build_const_vec(type, 0.5f), "");
|
||||||
ipart = LLVMBuildFPToSI(bld->builder, ipart, int_vec_type, "");
|
ipart = LLVMBuildFPToSI(bld->builder, ipart, int_vec_type, "");
|
||||||
|
|
||||||
/* fpart = x - ipart */
|
/* fpart = x - ipart */
|
||||||
|
|
@ -1386,8 +1389,8 @@ lp_build_exp2_approx(struct lp_build_context *bld,
|
||||||
|
|
||||||
if(p_exp2_int_part || p_exp2) {
|
if(p_exp2_int_part || p_exp2) {
|
||||||
/* expipart = (float) (1 << ipart) */
|
/* expipart = (float) (1 << ipart) */
|
||||||
expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_int_const_scalar(type, 127), "");
|
expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_const_int_vec(type, 127), "");
|
||||||
expipart = LLVMBuildShl(bld->builder, expipart, lp_build_int_const_scalar(type, 23), "");
|
expipart = LLVMBuildShl(bld->builder, expipart, lp_build_const_int_vec(type, 23), "");
|
||||||
expipart = LLVMBuildBitCast(bld->builder, expipart, vec_type, "");
|
expipart = LLVMBuildBitCast(bld->builder, expipart, vec_type, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1453,8 +1456,8 @@ lp_build_log2_approx(struct lp_build_context *bld,
|
||||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||||
|
|
||||||
LLVMValueRef expmask = lp_build_int_const_scalar(type, 0x7f800000);
|
LLVMValueRef expmask = lp_build_const_int_vec(type, 0x7f800000);
|
||||||
LLVMValueRef mantmask = lp_build_int_const_scalar(type, 0x007fffff);
|
LLVMValueRef mantmask = lp_build_const_int_vec(type, 0x007fffff);
|
||||||
LLVMValueRef one = LLVMConstBitCast(bld->one, int_vec_type);
|
LLVMValueRef one = LLVMConstBitCast(bld->one, int_vec_type);
|
||||||
|
|
||||||
LLVMValueRef i = NULL;
|
LLVMValueRef i = NULL;
|
||||||
|
|
@ -1479,8 +1482,8 @@ lp_build_log2_approx(struct lp_build_context *bld,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p_floor_log2 || p_log2) {
|
if(p_floor_log2 || p_log2) {
|
||||||
logexp = LLVMBuildLShr(bld->builder, exp, lp_build_int_const_scalar(type, 23), "");
|
logexp = LLVMBuildLShr(bld->builder, exp, lp_build_const_int_vec(type, 23), "");
|
||||||
logexp = LLVMBuildSub(bld->builder, logexp, lp_build_int_const_scalar(type, 127), "");
|
logexp = LLVMBuildSub(bld->builder, logexp, lp_build_const_int_vec(type, 127), "");
|
||||||
logexp = LLVMBuildSIToFP(bld->builder, logexp, vec_type, "");
|
logexp = LLVMBuildSIToFP(bld->builder, logexp, vec_type, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#define LP_BLD_ARIT_H
|
#define LP_BLD_ARIT_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
struct lp_type;
|
struct lp_type;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
* for a standalone example.
|
* for a standalone example.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
#include "pipe/p_format.h"
|
#include "pipe/p_format.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ lp_build_one(struct lp_type type)
|
||||||
if(type.sign)
|
if(type.sign)
|
||||||
/* TODO: Unfortunately this caused "Tried to create a shift operation
|
/* TODO: Unfortunately this caused "Tried to create a shift operation
|
||||||
* on a non-integer type!" */
|
* on a non-integer type!" */
|
||||||
vec = LLVMConstLShr(vec, lp_build_int_const_scalar(type, 1));
|
vec = LLVMConstLShr(vec, lp_build_const_int_vec(type, 1));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return vec;
|
return vec;
|
||||||
|
|
@ -283,8 +283,8 @@ lp_build_one(struct lp_type type)
|
||||||
* Build constant-valued vector from a scalar value.
|
* Build constant-valued vector from a scalar value.
|
||||||
*/
|
*/
|
||||||
LLVMValueRef
|
LLVMValueRef
|
||||||
lp_build_const_scalar(struct lp_type type,
|
lp_build_const_vec(struct lp_type type,
|
||||||
double val)
|
double val)
|
||||||
{
|
{
|
||||||
LLVMTypeRef elem_type = lp_build_elem_type(type);
|
LLVMTypeRef elem_type = lp_build_elem_type(type);
|
||||||
LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
|
LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
|
||||||
|
|
@ -309,7 +309,7 @@ lp_build_const_scalar(struct lp_type type,
|
||||||
|
|
||||||
|
|
||||||
LLVMValueRef
|
LLVMValueRef
|
||||||
lp_build_int_const_scalar(struct lp_type type,
|
lp_build_const_int_vec(struct lp_type type,
|
||||||
long long val)
|
long long val)
|
||||||
{
|
{
|
||||||
LLVMTypeRef elem_type = lp_build_int_elem_type(type);
|
LLVMTypeRef elem_type = lp_build_int_elem_type(type);
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@
|
||||||
#define LP_BLD_CONST_H
|
#define LP_BLD_CONST_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "pipe/p_compiler.h"
|
||||||
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
#include <pipe/p_compiler.h>
|
|
||||||
|
|
||||||
|
|
||||||
struct lp_type;
|
struct lp_type;
|
||||||
|
|
@ -85,13 +85,11 @@ lp_build_one(struct lp_type type);
|
||||||
|
|
||||||
|
|
||||||
LLVMValueRef
|
LLVMValueRef
|
||||||
lp_build_const_scalar(struct lp_type type,
|
lp_build_const_vec(struct lp_type type, double val);
|
||||||
double val);
|
|
||||||
|
|
||||||
|
|
||||||
LLVMValueRef
|
LLVMValueRef
|
||||||
lp_build_int_const_scalar(struct lp_type type,
|
lp_build_const_int_vec(struct lp_type type, long long val);
|
||||||
long long val);
|
|
||||||
|
|
||||||
|
|
||||||
LLVMValueRef
|
LLVMValueRef
|
||||||
|
|
|
||||||
|
|
@ -114,13 +114,13 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
|
||||||
scale = (double)mask/ubound;
|
scale = (double)mask/ubound;
|
||||||
bias = (double)((unsigned long long)1 << (mantissa - n));
|
bias = (double)((unsigned long long)1 << (mantissa - n));
|
||||||
|
|
||||||
res = LLVMBuildMul(builder, src, lp_build_const_scalar(src_type, scale), "");
|
res = LLVMBuildMul(builder, src, lp_build_const_vec(src_type, scale), "");
|
||||||
res = LLVMBuildAdd(builder, res, lp_build_const_scalar(src_type, bias), "");
|
res = LLVMBuildAdd(builder, res, lp_build_const_vec(src_type, bias), "");
|
||||||
res = LLVMBuildBitCast(builder, res, int_vec_type, "");
|
res = LLVMBuildBitCast(builder, res, int_vec_type, "");
|
||||||
|
|
||||||
if(dst_width > n) {
|
if(dst_width > n) {
|
||||||
int shift = dst_width - n;
|
int shift = dst_width - n;
|
||||||
res = LLVMBuildShl(builder, res, lp_build_int_const_scalar(src_type, shift), "");
|
res = LLVMBuildShl(builder, res, lp_build_const_int_vec(src_type, shift), "");
|
||||||
|
|
||||||
/* TODO: Fill in the empty lower bits for additional precision? */
|
/* TODO: Fill in the empty lower bits for additional precision? */
|
||||||
/* YES: this fixes progs/trivial/tri-z-eq.c.
|
/* YES: this fixes progs/trivial/tri-z-eq.c.
|
||||||
|
|
@ -130,21 +130,21 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
LLVMValueRef msb;
|
LLVMValueRef msb;
|
||||||
msb = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, dst_width - 1), "");
|
msb = LLVMBuildLShr(builder, res, lp_build_const_int_vec(src_type, dst_width - 1), "");
|
||||||
msb = LLVMBuildShl(builder, msb, lp_build_int_const_scalar(src_type, shift), "");
|
msb = LLVMBuildShl(builder, msb, lp_build_const_int_vec(src_type, shift), "");
|
||||||
msb = LLVMBuildSub(builder, msb, lp_build_int_const_scalar(src_type, 1), "");
|
msb = LLVMBuildSub(builder, msb, lp_build_const_int_vec(src_type, 1), "");
|
||||||
res = LLVMBuildOr(builder, res, msb, "");
|
res = LLVMBuildOr(builder, res, msb, "");
|
||||||
}
|
}
|
||||||
#elif 0
|
#elif 0
|
||||||
while(shift > 0) {
|
while(shift > 0) {
|
||||||
res = LLVMBuildOr(builder, res, LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, n), ""), "");
|
res = LLVMBuildOr(builder, res, LLVMBuildLShr(builder, res, lp_build_const_int_vec(src_type, n), ""), "");
|
||||||
shift -= n;
|
shift -= n;
|
||||||
n *= 2;
|
n *= 2;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res = LLVMBuildAnd(builder, res, lp_build_int_const_scalar(src_type, mask), "");
|
res = LLVMBuildAnd(builder, res, lp_build_const_int_vec(src_type, mask), "");
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -183,10 +183,10 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
|
||||||
|
|
||||||
if(src_width > mantissa) {
|
if(src_width > mantissa) {
|
||||||
int shift = src_width - mantissa;
|
int shift = src_width - mantissa;
|
||||||
res = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(dst_type, shift), "");
|
res = LLVMBuildLShr(builder, res, lp_build_const_int_vec(dst_type, shift), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
bias_ = lp_build_const_scalar(dst_type, bias);
|
bias_ = lp_build_const_vec(dst_type, bias);
|
||||||
|
|
||||||
res = LLVMBuildOr(builder,
|
res = LLVMBuildOr(builder,
|
||||||
res,
|
res,
|
||||||
|
|
@ -195,7 +195,7 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
|
||||||
res = LLVMBuildBitCast(builder, res, vec_type, "");
|
res = LLVMBuildBitCast(builder, res, vec_type, "");
|
||||||
|
|
||||||
res = LLVMBuildSub(builder, res, bias_, "");
|
res = LLVMBuildSub(builder, res, bias_, "");
|
||||||
res = LLVMBuildMul(builder, res, lp_build_const_scalar(dst_type, scale), "");
|
res = LLVMBuildMul(builder, res, lp_build_const_vec(dst_type, scale), "");
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -251,7 +251,7 @@ lp_build_conv(LLVMBuilderRef builder,
|
||||||
if(dst_min == 0.0)
|
if(dst_min == 0.0)
|
||||||
thres = bld.zero;
|
thres = bld.zero;
|
||||||
else
|
else
|
||||||
thres = lp_build_const_scalar(src_type, dst_min);
|
thres = lp_build_const_vec(src_type, dst_min);
|
||||||
for(i = 0; i < num_tmps; ++i)
|
for(i = 0; i < num_tmps; ++i)
|
||||||
tmp[i] = lp_build_max(&bld, tmp[i], thres);
|
tmp[i] = lp_build_max(&bld, tmp[i], thres);
|
||||||
}
|
}
|
||||||
|
|
@ -260,7 +260,7 @@ lp_build_conv(LLVMBuilderRef builder,
|
||||||
if(dst_max == 1.0)
|
if(dst_max == 1.0)
|
||||||
thres = bld.one;
|
thres = bld.one;
|
||||||
else
|
else
|
||||||
thres = lp_build_const_scalar(src_type, dst_max);
|
thres = lp_build_const_vec(src_type, dst_max);
|
||||||
for(i = 0; i < num_tmps; ++i)
|
for(i = 0; i < num_tmps; ++i)
|
||||||
tmp[i] = lp_build_min(&bld, tmp[i], thres);
|
tmp[i] = lp_build_min(&bld, tmp[i], thres);
|
||||||
}
|
}
|
||||||
|
|
@ -288,7 +288,7 @@ lp_build_conv(LLVMBuilderRef builder,
|
||||||
LLVMTypeRef tmp_vec_type;
|
LLVMTypeRef tmp_vec_type;
|
||||||
|
|
||||||
if (dst_scale != 1.0) {
|
if (dst_scale != 1.0) {
|
||||||
LLVMValueRef scale = lp_build_const_scalar(tmp_type, dst_scale);
|
LLVMValueRef scale = lp_build_const_vec(tmp_type, dst_scale);
|
||||||
for(i = 0; i < num_tmps; ++i)
|
for(i = 0; i < num_tmps; ++i)
|
||||||
tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
|
tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +315,7 @@ lp_build_conv(LLVMBuilderRef builder,
|
||||||
|
|
||||||
/* FIXME: compensate different offsets too */
|
/* FIXME: compensate different offsets too */
|
||||||
if(src_shift > dst_shift) {
|
if(src_shift > dst_shift) {
|
||||||
LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, src_shift - dst_shift);
|
LLVMValueRef shift = lp_build_const_int_vec(tmp_type, src_shift - dst_shift);
|
||||||
for(i = 0; i < num_tmps; ++i)
|
for(i = 0; i < num_tmps; ++i)
|
||||||
if(src_type.sign)
|
if(src_type.sign)
|
||||||
tmp[i] = LLVMBuildAShr(builder, tmp[i], shift, "");
|
tmp[i] = LLVMBuildAShr(builder, tmp[i], shift, "");
|
||||||
|
|
@ -388,7 +388,7 @@ lp_build_conv(LLVMBuilderRef builder,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_scale != 1.0) {
|
if (src_scale != 1.0) {
|
||||||
LLVMValueRef scale = lp_build_const_scalar(tmp_type, 1.0/src_scale);
|
LLVMValueRef scale = lp_build_const_vec(tmp_type, 1.0/src_scale);
|
||||||
for(i = 0; i < num_tmps; ++i)
|
for(i = 0; i < num_tmps; ++i)
|
||||||
tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
|
tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
|
||||||
}
|
}
|
||||||
|
|
@ -400,7 +400,7 @@ lp_build_conv(LLVMBuilderRef builder,
|
||||||
|
|
||||||
/* FIXME: compensate different offsets too */
|
/* FIXME: compensate different offsets too */
|
||||||
if(src_shift < dst_shift) {
|
if(src_shift < dst_shift) {
|
||||||
LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, dst_shift - src_shift);
|
LLVMValueRef shift = lp_build_const_int_vec(tmp_type, dst_shift - src_shift);
|
||||||
for(i = 0; i < num_tmps; ++i)
|
for(i = 0; i < num_tmps; ++i)
|
||||||
tmp[i] = LLVMBuildShl(builder, tmp[i], shift, "");
|
tmp[i] = LLVMBuildShl(builder, tmp[i], shift, "");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#define LP_BLD_CONV_H
|
#define LP_BLD_CONV_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
struct lp_type;
|
struct lp_type;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
#define LP_BLD_DEBUG_H
|
#define LP_BLD_DEBUG_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
#include "pipe/p_compiler.h"
|
#include "pipe/p_compiler.h"
|
||||||
#include "util/u_string.h"
|
#include "util/u_string.h"
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,104 @@
|
||||||
#include "util/u_format.h"
|
#include "util/u_format.h"
|
||||||
|
|
||||||
#include "lp_bld_type.h"
|
#include "lp_bld_type.h"
|
||||||
|
#include "lp_bld_arit.h"
|
||||||
#include "lp_bld_const.h"
|
#include "lp_bld_const.h"
|
||||||
#include "lp_bld_logic.h"
|
#include "lp_bld_logic.h"
|
||||||
#include "lp_bld_flow.h"
|
#include "lp_bld_flow.h"
|
||||||
#include "lp_bld_debug.h"
|
#include "lp_bld_debug.h"
|
||||||
#include "lp_bld_depth.h"
|
#include "lp_bld_depth.h"
|
||||||
|
#include "lp_bld_swizzle.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the stencil test comparison (compare fb Z values against ref value.
|
||||||
|
* \param stencilVals vector of stencil values from framebuffer
|
||||||
|
* \param stencilRef the stencil reference value, replicated as a vector
|
||||||
|
* \return mask of pass/fail values
|
||||||
|
*/
|
||||||
|
static LLVMValueRef
|
||||||
|
lp_build_stencil_test(struct lp_build_context *bld,
|
||||||
|
const struct pipe_stencil_state *stencil,
|
||||||
|
LLVMValueRef stencilVals,
|
||||||
|
LLVMValueRef stencilRef)
|
||||||
|
{
|
||||||
|
const unsigned stencilMax = 255; /* XXX fix */
|
||||||
|
struct lp_type type = bld->type;
|
||||||
|
LLVMValueRef res;
|
||||||
|
|
||||||
|
assert(stencil->enabled);
|
||||||
|
|
||||||
|
if (stencil->valuemask != stencilMax) {
|
||||||
|
/* compute stencilRef = stencilRef & valuemask */
|
||||||
|
LLVMValueRef valuemask = lp_build_const_int_vec(type, stencil->valuemask);
|
||||||
|
stencilRef = LLVMBuildAnd(bld->builder, stencilRef, valuemask, "");
|
||||||
|
/* compute stencilVals = stencilVals & valuemask */
|
||||||
|
stencilVals = LLVMBuildAnd(bld->builder, stencilVals, valuemask, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
res = lp_build_compare(bld->builder, bld->type, stencil->func,
|
||||||
|
stencilVals, stencilRef);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the stencil operator (add/sub/keep/etc) to the given vector
|
||||||
|
* of stencil values.
|
||||||
|
* \return new stencil values vector
|
||||||
|
*/
|
||||||
|
static LLVMValueRef
|
||||||
|
lp_build_stencil_op(struct lp_build_context *bld,
|
||||||
|
unsigned stencil_op,
|
||||||
|
LLVMValueRef stencilRef,
|
||||||
|
const struct pipe_stencil_state *stencil,
|
||||||
|
LLVMValueRef stencilVals)
|
||||||
|
|
||||||
|
{
|
||||||
|
const unsigned stencilMax = 255; /* XXX fix */
|
||||||
|
struct lp_type type = bld->type;
|
||||||
|
LLVMValueRef res;
|
||||||
|
LLVMValueRef max = lp_build_const_int_vec(type, stencilMax);
|
||||||
|
|
||||||
|
switch (stencil_op) {
|
||||||
|
case PIPE_STENCIL_OP_KEEP:
|
||||||
|
res = stencilVals;
|
||||||
|
case PIPE_STENCIL_OP_ZERO:
|
||||||
|
res = bld->zero;
|
||||||
|
case PIPE_STENCIL_OP_REPLACE:
|
||||||
|
res = lp_build_broadcast_scalar(bld, stencilRef);
|
||||||
|
case PIPE_STENCIL_OP_INCR:
|
||||||
|
res = lp_build_add(bld, stencilVals, bld->one);
|
||||||
|
res = lp_build_min(bld, res, max);
|
||||||
|
case PIPE_STENCIL_OP_DECR:
|
||||||
|
res = lp_build_sub(bld, stencilVals, bld->one);
|
||||||
|
res = lp_build_max(bld, res, bld->zero);
|
||||||
|
case PIPE_STENCIL_OP_INCR_WRAP:
|
||||||
|
res = lp_build_add(bld, stencilVals, bld->one);
|
||||||
|
res = LLVMBuildAnd(bld->builder, res, max, "");
|
||||||
|
case PIPE_STENCIL_OP_DECR_WRAP:
|
||||||
|
res = lp_build_sub(bld, stencilVals, bld->one);
|
||||||
|
res = LLVMBuildAnd(bld->builder, res, max, "");
|
||||||
|
case PIPE_STENCIL_OP_INVERT:
|
||||||
|
res = LLVMBuildNot(bld->builder, stencilVals, "");
|
||||||
|
default:
|
||||||
|
assert(0 && "bad stencil op mode");
|
||||||
|
res = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stencil->writemask != stencilMax) {
|
||||||
|
/* compute res = (res & mask) | (stencilVals & ~mask) */
|
||||||
|
LLVMValueRef mask = lp_build_const_int_vec(type, stencil->writemask);
|
||||||
|
LLVMValueRef cmask = LLVMBuildNot(bld->builder, mask, "notWritemask");
|
||||||
|
LLVMValueRef t1 = LLVMBuildAnd(bld->builder, res, mask, "t1");
|
||||||
|
LLVMValueRef t2 = LLVMBuildAnd(bld->builder, stencilVals, cmask, "t2");
|
||||||
|
res = LLVMBuildOr(bld->builder, t1, t2, "t1_or_t2");
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -109,7 +202,14 @@ lp_depth_type(const struct util_format_description *format_desc,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Depth test.
|
* Generate code for performing depth and/or stencil tests.
|
||||||
|
* We operate on a vector of values (typically a 2x2 quad).
|
||||||
|
*
|
||||||
|
* \param type the data type of the fragment depth/stencil values
|
||||||
|
* \param format_desc description of the depth/stencil surface
|
||||||
|
* \param mask the alive/dead pixel mask for the quad
|
||||||
|
* \param src the incoming depth/stencil values (a 2x2 quad)
|
||||||
|
* \param dst_ptr the outgoing/updated depth/stencil values
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
lp_build_depth_test(LLVMBuilderRef builder,
|
lp_build_depth_test(LLVMBuilderRef builder,
|
||||||
|
|
@ -126,6 +226,9 @@ lp_build_depth_test(LLVMBuilderRef builder,
|
||||||
LLVMValueRef z_bitmask = NULL;
|
LLVMValueRef z_bitmask = NULL;
|
||||||
LLVMValueRef test;
|
LLVMValueRef test;
|
||||||
|
|
||||||
|
(void) lp_build_stencil_test;
|
||||||
|
(void) lp_build_stencil_op;
|
||||||
|
|
||||||
if(!state->enabled)
|
if(!state->enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -185,11 +288,11 @@ lp_build_depth_test(LLVMBuilderRef builder,
|
||||||
if(padding_left || padding_right) {
|
if(padding_left || padding_right) {
|
||||||
const unsigned long long mask_left = ((unsigned long long)1 << (format_desc->block.bits - padding_left)) - 1;
|
const unsigned long long mask_left = ((unsigned long long)1 << (format_desc->block.bits - padding_left)) - 1;
|
||||||
const unsigned long long mask_right = ((unsigned long long)1 << (padding_right)) - 1;
|
const unsigned long long mask_right = ((unsigned long long)1 << (padding_right)) - 1;
|
||||||
z_bitmask = lp_build_int_const_scalar(type, mask_left ^ mask_right);
|
z_bitmask = lp_build_const_int_vec(type, mask_left ^ mask_right);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(padding_left)
|
if(padding_left)
|
||||||
src = LLVMBuildLShr(builder, src, lp_build_int_const_scalar(type, padding_left), "");
|
src = LLVMBuildLShr(builder, src, lp_build_const_int_vec(type, padding_left), "");
|
||||||
if(padding_right)
|
if(padding_right)
|
||||||
src = LLVMBuildAnd(builder, src, z_bitmask, "");
|
src = LLVMBuildAnd(builder, src, z_bitmask, "");
|
||||||
if(padding_left || padding_right)
|
if(padding_left || padding_right)
|
||||||
|
|
@ -198,6 +301,7 @@ lp_build_depth_test(LLVMBuilderRef builder,
|
||||||
|
|
||||||
lp_build_name(dst, "zsbuf.z");
|
lp_build_name(dst, "zsbuf.z");
|
||||||
|
|
||||||
|
/* compare src Z to dst Z, returning 'pass' mask */
|
||||||
test = lp_build_cmp(&bld, state->func, src, dst);
|
test = lp_build_cmp(&bld, state->func, src, dst);
|
||||||
lp_build_mask_update(mask, test);
|
lp_build_mask_update(mask, test);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
#define LP_BLD_DEPTH_H
|
#define LP_BLD_DEPTH_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
struct pipe_depth_state;
|
struct pipe_depth_state;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
#define LP_BLD_FLOW_H
|
#define LP_BLD_FLOW_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
struct lp_type;
|
struct lp_type;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
* Pixel format helpers.
|
* Pixel format helpers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
#include "pipe/p_format.h"
|
#include "pipe/p_format.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,10 +114,10 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
|
||||||
case UTIL_FORMAT_TYPE_UNSIGNED:
|
case UTIL_FORMAT_TYPE_UNSIGNED:
|
||||||
if(type.floating) {
|
if(type.floating) {
|
||||||
if(start)
|
if(start)
|
||||||
input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(type, start), "");
|
input = LLVMBuildLShr(builder, input, lp_build_const_int_vec(type, start), "");
|
||||||
if(stop < format_desc->block.bits) {
|
if(stop < format_desc->block.bits) {
|
||||||
unsigned mask = ((unsigned long long)1 << width) - 1;
|
unsigned mask = ((unsigned long long)1 << width) - 1;
|
||||||
input = LLVMBuildAnd(builder, input, lp_build_int_const_scalar(type, mask), "");
|
input = LLVMBuildAnd(builder, input, lp_build_const_int_vec(type, mask), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(format_desc->channel[chan].normalized)
|
if(format_desc->channel[chan].normalized)
|
||||||
|
|
|
||||||
|
|
@ -289,17 +289,17 @@ pos_update(struct lp_build_interp_soa_context *bld, int quad_index)
|
||||||
/* top-right or bottom-right quad in block */
|
/* top-right or bottom-right quad in block */
|
||||||
/* build x += xstep */
|
/* build x += xstep */
|
||||||
x = lp_build_add(&bld->base, x,
|
x = lp_build_add(&bld->base, x,
|
||||||
lp_build_const_scalar(bld->base.type, xstep));
|
lp_build_const_vec(bld->base.type, xstep));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quad_index == 2) {
|
if (quad_index == 2) {
|
||||||
/* bottom-left quad in block */
|
/* bottom-left quad in block */
|
||||||
/* build y += ystep */
|
/* build y += ystep */
|
||||||
y = lp_build_add(&bld->base, y,
|
y = lp_build_add(&bld->base, y,
|
||||||
lp_build_const_scalar(bld->base.type, ystep));
|
lp_build_const_vec(bld->base.type, ystep));
|
||||||
/* build x -= xstep */
|
/* build x -= xstep */
|
||||||
x = lp_build_sub(&bld->base, x,
|
x = lp_build_sub(&bld->base, x,
|
||||||
lp_build_const_scalar(bld->base.type, xstep));
|
lp_build_const_vec(bld->base.type, xstep));
|
||||||
}
|
}
|
||||||
|
|
||||||
lp_build_name(x, "pos.x");
|
lp_build_name(x, "pos.x");
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
#define LP_BLD_INTERP_H
|
#define LP_BLD_INTERP_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
#include "tgsi/tgsi_exec.h"
|
#include "tgsi/tgsi_exec.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#define LP_BLD_INTR_H
|
#define LP_BLD_INTR_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ lp_build_compare(LLVMBuilderRef builder,
|
||||||
if(table[func].gt &&
|
if(table[func].gt &&
|
||||||
((type.width == 8 && type.sign) ||
|
((type.width == 8 && type.sign) ||
|
||||||
(type.width != 8 && !type.sign))) {
|
(type.width != 8 && !type.sign))) {
|
||||||
LLVMValueRef msb = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1));
|
LLVMValueRef msb = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1));
|
||||||
a = LLVMBuildXor(builder, a, msb, "");
|
a = LLVMBuildXor(builder, a, msb, "");
|
||||||
b = LLVMBuildXor(builder, b, msb, "");
|
b = LLVMBuildXor(builder, b, msb, "");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#define LP_BLD_LOGIC_H
|
#define LP_BLD_LOGIC_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
#include "pipe/p_defines.h" /* For PIPE_FUNC_xxx */
|
#include "pipe/p_defines.h" /* For PIPE_FUNC_xxx */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ lp_build_unpack2(LLVMBuilderRef builder,
|
||||||
|
|
||||||
if(dst_type.sign && src_type.sign) {
|
if(dst_type.sign && src_type.sign) {
|
||||||
/* Replicate the sign bit in the most significant bits */
|
/* Replicate the sign bit in the most significant bits */
|
||||||
msb = LLVMBuildAShr(builder, src, lp_build_int_const_scalar(src_type, src_type.width - 1), "");
|
msb = LLVMBuildAShr(builder, src, lp_build_const_int_vec(src_type, src_type.width - 1), "");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Most significant bits always zero */
|
/* Most significant bits always zero */
|
||||||
|
|
@ -361,7 +361,7 @@ lp_build_packs2(LLVMBuilderRef builder,
|
||||||
if(clamp) {
|
if(clamp) {
|
||||||
struct lp_build_context bld;
|
struct lp_build_context bld;
|
||||||
unsigned dst_bits = dst_type.sign ? dst_type.width - 1 : dst_type.width;
|
unsigned dst_bits = dst_type.sign ? dst_type.width - 1 : dst_type.width;
|
||||||
LLVMValueRef dst_max = lp_build_int_const_scalar(src_type, ((unsigned long long)1 << dst_bits) - 1);
|
LLVMValueRef dst_max = lp_build_const_int_vec(src_type, ((unsigned long long)1 << dst_bits) - 1);
|
||||||
lp_build_context_init(&bld, builder, src_type);
|
lp_build_context_init(&bld, builder, src_type);
|
||||||
lo = lp_build_min(&bld, lo, dst_max);
|
lo = lp_build_min(&bld, lo, dst_max);
|
||||||
hi = lp_build_min(&bld, hi, dst_max);
|
hi = lp_build_min(&bld, hi, dst_max);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#define LP_BLD_PACK_H
|
#define LP_BLD_PACK_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
struct lp_type;
|
struct lp_type;
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ lp_build_sample_offset(struct lp_build_context *bld,
|
||||||
LLVMValueRef x_stride;
|
LLVMValueRef x_stride;
|
||||||
LLVMValueRef offset;
|
LLVMValueRef offset;
|
||||||
|
|
||||||
x_stride = lp_build_const_scalar(bld->type, format_desc->block.bits/8);
|
x_stride = lp_build_const_vec(bld->type, format_desc->block.bits/8);
|
||||||
|
|
||||||
if(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
|
if(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
|
||||||
LLVMValueRef x_lo, x_hi;
|
LLVMValueRef x_lo, x_hi;
|
||||||
|
|
@ -195,9 +195,9 @@ lp_build_sample_offset(struct lp_build_context *bld,
|
||||||
y_hi = LLVMBuildLShr(bld->builder, y, bld->one, "");
|
y_hi = LLVMBuildLShr(bld->builder, y, bld->one, "");
|
||||||
|
|
||||||
x_stride_lo = x_stride;
|
x_stride_lo = x_stride;
|
||||||
y_stride_lo = lp_build_const_scalar(bld->type, 2*format_desc->block.bits/8);
|
y_stride_lo = lp_build_const_vec(bld->type, 2*format_desc->block.bits/8);
|
||||||
|
|
||||||
x_stride_hi = lp_build_const_scalar(bld->type, 4*format_desc->block.bits/8);
|
x_stride_hi = lp_build_const_vec(bld->type, 4*format_desc->block.bits/8);
|
||||||
y_stride_hi = LLVMBuildShl(bld->builder, y_stride, bld->one, "");
|
y_stride_hi = LLVMBuildShl(bld->builder, y_stride, bld->one, "");
|
||||||
|
|
||||||
x_offset_lo = lp_build_mul(bld, x_lo, x_stride_lo);
|
x_offset_lo = lp_build_mul(bld, x_lo, x_stride_lo);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
#define LP_BLD_SAMPLE_H
|
#define LP_BLD_SAMPLE_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
struct pipe_texture;
|
struct pipe_texture;
|
||||||
struct pipe_sampler_state;
|
struct pipe_sampler_state;
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,7 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
|
||||||
int chan;
|
int chan;
|
||||||
for (chan = 0; chan < 4; chan++) {
|
for (chan = 0; chan < 4; chan++) {
|
||||||
LLVMValueRef border_chan =
|
LLVMValueRef border_chan =
|
||||||
lp_build_const_scalar(bld->texel_type,
|
lp_build_const_vec(bld->texel_type,
|
||||||
bld->static_state->border_color[chan]);
|
bld->static_state->border_color[chan]);
|
||||||
texel[chan] = lp_build_select(&bld->texel_bld, use_border,
|
texel[chan] = lp_build_select(&bld->texel_bld, use_border,
|
||||||
border_chan, texel[chan]);
|
border_chan, texel[chan]);
|
||||||
|
|
@ -457,8 +457,8 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
|
||||||
struct lp_build_context *coord_bld = &bld->coord_bld;
|
struct lp_build_context *coord_bld = &bld->coord_bld;
|
||||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||||
struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
|
struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
|
||||||
LLVMValueRef two = lp_build_const_scalar(coord_bld->type, 2.0);
|
LLVMValueRef two = lp_build_const_vec(coord_bld->type, 2.0);
|
||||||
LLVMValueRef half = lp_build_const_scalar(coord_bld->type, 0.5);
|
LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5);
|
||||||
LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length);
|
LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length);
|
||||||
LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
|
LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
|
||||||
LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one);
|
LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one);
|
||||||
|
|
@ -512,7 +512,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
|
||||||
else {
|
else {
|
||||||
LLVMValueRef min, max;
|
LLVMValueRef min, max;
|
||||||
/* clamp to [0.5, length - 0.5] */
|
/* clamp to [0.5, length - 0.5] */
|
||||||
min = lp_build_const_scalar(coord_bld->type, 0.5F);
|
min = lp_build_const_vec(coord_bld->type, 0.5F);
|
||||||
max = lp_build_sub(coord_bld, length_f, min);
|
max = lp_build_sub(coord_bld, length_f, min);
|
||||||
coord = lp_build_clamp(coord_bld, coord, min, max);
|
coord = lp_build_clamp(coord_bld, coord, min, max);
|
||||||
}
|
}
|
||||||
|
|
@ -533,7 +533,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
|
||||||
if (bld->static_state->normalized_coords) {
|
if (bld->static_state->normalized_coords) {
|
||||||
/* min = -1.0 / (2 * length) = -0.5 / length */
|
/* min = -1.0 / (2 * length) = -0.5 / length */
|
||||||
min = lp_build_mul(coord_bld,
|
min = lp_build_mul(coord_bld,
|
||||||
lp_build_const_scalar(coord_bld->type, -0.5F),
|
lp_build_const_vec(coord_bld->type, -0.5F),
|
||||||
lp_build_rcp(coord_bld, length_f));
|
lp_build_rcp(coord_bld, length_f));
|
||||||
/* max = 1.0 - min */
|
/* max = 1.0 - min */
|
||||||
max = lp_build_sub(coord_bld, coord_bld->one, min);
|
max = lp_build_sub(coord_bld, coord_bld->one, min);
|
||||||
|
|
@ -545,7 +545,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* clamp to [-0.5, length + 0.5] */
|
/* clamp to [-0.5, length + 0.5] */
|
||||||
min = lp_build_const_scalar(coord_bld->type, -0.5F);
|
min = lp_build_const_vec(coord_bld->type, -0.5F);
|
||||||
max = lp_build_sub(coord_bld, length_f, min);
|
max = lp_build_sub(coord_bld, length_f, min);
|
||||||
coord = lp_build_clamp(coord_bld, coord, min, max);
|
coord = lp_build_clamp(coord_bld, coord, min, max);
|
||||||
coord = lp_build_sub(coord_bld, coord, half);
|
coord = lp_build_sub(coord_bld, coord, half);
|
||||||
|
|
@ -620,7 +620,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
|
||||||
LLVMValueRef min, max;
|
LLVMValueRef min, max;
|
||||||
/* min = -1.0 / (2 * length) = -0.5 / length */
|
/* min = -1.0 / (2 * length) = -0.5 / length */
|
||||||
min = lp_build_mul(coord_bld,
|
min = lp_build_mul(coord_bld,
|
||||||
lp_build_const_scalar(coord_bld->type, -0.5F),
|
lp_build_const_vec(coord_bld->type, -0.5F),
|
||||||
lp_build_rcp(coord_bld, length_f));
|
lp_build_rcp(coord_bld, length_f));
|
||||||
/* max = 1.0 - min */
|
/* max = 1.0 - min */
|
||||||
max = lp_build_sub(coord_bld, coord_bld->one, min);
|
max = lp_build_sub(coord_bld, coord_bld->one, min);
|
||||||
|
|
@ -665,7 +665,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
|
||||||
struct lp_build_context *coord_bld = &bld->coord_bld;
|
struct lp_build_context *coord_bld = &bld->coord_bld;
|
||||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||||
struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
|
struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
|
||||||
LLVMValueRef two = lp_build_const_scalar(coord_bld->type, 2.0);
|
LLVMValueRef two = lp_build_const_vec(coord_bld->type, 2.0);
|
||||||
LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length);
|
LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length);
|
||||||
LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
|
LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
|
||||||
LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one);
|
LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one);
|
||||||
|
|
@ -708,7 +708,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* clamp to [0.5, length - 0.5] */
|
/* clamp to [0.5, length - 0.5] */
|
||||||
min = lp_build_const_scalar(coord_bld->type, 0.5F);
|
min = lp_build_const_vec(coord_bld->type, 0.5F);
|
||||||
max = lp_build_sub(coord_bld, length_f, min);
|
max = lp_build_sub(coord_bld, length_f, min);
|
||||||
}
|
}
|
||||||
/* coord = clamp(coord, min, max) */
|
/* coord = clamp(coord, min, max) */
|
||||||
|
|
@ -724,7 +724,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
|
||||||
if (bld->static_state->normalized_coords) {
|
if (bld->static_state->normalized_coords) {
|
||||||
/* min = -1.0 / (2 * length) = -0.5 / length */
|
/* min = -1.0 / (2 * length) = -0.5 / length */
|
||||||
min = lp_build_mul(coord_bld,
|
min = lp_build_mul(coord_bld,
|
||||||
lp_build_const_scalar(coord_bld->type, -0.5F),
|
lp_build_const_vec(coord_bld->type, -0.5F),
|
||||||
lp_build_rcp(coord_bld, length_f));
|
lp_build_rcp(coord_bld, length_f));
|
||||||
/* max = length - min */
|
/* max = length - min */
|
||||||
max = lp_build_sub(coord_bld, length_f, min);
|
max = lp_build_sub(coord_bld, length_f, min);
|
||||||
|
|
@ -733,7 +733,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* clamp to [-0.5, length + 0.5] */
|
/* clamp to [-0.5, length + 0.5] */
|
||||||
min = lp_build_const_scalar(coord_bld->type, -0.5F);
|
min = lp_build_const_vec(coord_bld->type, -0.5F);
|
||||||
max = lp_build_sub(coord_bld, length_f, min);
|
max = lp_build_sub(coord_bld, length_f, min);
|
||||||
}
|
}
|
||||||
/* coord = clamp(coord, min, max) */
|
/* coord = clamp(coord, min, max) */
|
||||||
|
|
@ -843,87 +843,98 @@ lp_build_lod_selector(struct lp_build_sample_context *bld,
|
||||||
LLVMValueRef depth)
|
LLVMValueRef depth)
|
||||||
|
|
||||||
{
|
{
|
||||||
const int dims = texture_dims(bld->static_state->target);
|
if (bld->static_state->min_lod == bld->static_state->max_lod) {
|
||||||
struct lp_build_context *float_bld = &bld->float_bld;
|
/* User is forcing sampling from a particular mipmap level.
|
||||||
LLVMValueRef lod_bias = LLVMConstReal(LLVMFloatType(), bld->static_state->lod_bias);
|
* This is hit during mipmap generation.
|
||||||
LLVMValueRef min_lod = LLVMConstReal(LLVMFloatType(), bld->static_state->min_lod);
|
*/
|
||||||
LLVMValueRef max_lod = LLVMConstReal(LLVMFloatType(), bld->static_state->max_lod);
|
return LLVMConstReal(LLVMFloatType(), bld->static_state->min_lod);
|
||||||
|
|
||||||
LLVMValueRef index0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
|
||||||
LLVMValueRef index1 = LLVMConstInt(LLVMInt32Type(), 1, 0);
|
|
||||||
LLVMValueRef index2 = LLVMConstInt(LLVMInt32Type(), 2, 0);
|
|
||||||
|
|
||||||
LLVMValueRef s0, s1, s2;
|
|
||||||
LLVMValueRef t0, t1, t2;
|
|
||||||
LLVMValueRef r0, r1, r2;
|
|
||||||
LLVMValueRef dsdx, dsdy, dtdx, dtdy, drdx, drdy;
|
|
||||||
LLVMValueRef rho, lod;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dsdx = abs(s[1] - s[0]);
|
|
||||||
* dsdy = abs(s[2] - s[0]);
|
|
||||||
* dtdx = abs(t[1] - t[0]);
|
|
||||||
* dtdy = abs(t[2] - t[0]);
|
|
||||||
* drdx = abs(r[1] - r[0]);
|
|
||||||
* drdy = abs(r[2] - r[0]);
|
|
||||||
* XXX we're assuming a four-element quad in 2x2 layout here.
|
|
||||||
*/
|
|
||||||
s0 = LLVMBuildExtractElement(bld->builder, s, index0, "s0");
|
|
||||||
s1 = LLVMBuildExtractElement(bld->builder, s, index1, "s1");
|
|
||||||
s2 = LLVMBuildExtractElement(bld->builder, s, index2, "s2");
|
|
||||||
dsdx = LLVMBuildSub(bld->builder, s1, s0, "");
|
|
||||||
dsdx = lp_build_abs(float_bld, dsdx);
|
|
||||||
dsdy = LLVMBuildSub(bld->builder, s2, s0, "");
|
|
||||||
dsdy = lp_build_abs(float_bld, dsdy);
|
|
||||||
if (dims > 1) {
|
|
||||||
t0 = LLVMBuildExtractElement(bld->builder, t, index0, "t0");
|
|
||||||
t1 = LLVMBuildExtractElement(bld->builder, t, index1, "t1");
|
|
||||||
t2 = LLVMBuildExtractElement(bld->builder, t, index2, "t2");
|
|
||||||
dtdx = LLVMBuildSub(bld->builder, t1, t0, "");
|
|
||||||
dtdx = lp_build_abs(float_bld, dtdx);
|
|
||||||
dtdy = LLVMBuildSub(bld->builder, t2, t0, "");
|
|
||||||
dtdy = lp_build_abs(float_bld, dtdy);
|
|
||||||
if (dims > 2) {
|
|
||||||
r0 = LLVMBuildExtractElement(bld->builder, r, index0, "r0");
|
|
||||||
r1 = LLVMBuildExtractElement(bld->builder, r, index1, "r1");
|
|
||||||
r2 = LLVMBuildExtractElement(bld->builder, r, index2, "r2");
|
|
||||||
drdx = LLVMBuildSub(bld->builder, r1, r0, "");
|
|
||||||
drdx = lp_build_abs(float_bld, drdx);
|
|
||||||
drdy = LLVMBuildSub(bld->builder, r2, r0, "");
|
|
||||||
drdy = lp_build_abs(float_bld, drdy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
const int dims = texture_dims(bld->static_state->target);
|
||||||
|
struct lp_build_context *float_bld = &bld->float_bld;
|
||||||
|
LLVMValueRef lod_bias = LLVMConstReal(LLVMFloatType(),
|
||||||
|
bld->static_state->lod_bias);
|
||||||
|
LLVMValueRef min_lod = LLVMConstReal(LLVMFloatType(),
|
||||||
|
bld->static_state->min_lod);
|
||||||
|
LLVMValueRef max_lod = LLVMConstReal(LLVMFloatType(),
|
||||||
|
bld->static_state->max_lod);
|
||||||
|
|
||||||
/* Compute rho = max of all partial derivatives scaled by texture size.
|
LLVMValueRef index0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||||
* XXX this could be vectorized somewhat
|
LLVMValueRef index1 = LLVMConstInt(LLVMInt32Type(), 1, 0);
|
||||||
*/
|
LLVMValueRef index2 = LLVMConstInt(LLVMInt32Type(), 2, 0);
|
||||||
rho = LLVMBuildMul(bld->builder,
|
|
||||||
lp_build_max(float_bld, dsdx, dsdy),
|
LLVMValueRef s0, s1, s2;
|
||||||
lp_build_int_to_float(float_bld, width), "");
|
LLVMValueRef t0, t1, t2;
|
||||||
if (dims > 1) {
|
LLVMValueRef r0, r1, r2;
|
||||||
LLVMValueRef max;
|
LLVMValueRef dsdx, dsdy, dtdx, dtdy, drdx, drdy;
|
||||||
max = LLVMBuildMul(bld->builder,
|
LLVMValueRef rho, lod;
|
||||||
lp_build_max(float_bld, dtdx, dtdy),
|
|
||||||
lp_build_int_to_float(float_bld, height), "");
|
/*
|
||||||
rho = lp_build_max(float_bld, rho, max);
|
* dsdx = abs(s[1] - s[0]);
|
||||||
if (dims > 2) {
|
* dsdy = abs(s[2] - s[0]);
|
||||||
|
* dtdx = abs(t[1] - t[0]);
|
||||||
|
* dtdy = abs(t[2] - t[0]);
|
||||||
|
* drdx = abs(r[1] - r[0]);
|
||||||
|
* drdy = abs(r[2] - r[0]);
|
||||||
|
* XXX we're assuming a four-element quad in 2x2 layout here.
|
||||||
|
*/
|
||||||
|
s0 = LLVMBuildExtractElement(bld->builder, s, index0, "s0");
|
||||||
|
s1 = LLVMBuildExtractElement(bld->builder, s, index1, "s1");
|
||||||
|
s2 = LLVMBuildExtractElement(bld->builder, s, index2, "s2");
|
||||||
|
dsdx = LLVMBuildSub(bld->builder, s1, s0, "");
|
||||||
|
dsdx = lp_build_abs(float_bld, dsdx);
|
||||||
|
dsdy = LLVMBuildSub(bld->builder, s2, s0, "");
|
||||||
|
dsdy = lp_build_abs(float_bld, dsdy);
|
||||||
|
if (dims > 1) {
|
||||||
|
t0 = LLVMBuildExtractElement(bld->builder, t, index0, "t0");
|
||||||
|
t1 = LLVMBuildExtractElement(bld->builder, t, index1, "t1");
|
||||||
|
t2 = LLVMBuildExtractElement(bld->builder, t, index2, "t2");
|
||||||
|
dtdx = LLVMBuildSub(bld->builder, t1, t0, "");
|
||||||
|
dtdx = lp_build_abs(float_bld, dtdx);
|
||||||
|
dtdy = LLVMBuildSub(bld->builder, t2, t0, "");
|
||||||
|
dtdy = lp_build_abs(float_bld, dtdy);
|
||||||
|
if (dims > 2) {
|
||||||
|
r0 = LLVMBuildExtractElement(bld->builder, r, index0, "r0");
|
||||||
|
r1 = LLVMBuildExtractElement(bld->builder, r, index1, "r1");
|
||||||
|
r2 = LLVMBuildExtractElement(bld->builder, r, index2, "r2");
|
||||||
|
drdx = LLVMBuildSub(bld->builder, r1, r0, "");
|
||||||
|
drdx = lp_build_abs(float_bld, drdx);
|
||||||
|
drdy = LLVMBuildSub(bld->builder, r2, r0, "");
|
||||||
|
drdy = lp_build_abs(float_bld, drdy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute rho = max of all partial derivatives scaled by texture size.
|
||||||
|
* XXX this could be vectorized somewhat
|
||||||
|
*/
|
||||||
|
rho = LLVMBuildMul(bld->builder,
|
||||||
|
lp_build_max(float_bld, dsdx, dsdy),
|
||||||
|
lp_build_int_to_float(float_bld, width), "");
|
||||||
|
if (dims > 1) {
|
||||||
|
LLVMValueRef max;
|
||||||
max = LLVMBuildMul(bld->builder,
|
max = LLVMBuildMul(bld->builder,
|
||||||
lp_build_max(float_bld, drdx, drdy),
|
lp_build_max(float_bld, dtdx, dtdy),
|
||||||
lp_build_int_to_float(float_bld, depth), "");
|
lp_build_int_to_float(float_bld, height), "");
|
||||||
rho = lp_build_max(float_bld, rho, max);
|
rho = lp_build_max(float_bld, rho, max);
|
||||||
|
if (dims > 2) {
|
||||||
|
max = LLVMBuildMul(bld->builder,
|
||||||
|
lp_build_max(float_bld, drdx, drdy),
|
||||||
|
lp_build_int_to_float(float_bld, depth), "");
|
||||||
|
rho = lp_build_max(float_bld, rho, max);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* compute lod = log2(rho) */
|
||||||
|
lod = lp_build_log2(float_bld, rho);
|
||||||
|
|
||||||
|
/* add lod bias */
|
||||||
|
lod = LLVMBuildAdd(bld->builder, lod, lod_bias, "LOD bias");
|
||||||
|
|
||||||
|
/* clamp lod */
|
||||||
|
lod = lp_build_clamp(float_bld, lod, min_lod, max_lod);
|
||||||
|
|
||||||
|
return lod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compute lod = log2(rho) */
|
|
||||||
lod = lp_build_log2(float_bld, rho);
|
|
||||||
|
|
||||||
/* add lod bias */
|
|
||||||
lod = LLVMBuildAdd(bld->builder, lod, lod_bias, "LOD bias");
|
|
||||||
|
|
||||||
/* clamp lod */
|
|
||||||
lod = lp_build_clamp(float_bld, lod, min_lod, max_lod);
|
|
||||||
|
|
||||||
return lod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -986,7 +997,7 @@ lp_build_linear_mip_levels(struct lp_build_sample_context *bld,
|
||||||
last_level);
|
last_level);
|
||||||
/* compute level 1 and clamp to legal range of levels */
|
/* compute level 1 and clamp to legal range of levels */
|
||||||
*level1_out = lp_build_add(int_bld, *level0_out, int_bld->one);
|
*level1_out = lp_build_add(int_bld, *level0_out, int_bld->one);
|
||||||
*level1_out = lp_build_min(int_bld, *level1_out, int_bld->zero);
|
*level1_out = lp_build_min(int_bld, *level1_out, last_level);
|
||||||
|
|
||||||
*weight_out = lp_build_fract(float_bld, lod);
|
*weight_out = lp_build_fract(float_bld, lod);
|
||||||
}
|
}
|
||||||
|
|
@ -1215,7 +1226,7 @@ static LLVMValueRef
|
||||||
lp_build_cube_ima(struct lp_build_context *coord_bld, LLVMValueRef coord)
|
lp_build_cube_ima(struct lp_build_context *coord_bld, LLVMValueRef coord)
|
||||||
{
|
{
|
||||||
/* ima = -0.5 / abs(coord); */
|
/* ima = -0.5 / abs(coord); */
|
||||||
LLVMValueRef negHalf = lp_build_const_scalar(coord_bld->type, -0.5);
|
LLVMValueRef negHalf = lp_build_const_vec(coord_bld->type, -0.5);
|
||||||
LLVMValueRef absCoord = lp_build_abs(coord_bld, coord);
|
LLVMValueRef absCoord = lp_build_abs(coord_bld, coord);
|
||||||
LLVMValueRef ima = lp_build_mul(coord_bld, negHalf,
|
LLVMValueRef ima = lp_build_mul(coord_bld, negHalf,
|
||||||
lp_build_rcp(coord_bld, absCoord));
|
lp_build_rcp(coord_bld, absCoord));
|
||||||
|
|
@ -1235,7 +1246,7 @@ lp_build_cube_coord(struct lp_build_context *coord_bld,
|
||||||
LLVMValueRef coord, LLVMValueRef ima)
|
LLVMValueRef coord, LLVMValueRef ima)
|
||||||
{
|
{
|
||||||
/* return negate(coord) * ima * sign + 0.5; */
|
/* return negate(coord) * ima * sign + 0.5; */
|
||||||
LLVMValueRef half = lp_build_const_scalar(coord_bld->type, 0.5);
|
LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5);
|
||||||
LLVMValueRef res;
|
LLVMValueRef res;
|
||||||
|
|
||||||
assert(negate_coord == +1 || negate_coord == -1);
|
assert(negate_coord == +1 || negate_coord == -1);
|
||||||
|
|
@ -1413,6 +1424,85 @@ lp_build_cube_lookup(struct lp_build_sample_context *bld,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sample the texture/mipmap using given image filter and mip filter.
|
||||||
|
* data0_ptr and data1_ptr point to the two mipmap levels to sample
|
||||||
|
* from. width0/1_vec, height0/1_vec, depth0/1_vec indicate their sizes.
|
||||||
|
* If we're using nearest miplevel sampling the '1' values will be null/unused.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
lp_build_sample_mipmap(struct lp_build_sample_context *bld,
|
||||||
|
unsigned img_filter,
|
||||||
|
unsigned mip_filter,
|
||||||
|
LLVMValueRef s,
|
||||||
|
LLVMValueRef t,
|
||||||
|
LLVMValueRef r,
|
||||||
|
LLVMValueRef lod_fpart,
|
||||||
|
LLVMValueRef width0_vec,
|
||||||
|
LLVMValueRef width1_vec,
|
||||||
|
LLVMValueRef height0_vec,
|
||||||
|
LLVMValueRef height1_vec,
|
||||||
|
LLVMValueRef depth0_vec,
|
||||||
|
LLVMValueRef depth1_vec,
|
||||||
|
LLVMValueRef row_stride0_vec,
|
||||||
|
LLVMValueRef row_stride1_vec,
|
||||||
|
LLVMValueRef img_stride0_vec,
|
||||||
|
LLVMValueRef img_stride1_vec,
|
||||||
|
LLVMValueRef data_ptr0,
|
||||||
|
LLVMValueRef data_ptr1,
|
||||||
|
LLVMValueRef *colors_out)
|
||||||
|
{
|
||||||
|
LLVMValueRef colors0[4], colors1[4];
|
||||||
|
int chan;
|
||||||
|
|
||||||
|
if (img_filter == PIPE_TEX_FILTER_NEAREST) {
|
||||||
|
lp_build_sample_image_nearest(bld,
|
||||||
|
width0_vec, height0_vec, depth0_vec,
|
||||||
|
row_stride0_vec, img_stride0_vec,
|
||||||
|
data_ptr0, s, t, r, colors0);
|
||||||
|
|
||||||
|
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
||||||
|
/* sample the second mipmap level, and interp */
|
||||||
|
lp_build_sample_image_nearest(bld,
|
||||||
|
width1_vec, height1_vec, depth1_vec,
|
||||||
|
row_stride1_vec, img_stride1_vec,
|
||||||
|
data_ptr1, s, t, r, colors1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(img_filter == PIPE_TEX_FILTER_LINEAR);
|
||||||
|
|
||||||
|
lp_build_sample_image_linear(bld,
|
||||||
|
width0_vec, height0_vec, depth0_vec,
|
||||||
|
row_stride0_vec, img_stride0_vec,
|
||||||
|
data_ptr0, s, t, r, colors0);
|
||||||
|
|
||||||
|
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
||||||
|
/* sample the second mipmap level, and interp */
|
||||||
|
lp_build_sample_image_linear(bld,
|
||||||
|
width1_vec, height1_vec, depth1_vec,
|
||||||
|
row_stride1_vec, img_stride1_vec,
|
||||||
|
data_ptr1, s, t, r, colors1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
||||||
|
/* interpolate samples from the two mipmap levels */
|
||||||
|
for (chan = 0; chan < 4; chan++) {
|
||||||
|
colors_out[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart,
|
||||||
|
colors0[chan], colors1[chan]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* use first/only level's colors */
|
||||||
|
for (chan = 0; chan < 4; chan++) {
|
||||||
|
colors_out[chan] = colors0[chan];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General texture sampling codegen.
|
* General texture sampling codegen.
|
||||||
* This function handles texture sampling for all texture targets (1D,
|
* This function handles texture sampling for all texture targets (1D,
|
||||||
|
|
@ -1435,6 +1525,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
|
||||||
LLVMValueRef data_array,
|
LLVMValueRef data_array,
|
||||||
LLVMValueRef *colors_out)
|
LLVMValueRef *colors_out)
|
||||||
{
|
{
|
||||||
|
struct lp_build_context *float_bld = &bld->float_bld;
|
||||||
const unsigned mip_filter = bld->static_state->min_mip_filter;
|
const unsigned mip_filter = bld->static_state->min_mip_filter;
|
||||||
const unsigned min_filter = bld->static_state->min_img_filter;
|
const unsigned min_filter = bld->static_state->min_img_filter;
|
||||||
const unsigned mag_filter = bld->static_state->mag_img_filter;
|
const unsigned mag_filter = bld->static_state->mag_img_filter;
|
||||||
|
|
@ -1446,7 +1537,6 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
|
||||||
LLVMValueRef row_stride0_vec = NULL, row_stride1_vec = NULL;
|
LLVMValueRef row_stride0_vec = NULL, row_stride1_vec = NULL;
|
||||||
LLVMValueRef img_stride0_vec = NULL, img_stride1_vec = NULL;
|
LLVMValueRef img_stride0_vec = NULL, img_stride1_vec = NULL;
|
||||||
LLVMValueRef data_ptr0, data_ptr1;
|
LLVMValueRef data_ptr0, data_ptr1;
|
||||||
int chan;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
printf("%s mip %d min %d mag %d\n", __FUNCTION__,
|
printf("%s mip %d min %d mag %d\n", __FUNCTION__,
|
||||||
|
|
@ -1454,16 +1544,24 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the level of detail (mipmap level index(es)).
|
* Compute the level of detail (float).
|
||||||
|
*/
|
||||||
|
if (min_filter != mag_filter ||
|
||||||
|
mip_filter != PIPE_TEX_MIPFILTER_NONE) {
|
||||||
|
/* Need to compute lod either to choose mipmap levels or to
|
||||||
|
* distinguish between minification/magnification with one mipmap level.
|
||||||
|
*/
|
||||||
|
lod = lp_build_lod_selector(bld, s, t, r, width, height, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute integer mipmap level(s) to fetch texels from.
|
||||||
*/
|
*/
|
||||||
if (mip_filter == PIPE_TEX_MIPFILTER_NONE) {
|
if (mip_filter == PIPE_TEX_MIPFILTER_NONE) {
|
||||||
/* always use mip level 0 */
|
/* always use mip level 0 */
|
||||||
ilevel0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
ilevel0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* compute float LOD */
|
|
||||||
lod = lp_build_lod_selector(bld, s, t, r, width, height, depth);
|
|
||||||
|
|
||||||
if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
|
if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
|
||||||
lp_build_nearest_mip_level(bld, unit, lod, &ilevel0);
|
lp_build_nearest_mip_level(bld, unit, lod, &ilevel0);
|
||||||
}
|
}
|
||||||
|
|
@ -1499,7 +1597,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
||||||
/* compute width, height, depth for second mipmap level at ilevel1 */
|
/* compute width, height, depth for second mipmap level at 'ilevel1' */
|
||||||
width1_vec = lp_build_minify(bld, width_vec, ilevel1_vec);
|
width1_vec = lp_build_minify(bld, width_vec, ilevel1_vec);
|
||||||
if (dims >= 2) {
|
if (dims >= 2) {
|
||||||
height1_vec = lp_build_minify(bld, height_vec, ilevel1_vec);
|
height1_vec = lp_build_minify(bld, height_vec, ilevel1_vec);
|
||||||
|
|
@ -1516,7 +1614,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Choose cube face, recompute texcoords.
|
* Choose cube face, recompute per-face texcoords.
|
||||||
*/
|
*/
|
||||||
if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
|
if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
|
||||||
LLVMValueRef face, face_s, face_t;
|
LLVMValueRef face, face_s, face_t;
|
||||||
|
|
@ -1538,62 +1636,67 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
|
||||||
/*
|
/*
|
||||||
* Get/interpolate texture colors.
|
* Get/interpolate texture colors.
|
||||||
*/
|
*/
|
||||||
/* XXX temporarily force this path: */
|
if (min_filter == mag_filter) {
|
||||||
if (1 /*min_filter == mag_filter*/) {
|
/* no need to distinquish between minification and magnification */
|
||||||
/* same filter for minification or magnification */
|
lp_build_sample_mipmap(bld, min_filter, mip_filter, s, t, r, lod_fpart,
|
||||||
LLVMValueRef colors0[4], colors1[4];
|
width0_vec, width1_vec,
|
||||||
|
height0_vec, height1_vec,
|
||||||
if (min_filter == PIPE_TEX_FILTER_NEAREST) {
|
depth0_vec, depth1_vec,
|
||||||
lp_build_sample_image_nearest(bld,
|
row_stride0_vec, row_stride1_vec,
|
||||||
width0_vec, height0_vec, depth0_vec,
|
img_stride0_vec, img_stride1_vec,
|
||||||
row_stride0_vec, img_stride0_vec,
|
data_ptr0, data_ptr1,
|
||||||
data_ptr0, s, t, r, colors0);
|
colors_out);
|
||||||
|
|
||||||
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
|
||||||
/* sample the second mipmap level, and interp */
|
|
||||||
lp_build_sample_image_nearest(bld,
|
|
||||||
width1_vec, height1_vec, depth1_vec,
|
|
||||||
row_stride1_vec, img_stride1_vec,
|
|
||||||
data_ptr1, s, t, r, colors1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(min_filter == PIPE_TEX_FILTER_LINEAR);
|
|
||||||
|
|
||||||
lp_build_sample_image_linear(bld,
|
|
||||||
width0_vec, height0_vec, depth0_vec,
|
|
||||||
row_stride0_vec, img_stride0_vec,
|
|
||||||
data_ptr0, s, t, r, colors0);
|
|
||||||
|
|
||||||
|
|
||||||
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
|
||||||
/* sample the second mipmap level, and interp */
|
|
||||||
lp_build_sample_image_linear(bld,
|
|
||||||
width1_vec, height1_vec, depth1_vec,
|
|
||||||
row_stride1_vec, img_stride1_vec,
|
|
||||||
data_ptr1, s, t, r, colors1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
|
||||||
/* interpolate samples from the two mipmap levels */
|
|
||||||
for (chan = 0; chan < 4; chan++) {
|
|
||||||
colors_out[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart,
|
|
||||||
colors0[chan], colors1[chan]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* use first/only level's colors */
|
|
||||||
for (chan = 0; chan < 4; chan++) {
|
|
||||||
colors_out[chan] = colors0[chan];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* emit conditional to choose min image filter or mag image filter
|
/* Emit conditional to choose min image filter or mag image filter
|
||||||
* depending on the lod being >0 or <= 0, respectively.
|
* depending on the lod being >0 or <= 0, respectively.
|
||||||
*/
|
*/
|
||||||
abort();
|
struct lp_build_flow_context *flow_ctx;
|
||||||
|
struct lp_build_if_state if_ctx;
|
||||||
|
LLVMValueRef minify;
|
||||||
|
|
||||||
|
flow_ctx = lp_build_flow_create(bld->builder);
|
||||||
|
lp_build_flow_scope_begin(flow_ctx);
|
||||||
|
|
||||||
|
lp_build_flow_scope_declare(flow_ctx, &colors_out[0]);
|
||||||
|
lp_build_flow_scope_declare(flow_ctx, &colors_out[1]);
|
||||||
|
lp_build_flow_scope_declare(flow_ctx, &colors_out[2]);
|
||||||
|
lp_build_flow_scope_declare(flow_ctx, &colors_out[3]);
|
||||||
|
|
||||||
|
/* minify = lod > 0.0 */
|
||||||
|
minify = LLVMBuildFCmp(bld->builder, LLVMRealUGE,
|
||||||
|
lod, float_bld->zero, "");
|
||||||
|
|
||||||
|
lp_build_if(&if_ctx, flow_ctx, bld->builder, minify);
|
||||||
|
{
|
||||||
|
/* Use the minification filter */
|
||||||
|
lp_build_sample_mipmap(bld, min_filter, mip_filter,
|
||||||
|
s, t, r, lod_fpart,
|
||||||
|
width0_vec, width1_vec,
|
||||||
|
height0_vec, height1_vec,
|
||||||
|
depth0_vec, depth1_vec,
|
||||||
|
row_stride0_vec, row_stride1_vec,
|
||||||
|
img_stride0_vec, img_stride1_vec,
|
||||||
|
data_ptr0, data_ptr1,
|
||||||
|
colors_out);
|
||||||
|
}
|
||||||
|
lp_build_else(&if_ctx);
|
||||||
|
{
|
||||||
|
/* Use the magnification filter */
|
||||||
|
lp_build_sample_mipmap(bld, mag_filter, mip_filter,
|
||||||
|
s, t, r, lod_fpart,
|
||||||
|
width0_vec, width1_vec,
|
||||||
|
height0_vec, height1_vec,
|
||||||
|
depth0_vec, depth1_vec,
|
||||||
|
row_stride0_vec, row_stride1_vec,
|
||||||
|
img_stride0_vec, img_stride1_vec,
|
||||||
|
data_ptr0, data_ptr1,
|
||||||
|
colors_out);
|
||||||
|
}
|
||||||
|
lp_build_endif(&if_ctx);
|
||||||
|
|
||||||
|
lp_build_flow_scope_end(flow_ctx);
|
||||||
|
lp_build_flow_destroy(flow_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1605,7 +1708,7 @@ lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder,
|
||||||
LLVMValueRef packed,
|
LLVMValueRef packed,
|
||||||
LLVMValueRef *rgba)
|
LLVMValueRef *rgba)
|
||||||
{
|
{
|
||||||
LLVMValueRef mask = lp_build_int_const_scalar(dst_type, 0xff);
|
LLVMValueRef mask = lp_build_const_int_vec(dst_type, 0xff);
|
||||||
unsigned chan;
|
unsigned chan;
|
||||||
|
|
||||||
/* Decode the input vector components */
|
/* Decode the input vector components */
|
||||||
|
|
@ -1617,7 +1720,7 @@ lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder,
|
||||||
input = packed;
|
input = packed;
|
||||||
|
|
||||||
if(start)
|
if(start)
|
||||||
input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(dst_type, start), "");
|
input = LLVMBuildLShr(builder, input, lp_build_const_int_vec(dst_type, start), "");
|
||||||
|
|
||||||
if(stop < 32)
|
if(stop < 32)
|
||||||
input = LLVMBuildAnd(builder, input, mask, "");
|
input = LLVMBuildAnd(builder, input, mask, "");
|
||||||
|
|
@ -1679,17 +1782,17 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
|
||||||
t = LLVMBuildFPToSI(builder, t, i32_vec_type, "");
|
t = LLVMBuildFPToSI(builder, t, i32_vec_type, "");
|
||||||
|
|
||||||
/* subtract 0.5 (add -128) */
|
/* subtract 0.5 (add -128) */
|
||||||
i32_c128 = lp_build_int_const_scalar(i32.type, -128);
|
i32_c128 = lp_build_const_int_vec(i32.type, -128);
|
||||||
s = LLVMBuildAdd(builder, s, i32_c128, "");
|
s = LLVMBuildAdd(builder, s, i32_c128, "");
|
||||||
t = LLVMBuildAdd(builder, t, i32_c128, "");
|
t = LLVMBuildAdd(builder, t, i32_c128, "");
|
||||||
|
|
||||||
/* compute floor (shift right 8) */
|
/* compute floor (shift right 8) */
|
||||||
i32_c8 = lp_build_int_const_scalar(i32.type, 8);
|
i32_c8 = lp_build_const_int_vec(i32.type, 8);
|
||||||
s_ipart = LLVMBuildAShr(builder, s, i32_c8, "");
|
s_ipart = LLVMBuildAShr(builder, s, i32_c8, "");
|
||||||
t_ipart = LLVMBuildAShr(builder, t, i32_c8, "");
|
t_ipart = LLVMBuildAShr(builder, t, i32_c8, "");
|
||||||
|
|
||||||
/* compute fractional part (AND with 0xff) */
|
/* compute fractional part (AND with 0xff) */
|
||||||
i32_c255 = lp_build_int_const_scalar(i32.type, 255);
|
i32_c255 = lp_build_const_int_vec(i32.type, 255);
|
||||||
s_fpart = LLVMBuildAnd(builder, s, i32_c255, "");
|
s_fpart = LLVMBuildAnd(builder, s, i32_c255, "");
|
||||||
t_fpart = LLVMBuildAnd(builder, t, i32_c255, "");
|
t_fpart = LLVMBuildAnd(builder, t, i32_c255, "");
|
||||||
|
|
||||||
|
|
@ -1856,7 +1959,7 @@ lp_build_sample_compare(struct lp_build_sample_context *bld,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(res);
|
assert(res);
|
||||||
res = lp_build_mul(texel_bld, res, lp_build_const_scalar(texel_bld->type, 0.25));
|
res = lp_build_mul(texel_bld, res, lp_build_const_vec(texel_bld->type, 0.25));
|
||||||
|
|
||||||
/* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
|
/* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
|
||||||
for(chan = 0; chan < 3; ++chan)
|
for(chan = 0; chan < 3; ++chan)
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#define LP_BLD_STRUCT_H
|
#define LP_BLD_STRUCT_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
#include <llvm-c/Target.h>
|
#include <llvm-c/Target.h>
|
||||||
|
|
||||||
#include "util/u_debug.h"
|
#include "util/u_debug.h"
|
||||||
|
|
|
||||||
|
|
@ -144,9 +144,9 @@ lp_build_broadcast_aos(struct lp_build_context *bld,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(shift > 0)
|
if(shift > 0)
|
||||||
tmp = LLVMBuildLShr(bld->builder, a, lp_build_int_const_scalar(type4, shift*type.width), "");
|
tmp = LLVMBuildLShr(bld->builder, a, lp_build_const_int_vec(type4, shift*type.width), "");
|
||||||
if(shift < 0)
|
if(shift < 0)
|
||||||
tmp = LLVMBuildShl(bld->builder, a, lp_build_int_const_scalar(type4, -shift*type.width), "");
|
tmp = LLVMBuildShl(bld->builder, a, lp_build_const_int_vec(type4, -shift*type.width), "");
|
||||||
|
|
||||||
assert(tmp);
|
assert(tmp);
|
||||||
if(tmp)
|
if(tmp)
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#define LP_BLD_SWIZZLE_H
|
#define LP_BLD_SWIZZLE_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
struct lp_type;
|
struct lp_type;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
#ifndef LP_BLD_TGSI_H
|
#ifndef LP_BLD_TGSI_H
|
||||||
#define LP_BLD_TGSI_H
|
#define LP_BLD_TGSI_H
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
struct tgsi_token;
|
struct tgsi_token;
|
||||||
|
|
|
||||||
|
|
@ -475,7 +475,7 @@ emit_store(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TGSI_SAT_MINUS_PLUS_ONE:
|
case TGSI_SAT_MINUS_PLUS_ONE:
|
||||||
value = lp_build_max(&bld->base, value, lp_build_const_scalar(bld->base.type, -1.0));
|
value = lp_build_max(&bld->base, value, lp_build_const_vec(bld->base.type, -1.0));
|
||||||
value = lp_build_min(&bld->base, value, bld->base.one);
|
value = lp_build_min(&bld->base, value, bld->base.one);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -996,7 +996,7 @@ emit_instruction(
|
||||||
src0 = emit_fetch( bld, inst, 0, chan_index );
|
src0 = emit_fetch( bld, inst, 0, chan_index );
|
||||||
src1 = emit_fetch( bld, inst, 1, chan_index );
|
src1 = emit_fetch( bld, inst, 1, chan_index );
|
||||||
src2 = emit_fetch( bld, inst, 2, chan_index );
|
src2 = emit_fetch( bld, inst, 2, chan_index );
|
||||||
tmp1 = lp_build_const_scalar(bld->base.type, 0.5);
|
tmp1 = lp_build_const_vec(bld->base.type, 0.5);
|
||||||
tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GREATER, src2, tmp1);
|
tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GREATER, src2, tmp1);
|
||||||
dst0[chan_index] = lp_build_select( &bld->base, tmp0, src0, src1 );
|
dst0[chan_index] = lp_build_select( &bld->base, tmp0, src0, src1 );
|
||||||
}
|
}
|
||||||
|
|
@ -1713,7 +1713,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
|
||||||
assert(num_immediates < LP_MAX_IMMEDIATES);
|
assert(num_immediates < LP_MAX_IMMEDIATES);
|
||||||
for( i = 0; i < size; ++i )
|
for( i = 0; i < size; ++i )
|
||||||
bld.immediates[num_immediates][i] =
|
bld.immediates[num_immediates][i] =
|
||||||
lp_build_const_scalar(type, parse.FullToken.FullImmediate.u[i].Float);
|
lp_build_const_vec(type, parse.FullToken.FullImmediate.u[i].Float);
|
||||||
for( i = size; i < 4; ++i )
|
for( i = size; i < 4; ++i )
|
||||||
bld.immediates[num_immediates][i] = bld.base.undef;
|
bld.immediates[num_immediates][i] = bld.base.undef;
|
||||||
num_immediates++;
|
num_immediates++;
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@
|
||||||
#define LP_BLD_TYPE_H
|
#define LP_BLD_TYPE_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "pipe/p_compiler.h"
|
||||||
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
#include <pipe/p_compiler.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -142,8 +142,10 @@ cell_is_format_supported( struct pipe_screen *screen,
|
||||||
format == PIPE_FORMAT_A8B8G8R8_SRGB)
|
format == PIPE_FORMAT_A8B8G8R8_SRGB)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
|
if (tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
|
||||||
if (!winsys->is_displaytarget_format_supported(winsys, format))
|
PIPE_TEXTURE_USAGE_SCANOUT |
|
||||||
|
PIPE_TEXTURE_USAGE_SHARED)) {
|
||||||
|
if (!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ cell_displaytarget_layout(struct pipe_screen *screen,
|
||||||
/* Round up the surface size to a multiple of the tile size?
|
/* Round up the surface size to a multiple of the tile size?
|
||||||
*/
|
*/
|
||||||
ct->dt = winsys->displaytarget_create(winsys,
|
ct->dt = winsys->displaytarget_create(winsys,
|
||||||
|
ct->base->tex_usage,
|
||||||
ct->base.format,
|
ct->base.format,
|
||||||
ct->base.width0,
|
ct->base.width0,
|
||||||
ct->base.height0,
|
ct->base.height0,
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ struct pipe_context *brw_create_context(struct pipe_screen *screen,
|
||||||
brw->sws = brw_screen(screen)->sws;
|
brw->sws = brw_screen(screen)->sws;
|
||||||
brw->chipset = brw_screen(screen)->chipset;
|
brw->chipset = brw_screen(screen)->chipset;
|
||||||
|
|
||||||
|
brw_tex_init( brw );
|
||||||
brw_pipe_blend_init( brw );
|
brw_pipe_blend_init( brw );
|
||||||
brw_pipe_depth_stencil_init( brw );
|
brw_pipe_depth_stencil_init( brw );
|
||||||
brw_pipe_framebuffer_init( brw );
|
brw_pipe_framebuffer_init( brw );
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,11 @@ Done so far is:
|
||||||
|
|
||||||
- depth testing
|
- depth testing
|
||||||
|
|
||||||
- texture sampling (not all state/formats are supported)
|
- texture sampling
|
||||||
|
- 1D/2D/3D/cube maps supported
|
||||||
|
- all texture wrap modes supported
|
||||||
|
- all texture filtering modes supported
|
||||||
|
- perhaps not all texture formats yet supported
|
||||||
|
|
||||||
- fragment shader TGSI translation
|
- fragment shader TGSI translation
|
||||||
- same level of support as the TGSI SSE2 exec machine, with the exception
|
- same level of support as the TGSI SSE2 exec machine, with the exception
|
||||||
|
|
@ -37,8 +41,6 @@ To do (probably by this order):
|
||||||
|
|
||||||
- code generate stipple and stencil testing
|
- code generate stipple and stencil testing
|
||||||
|
|
||||||
- translate the remaining bits of texture sampling state
|
|
||||||
|
|
||||||
- translate TGSI control flow instructions, and all other remaining opcodes
|
- translate TGSI control flow instructions, and all other remaining opcodes
|
||||||
|
|
||||||
- integrate with the draw module for VS code generation
|
- integrate with the draw module for VS code generation
|
||||||
|
|
@ -57,7 +59,7 @@ Requirements
|
||||||
|
|
||||||
See /proc/cpuinfo to know what your CPU supports.
|
See /proc/cpuinfo to know what your CPU supports.
|
||||||
|
|
||||||
- LLVM 2.6.
|
- LLVM 2.6 (or later)
|
||||||
|
|
||||||
For Linux, on a recent Debian based distribution do:
|
For Linux, on a recent Debian based distribution do:
|
||||||
|
|
||||||
|
|
@ -67,6 +69,9 @@ Requirements
|
||||||
http://people.freedesktop.org/~jrfonseca/llvm/ and set the LLVM environment
|
http://people.freedesktop.org/~jrfonseca/llvm/ and set the LLVM environment
|
||||||
variable to the extracted path.
|
variable to the extracted path.
|
||||||
|
|
||||||
|
The version of LLVM from SVN ("2.7svn") from mid-March 2010 seems pretty
|
||||||
|
stable and has some features not in version 2.6.
|
||||||
|
|
||||||
- scons (optional)
|
- scons (optional)
|
||||||
|
|
||||||
- udis86, http://udis86.sourceforge.net/ (optional):
|
- udis86, http://udis86.sourceforge.net/ (optional):
|
||||||
|
|
@ -140,11 +145,13 @@ Development Notes
|
||||||
then skim through the lp_bld_* functions called in there, and the comments
|
then skim through the lp_bld_* functions called in there, and the comments
|
||||||
at the top of the lp_bld_*.c functions.
|
at the top of the lp_bld_*.c functions.
|
||||||
|
|
||||||
- All lp_bld_*.[ch] are isolated from the rest of the driver, and could/may be
|
- The driver-independent parts of the LLVM / Gallium code are found in
|
||||||
put in a stand-alone Gallium state -> LLVM IR translation module.
|
src/gallium/auxiliary/gallivm/. The filenames and function prefixes
|
||||||
|
need to be renamed from "lp_bld_" to something else though.
|
||||||
|
|
||||||
- We use LLVM-C bindings for now. They are not documented, but follow the C++
|
- We use LLVM-C bindings for now. They are not documented, but follow the C++
|
||||||
interfaces very closely, and appear to be complete enough for code
|
interfaces very closely, and appear to be complete enough for code
|
||||||
generation. See
|
generation. See
|
||||||
http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html
|
http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html
|
||||||
for a stand-alone example.
|
for a stand-alone example.
|
||||||
|
See the llvm-c/Core.h file for reference.
|
||||||
|
|
|
||||||
|
|
@ -204,8 +204,10 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
|
if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
|
||||||
if(!winsys->is_displaytarget_format_supported(winsys, format))
|
PIPE_TEXTURE_USAGE_SCANOUT |
|
||||||
|
PIPE_TEXTURE_USAGE_SHARED)) {
|
||||||
|
if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
#ifndef LP_SCREEN_H
|
#ifndef LP_SCREEN_H
|
||||||
#define LP_SCREEN_H
|
#define LP_SCREEN_H
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
#include <llvm-c/ExecutionEngine.h>
|
#include <llvm-c/ExecutionEngine.h>
|
||||||
|
|
||||||
#include "pipe/p_screen.h"
|
#include "pipe/p_screen.h"
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
#ifndef LP_STATE_H
|
#ifndef LP_STATE_H
|
||||||
#define LP_STATE_H
|
#define LP_STATE_H
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
#include "pipe/p_state.h"
|
#include "pipe/p_state.h"
|
||||||
#include "tgsi/tgsi_scan.h"
|
#include "tgsi/tgsi_scan.h"
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ generate_tri_edge_mask(LLVMBuilderRef builder,
|
||||||
LLVMConstInt(LLVMInt32Type(), INT_MIN, 0),
|
LLVMConstInt(LLVMInt32Type(), INT_MIN, 0),
|
||||||
"");
|
"");
|
||||||
|
|
||||||
in_out_mask = lp_build_int_const_scalar(i32_type, ~0);
|
in_out_mask = lp_build_const_int_vec(i32_type, ~0);
|
||||||
|
|
||||||
|
|
||||||
lp_build_flow_scope_declare(flow, &in_out_mask);
|
lp_build_flow_scope_declare(flow, &in_out_mask);
|
||||||
|
|
@ -367,7 +367,7 @@ build_int32_vec_const(int value)
|
||||||
i32_type.norm = FALSE; /* values are not normalized */
|
i32_type.norm = FALSE; /* values are not normalized */
|
||||||
i32_type.width = 32; /* 32-bit int values */
|
i32_type.width = 32; /* 32-bit int values */
|
||||||
i32_type.length = 4; /* 4 elements per vector */
|
i32_type.length = 4; /* 4 elements per vector */
|
||||||
return lp_build_int_const_scalar(i32_type, value);
|
return lp_build_const_int_vec(i32_type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
#include <llvm-c/Analysis.h>
|
#include <llvm-c/Analysis.h>
|
||||||
#include <llvm-c/ExecutionEngine.h>
|
#include <llvm-c/ExecutionEngine.h>
|
||||||
#include <llvm-c/Target.h>
|
#include <llvm-c/Target.h>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
#include <llvm-c/Analysis.h>
|
#include <llvm-c/Analysis.h>
|
||||||
#include <llvm-c/ExecutionEngine.h>
|
#include <llvm-c/ExecutionEngine.h>
|
||||||
#include <llvm-c/Target.h>
|
#include <llvm-c/Target.h>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
#define LP_TEX_SAMPLE_H
|
#define LP_TEX_SAMPLE_H
|
||||||
|
|
||||||
|
|
||||||
#include "os/os_llvm.h"
|
#include "gallivm/lp_bld.h"
|
||||||
|
|
||||||
|
|
||||||
struct lp_sampler_static_state;
|
struct lp_sampler_static_state;
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
|
||||||
unsigned height = align(lpt->base.height0, TILE_SIZE);
|
unsigned height = align(lpt->base.height0, TILE_SIZE);
|
||||||
|
|
||||||
lpt->dt = winsys->displaytarget_create(winsys,
|
lpt->dt = winsys->displaytarget_create(winsys,
|
||||||
|
lpt->base.tex_usage,
|
||||||
lpt->base.format,
|
lpt->base.format,
|
||||||
width, height,
|
width, height,
|
||||||
16,
|
16,
|
||||||
|
|
@ -250,6 +251,51 @@ llvmpipe_texture_unmap(struct pipe_texture *texture,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct pipe_texture *
|
||||||
|
llvmpipe_texture_from_handle(struct pipe_screen *screen,
|
||||||
|
const struct pipe_texture *template,
|
||||||
|
struct winsys_handle *whandle)
|
||||||
|
{
|
||||||
|
struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
|
||||||
|
struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture);
|
||||||
|
if (!lpt)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
lpt->base = *template;
|
||||||
|
pipe_reference_init(&lpt->base.reference, 1);
|
||||||
|
lpt->base.screen = screen;
|
||||||
|
|
||||||
|
lpt->dt = winsys->displaytarget_from_handle(winsys,
|
||||||
|
template,
|
||||||
|
whandle,
|
||||||
|
&lpt->stride[0]);
|
||||||
|
if (!lpt->dt)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return &lpt->base;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
FREE(lpt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
llvmpipe_texture_get_handle(struct pipe_screen *screen,
|
||||||
|
struct pipe_texture *pt,
|
||||||
|
struct winsys_handle *whandle)
|
||||||
|
{
|
||||||
|
struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
|
||||||
|
struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
|
||||||
|
|
||||||
|
assert(lpt->dt);
|
||||||
|
if (!lpt->dt)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return winsys->displaytarget_get_handle(winsys, lpt->dt, whandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct pipe_surface *
|
static struct pipe_surface *
|
||||||
llvmpipe_get_tex_surface(struct pipe_screen *screen,
|
llvmpipe_get_tex_surface(struct pipe_screen *screen,
|
||||||
struct pipe_texture *pt,
|
struct pipe_texture *pt,
|
||||||
|
|
@ -418,6 +464,7 @@ llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen)
|
||||||
{
|
{
|
||||||
screen->texture_create = llvmpipe_texture_create;
|
screen->texture_create = llvmpipe_texture_create;
|
||||||
screen->texture_destroy = llvmpipe_texture_destroy;
|
screen->texture_destroy = llvmpipe_texture_destroy;
|
||||||
|
screen->texture_get_handle = llvmpipe_texture_get_handle;
|
||||||
|
|
||||||
screen->get_tex_surface = llvmpipe_get_tex_surface;
|
screen->get_tex_surface = llvmpipe_get_tex_surface;
|
||||||
screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
|
screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
|
||||||
|
|
|
||||||
|
|
@ -173,8 +173,10 @@ softpipe_is_format_supported( struct pipe_screen *screen,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
|
if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
|
||||||
if(!winsys->is_displaytarget_format_supported(winsys, format))
|
PIPE_TEXTURE_USAGE_SCANOUT |
|
||||||
|
PIPE_TEXTURE_USAGE_SHARED)) {
|
||||||
|
if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ softpipe_displaytarget_layout(struct pipe_screen *screen,
|
||||||
/* Round up the surface size to a multiple of the tile size?
|
/* Round up the surface size to a multiple of the tile size?
|
||||||
*/
|
*/
|
||||||
spt->dt = winsys->displaytarget_create(winsys,
|
spt->dt = winsys->displaytarget_create(winsys,
|
||||||
|
spt->base.tex_usage,
|
||||||
spt->base.format,
|
spt->base.format,
|
||||||
spt->base.width0,
|
spt->base.width0,
|
||||||
spt->base.height0,
|
spt->base.height0,
|
||||||
|
|
@ -139,8 +140,6 @@ softpipe_texture_create(struct pipe_screen *screen,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
softpipe_texture_destroy(struct pipe_texture *pt)
|
softpipe_texture_destroy(struct pipe_texture *pt)
|
||||||
{
|
{
|
||||||
|
|
@ -161,6 +160,55 @@ softpipe_texture_destroy(struct pipe_texture *pt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct pipe_texture *
|
||||||
|
softpipe_texture_from_handle(struct pipe_screen *screen,
|
||||||
|
const struct pipe_texture *template,
|
||||||
|
struct winsys_handle *whandle)
|
||||||
|
{
|
||||||
|
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
|
||||||
|
struct softpipe_texture *spt = CALLOC_STRUCT(softpipe_texture);
|
||||||
|
if (!spt)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
spt->base = *template;
|
||||||
|
pipe_reference_init(&spt->base.reference, 1);
|
||||||
|
spt->base.screen = screen;
|
||||||
|
|
||||||
|
spt->pot = (util_is_power_of_two(template->width0) &&
|
||||||
|
util_is_power_of_two(template->height0) &&
|
||||||
|
util_is_power_of_two(template->depth0));
|
||||||
|
|
||||||
|
spt->dt = winsys->displaytarget_from_handle(winsys,
|
||||||
|
template,
|
||||||
|
whandle,
|
||||||
|
&spt->stride[0]);
|
||||||
|
if (!spt->dt)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return &spt->base;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
FREE(spt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
softpipe_texture_get_handle(struct pipe_screen *screen,
|
||||||
|
struct pipe_texture *pt,
|
||||||
|
struct winsys_handle *whandle)
|
||||||
|
{
|
||||||
|
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
|
||||||
|
struct softpipe_texture *spt = softpipe_texture(pt);
|
||||||
|
|
||||||
|
assert(spt->dt);
|
||||||
|
if (!spt->dt)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return winsys->displaytarget_get_handle(winsys, spt->dt, whandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a pipe_surface "view" into a texture.
|
* Get a pipe_surface "view" into a texture.
|
||||||
*/
|
*/
|
||||||
|
|
@ -461,6 +509,8 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
|
||||||
{
|
{
|
||||||
screen->texture_create = softpipe_texture_create;
|
screen->texture_create = softpipe_texture_create;
|
||||||
screen->texture_destroy = softpipe_texture_destroy;
|
screen->texture_destroy = softpipe_texture_destroy;
|
||||||
|
screen->texture_from_handle = softpipe_texture_from_handle;
|
||||||
|
screen->texture_get_handle = softpipe_texture_get_handle;
|
||||||
|
|
||||||
screen->get_tex_surface = softpipe_get_tex_surface;
|
screen->get_tex_surface = softpipe_get_tex_surface;
|
||||||
screen->tex_surface_destroy = softpipe_tex_surface_destroy;
|
screen->tex_surface_destroy = softpipe_tex_surface_destroy;
|
||||||
|
|
|
||||||
407
src/gallium/include/state_tracker/st_api.h
Normal file
407
src/gallium/include/state_tracker/st_api.h
Normal file
|
|
@ -0,0 +1,407 @@
|
||||||
|
/**********************************************************
|
||||||
|
* Copyright 2010 VMware, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _ST_API_H_
|
||||||
|
#define _ST_API_H_
|
||||||
|
|
||||||
|
#include "pipe/p_compiler.h"
|
||||||
|
#include "pipe/p_format.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file API for communication between state trackers and state tracker
|
||||||
|
* managers.
|
||||||
|
*
|
||||||
|
* While both are state tackers, we use the term state tracker for rendering
|
||||||
|
* APIs such as OpenGL or OpenVG, and state tracker manager for window system
|
||||||
|
* APIs such as EGL or GLX in this file.
|
||||||
|
*
|
||||||
|
* This file defines an API to be implemented by both state trackers and state
|
||||||
|
* tracker managers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entry points of the state trackers.
|
||||||
|
*/
|
||||||
|
#define ST_MODULE_OPENGL_SYMBOL "st_module_OpenGL"
|
||||||
|
#define ST_MODULE_OPENGL_ES1_SYMBOL "st_module_OpenGL_ES1"
|
||||||
|
#define ST_MODULE_OPENGL_ES2_SYMBOL "st_module_OpenGL_ES2"
|
||||||
|
#define ST_MODULE_OPENVG_SYMBOL "st_module_OpenVG"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The supported rendering API of a state tracker.
|
||||||
|
*/
|
||||||
|
enum st_api_type {
|
||||||
|
ST_API_OPENGL,
|
||||||
|
ST_API_OPENGL_ES1,
|
||||||
|
ST_API_OPENGL_ES2,
|
||||||
|
ST_API_OPENVG,
|
||||||
|
|
||||||
|
ST_API_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in st_context_iface->teximage.
|
||||||
|
*/
|
||||||
|
enum st_texture_type {
|
||||||
|
ST_TEXTURE_1D,
|
||||||
|
ST_TEXTURE_2D,
|
||||||
|
ST_TEXTURE_3D,
|
||||||
|
ST_TEXTURE_RECT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available attachments of framebuffer.
|
||||||
|
*/
|
||||||
|
enum st_attachment_type {
|
||||||
|
ST_ATTACHMENT_FRONT_LEFT,
|
||||||
|
ST_ATTACHMENT_BACK_LEFT,
|
||||||
|
ST_ATTACHMENT_FRONT_RIGHT,
|
||||||
|
ST_ATTACHMENT_BACK_RIGHT,
|
||||||
|
ST_ATTACHMENT_DEPTH_STENCIL,
|
||||||
|
ST_ATTACHMENT_ACCUM,
|
||||||
|
ST_ATTACHMENT_SAMPLE,
|
||||||
|
|
||||||
|
ST_ATTACHMENT_COUNT,
|
||||||
|
ST_ATTACHMENT_INVALID = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for buffer_mask in st_visual */
|
||||||
|
#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT)
|
||||||
|
#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT)
|
||||||
|
#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT)
|
||||||
|
#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT)
|
||||||
|
#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL)
|
||||||
|
#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM)
|
||||||
|
#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerations of state tracker context resources.
|
||||||
|
*/
|
||||||
|
enum st_context_resource_type {
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER,
|
||||||
|
ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The return type of st_api->get_proc_address.
|
||||||
|
*/
|
||||||
|
typedef void (*st_proc_t)(void);
|
||||||
|
|
||||||
|
struct pipe_context;
|
||||||
|
struct pipe_texture;
|
||||||
|
struct pipe_fence_handle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in st_context_iface->get_resource_for_egl_image.
|
||||||
|
*/
|
||||||
|
struct st_context_resource
|
||||||
|
{
|
||||||
|
/* these fields are filled by the caller */
|
||||||
|
enum st_context_resource_type type;
|
||||||
|
void *resource;
|
||||||
|
|
||||||
|
/* this is owned by the caller */
|
||||||
|
struct pipe_texture *texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in st_manager_iface->get_egl_image.
|
||||||
|
*/
|
||||||
|
struct st_egl_image
|
||||||
|
{
|
||||||
|
/* these fields are filled by the caller */
|
||||||
|
struct st_context_iface *stctxi;
|
||||||
|
void *egl_image;
|
||||||
|
|
||||||
|
/* this is owned by the caller */
|
||||||
|
struct pipe_texture *texture;
|
||||||
|
|
||||||
|
unsigned face;
|
||||||
|
unsigned level;
|
||||||
|
unsigned zslice;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent the visual of a framebuffer.
|
||||||
|
*/
|
||||||
|
struct st_visual
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Available buffers. Tested with ST_FRAMEBUFFER_*_MASK.
|
||||||
|
*/
|
||||||
|
unsigned buffer_mask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer formats. The formats are always set even when the buffer is
|
||||||
|
* not available.
|
||||||
|
*/
|
||||||
|
enum pipe_format color_format;
|
||||||
|
enum pipe_format depth_stencil_format;
|
||||||
|
enum pipe_format accum_format;
|
||||||
|
int samples;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Desired render buffer.
|
||||||
|
*/
|
||||||
|
enum st_attachment_type render_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a windowing system drawable.
|
||||||
|
*
|
||||||
|
* The framebuffer is implemented by the state tracker manager and
|
||||||
|
* used by the state trackers.
|
||||||
|
*
|
||||||
|
* Instead of the winsys pokeing into the API context to figure
|
||||||
|
* out what buffers that might be needed in the future by the API
|
||||||
|
* context, it calls into the framebuffer to get the textures.
|
||||||
|
*
|
||||||
|
* This structure along with the notify_invalid_framebuffer
|
||||||
|
* allows framebuffers to be shared between different threads
|
||||||
|
* but at the same make the API context free from thread
|
||||||
|
* syncronisation primitves, with the exception of a small
|
||||||
|
* atomic flag used for notification of framebuffer dirty status.
|
||||||
|
*
|
||||||
|
* The thread syncronisation is put inside the framebuffer
|
||||||
|
* and only called once the framebuffer has become dirty.
|
||||||
|
*/
|
||||||
|
struct st_framebuffer_iface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Available for the state tracker manager to use.
|
||||||
|
*/
|
||||||
|
void *st_manager_private;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The visual of a framebuffer.
|
||||||
|
*/
|
||||||
|
const struct st_visual *visual;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush the front buffer.
|
||||||
|
*
|
||||||
|
* On some window systems, changes to the front buffers are not immediately
|
||||||
|
* visible. They need to be flushed.
|
||||||
|
*
|
||||||
|
* @att is one of the front buffer attachments.
|
||||||
|
*/
|
||||||
|
boolean (*flush_front)(struct st_framebuffer_iface *stfbi,
|
||||||
|
enum st_attachment_type statt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The state tracker asks for the textures it needs.
|
||||||
|
*
|
||||||
|
* It should try to only ask for attachments that it currently renders
|
||||||
|
* to, thus allowing the winsys to delay the allocation of textures not
|
||||||
|
* needed. For example front buffer attachments are not needed if you
|
||||||
|
* only do back buffer rendering.
|
||||||
|
*
|
||||||
|
* The implementor of this function needs to also ensure
|
||||||
|
* thread safty as this call might be done from multiple threads.
|
||||||
|
*
|
||||||
|
* The returned textures are owned by the caller. They should be
|
||||||
|
* unreferenced when no longer used. If this function is called multiple
|
||||||
|
* times with different sets of attachments, those buffers not included in
|
||||||
|
* the last call might be destroyed. This behavior might change in the
|
||||||
|
* future.
|
||||||
|
*/
|
||||||
|
boolean (*validate)(struct st_framebuffer_iface *stfbi,
|
||||||
|
const enum st_attachment_type *statts,
|
||||||
|
unsigned count,
|
||||||
|
struct pipe_texture **out);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a rendering context.
|
||||||
|
*
|
||||||
|
* This entity is created from st_api and used by the state tracker manager.
|
||||||
|
*/
|
||||||
|
struct st_context_iface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Available for the state tracker and the manager to use.
|
||||||
|
*/
|
||||||
|
void *st_context_private;
|
||||||
|
void *st_manager_private;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the context.
|
||||||
|
*/
|
||||||
|
void (*destroy)(struct st_context_iface *stctxi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate the current textures that was taken from a framebuffer.
|
||||||
|
*
|
||||||
|
* The state tracker manager calls this function to let the rendering
|
||||||
|
* context know that it should update the textures it got from
|
||||||
|
* st_framebuffer_iface::validate. It should do so at the latest time possible.
|
||||||
|
* Possible right before sending triangles to the pipe context.
|
||||||
|
*
|
||||||
|
* For certain platforms this function might be called from a thread other
|
||||||
|
* than the thread that the context is currently bound in, and must
|
||||||
|
* therefore be thread safe. But it is the state tracker manager's
|
||||||
|
* responsibility to make sure that the framebuffer is bound to the context
|
||||||
|
* and the API context is current for the duration of this call.
|
||||||
|
*
|
||||||
|
* Thus reducing the sync primitive needed to a single atomic flag.
|
||||||
|
*/
|
||||||
|
void (*notify_invalid_framebuffer)(struct st_context_iface *stctxi,
|
||||||
|
struct st_framebuffer_iface *stfbi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush all drawing from context to the pipe also flushes the pipe.
|
||||||
|
*/
|
||||||
|
void (*flush)(struct st_context_iface *stctxi, unsigned flags,
|
||||||
|
struct pipe_fence_handle **fence);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the texture image of a texture object at the specified level.
|
||||||
|
*
|
||||||
|
* This function is optional.
|
||||||
|
*/
|
||||||
|
boolean (*teximage)(struct st_context_iface *stctxi, enum st_texture_type target,
|
||||||
|
int level, enum pipe_format internal_format,
|
||||||
|
struct pipe_texture *tex, boolean mipmap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to implement glXCopyContext.
|
||||||
|
*/
|
||||||
|
void (*copy)(struct st_context_iface *stctxi,
|
||||||
|
struct st_context_iface *stsrci, unsigned mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up and return the info of a resource for EGLImage.
|
||||||
|
*
|
||||||
|
* This function is optional.
|
||||||
|
*/
|
||||||
|
boolean (*get_resource_for_egl_image)(struct st_context_iface *stctxi,
|
||||||
|
struct st_context_resource *stres);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a state tracker manager.
|
||||||
|
*
|
||||||
|
* This interface is implemented by the state tracker manager. It corresponds
|
||||||
|
* to a "display" in the window system.
|
||||||
|
*/
|
||||||
|
struct st_manager
|
||||||
|
{
|
||||||
|
struct pipe_screen *screen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up and return the info of an EGLImage.
|
||||||
|
*
|
||||||
|
* This function is optional.
|
||||||
|
*/
|
||||||
|
boolean (*get_egl_image)(struct st_manager *smapi,
|
||||||
|
struct st_egl_image *stimg);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a rendering API such as OpenGL or OpenVG.
|
||||||
|
*
|
||||||
|
* Implemented by the state tracker and used by the state tracker manager.
|
||||||
|
*/
|
||||||
|
struct st_api
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Destroy the API.
|
||||||
|
*/
|
||||||
|
void (*destroy)(struct st_api *stapi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an API entry point.
|
||||||
|
*
|
||||||
|
* For GL this is the same as _glapi_get_proc_address.
|
||||||
|
*/
|
||||||
|
st_proc_t (*get_proc_address)(struct st_api *stapi, const char *procname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the visual is supported by the state tracker.
|
||||||
|
*/
|
||||||
|
boolean (*is_visual_supported)(struct st_api *stapi,
|
||||||
|
const struct st_visual *visual);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a rendering context.
|
||||||
|
*/
|
||||||
|
struct st_context_iface *(*create_context)(struct st_api *stapi,
|
||||||
|
struct st_manager *smapi,
|
||||||
|
const struct st_visual *visual,
|
||||||
|
struct st_context_iface *stsharei);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind the context to the calling thread with draw and read as drawables.
|
||||||
|
*
|
||||||
|
* The framebuffers might have different visuals than the context does.
|
||||||
|
*/
|
||||||
|
boolean (*make_current)(struct st_api *stapi,
|
||||||
|
struct st_context_iface *stctxi,
|
||||||
|
struct st_framebuffer_iface *stdrawi,
|
||||||
|
struct st_framebuffer_iface *streadi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently bound context in the calling thread.
|
||||||
|
*/
|
||||||
|
struct st_context_iface *(*get_current)(struct st_api *stapi);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a state tracker.
|
||||||
|
*
|
||||||
|
* This is the entry point of a state tracker.
|
||||||
|
*/
|
||||||
|
struct st_module
|
||||||
|
{
|
||||||
|
enum st_api_type api;
|
||||||
|
struct st_api *(*create_api)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the visual has the specified buffers.
|
||||||
|
*/
|
||||||
|
static INLINE boolean
|
||||||
|
st_visual_have_buffers(const struct st_visual *visual, unsigned mask)
|
||||||
|
{
|
||||||
|
return ((visual->buffer_mask & mask) == mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* these symbols may need to be dynamically lookup up */
|
||||||
|
extern PUBLIC const struct st_module st_module_OpenGL;
|
||||||
|
extern PUBLIC const struct st_module st_module_OpenGL_ES1;
|
||||||
|
extern PUBLIC const struct st_module st_module_OpenGL_ES2;
|
||||||
|
extern PUBLIC const struct st_module st_module_OpenVG;
|
||||||
|
|
||||||
|
#endif /* _ST_API_H_ */
|
||||||
|
|
@ -44,6 +44,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct winsys_handle;
|
||||||
struct pipe_screen;
|
struct pipe_screen;
|
||||||
struct pipe_context;
|
struct pipe_context;
|
||||||
|
|
||||||
|
|
@ -68,6 +69,7 @@ struct sw_winsys
|
||||||
|
|
||||||
boolean
|
boolean
|
||||||
(*is_displaytarget_format_supported)( struct sw_winsys *ws,
|
(*is_displaytarget_format_supported)( struct sw_winsys *ws,
|
||||||
|
unsigned tex_usage,
|
||||||
enum pipe_format format );
|
enum pipe_format format );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -83,11 +85,29 @@ struct sw_winsys
|
||||||
*/
|
*/
|
||||||
struct sw_displaytarget *
|
struct sw_displaytarget *
|
||||||
(*displaytarget_create)( struct sw_winsys *ws,
|
(*displaytarget_create)( struct sw_winsys *ws,
|
||||||
|
unsigned tex_usage,
|
||||||
enum pipe_format format,
|
enum pipe_format format,
|
||||||
unsigned width, unsigned height,
|
unsigned width, unsigned height,
|
||||||
unsigned alignment,
|
unsigned alignment,
|
||||||
unsigned *stride );
|
unsigned *stride );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to implement texture_from_handle.
|
||||||
|
*/
|
||||||
|
struct sw_displaytarget *
|
||||||
|
(*displaytarget_from_handle)( struct sw_winsys *ws,
|
||||||
|
const struct pipe_texture *templat,
|
||||||
|
struct winsys_handle *whandle,
|
||||||
|
unsigned *stride );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to implement texture_get_handle.
|
||||||
|
*/
|
||||||
|
boolean
|
||||||
|
(*displaytarget_get_handle)( struct sw_winsys *ws,
|
||||||
|
struct sw_displaytarget *dt,
|
||||||
|
struct winsys_handle *whandle );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param flags bitmask of PIPE_BUFFER_USAGE_x flags
|
* \param flags bitmask of PIPE_BUFFER_USAGE_x flags
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@
|
||||||
#include "state_tracker/drm_api.h"
|
#include "state_tracker/drm_api.h"
|
||||||
#include "state_tracker/dri1_api.h"
|
#include "state_tracker/dri1_api.h"
|
||||||
#include "state_tracker/st_public.h"
|
#include "state_tracker/st_public.h"
|
||||||
#include "state_tracker/st_context.h"
|
|
||||||
#include "pipe/p_context.h"
|
#include "pipe/p_context.h"
|
||||||
|
|
||||||
#include "dri_context.h"
|
#include "dri_context.h"
|
||||||
|
|
@ -167,7 +166,7 @@ dri_make_current(__DRIcontext * cPriv,
|
||||||
* flush_frontbuffer directly (in front-buffer rendering), it
|
* flush_frontbuffer directly (in front-buffer rendering), it
|
||||||
* will have access to the drawable argument:
|
* will have access to the drawable argument:
|
||||||
*/
|
*/
|
||||||
st_make_current(ctx->st, draw->stfb, read->stfb, NULL);
|
st_make_current(ctx->st, draw->stfb, read->stfb, ctx);
|
||||||
|
|
||||||
if (__dri1_api_hooks) {
|
if (__dri1_api_hooks) {
|
||||||
dri1_update_drawables(ctx, draw, read);
|
dri1_update_drawables(ctx, draw, read);
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@
|
||||||
#include "main/renderbuffer.h"
|
#include "main/renderbuffer.h"
|
||||||
#include "state_tracker/drm_api.h"
|
#include "state_tracker/drm_api.h"
|
||||||
#include "state_tracker/dri1_api.h"
|
#include "state_tracker/dri1_api.h"
|
||||||
#include "state_tracker/st_public.h"
|
|
||||||
#include "state_tracker/st_context.h"
|
#include "state_tracker/st_context.h"
|
||||||
|
#include "state_tracker/st_public.h"
|
||||||
#include "state_tracker/st_cb_fbo.h"
|
#include "state_tracker/st_cb_fbo.h"
|
||||||
|
|
||||||
#include "util/u_format.h"
|
#include "util/u_format.h"
|
||||||
|
|
|
||||||
|
|
@ -36,234 +36,27 @@
|
||||||
|
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
#include "egl_g3d.h"
|
#include "egl_g3d.h"
|
||||||
|
#include "egl_g3d_st.h"
|
||||||
#include "egl_g3d_image.h"
|
#include "egl_g3d_image.h"
|
||||||
#include "egl_st.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the draw/read surfaces of the context.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|
||||||
{
|
|
||||||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
|
||||||
struct pipe_screen *screen = gdpy->native->screen;
|
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
|
||||||
const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
|
|
||||||
ST_SURFACE_FRONT_LEFT,
|
|
||||||
ST_SURFACE_BACK_LEFT,
|
|
||||||
ST_SURFACE_FRONT_RIGHT,
|
|
||||||
ST_SURFACE_BACK_RIGHT,
|
|
||||||
};
|
|
||||||
EGLint num_surfaces, s;
|
|
||||||
|
|
||||||
/* validate draw and/or read buffers */
|
|
||||||
num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
|
|
||||||
for (s = 0; s < num_surfaces; s++) {
|
|
||||||
struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
|
|
||||||
struct egl_g3d_surface *gsurf;
|
|
||||||
struct egl_g3d_buffer *gbuf;
|
|
||||||
EGLint att;
|
|
||||||
|
|
||||||
if (s == 0) {
|
|
||||||
gsurf = egl_g3d_surface(gctx->base.DrawSurface);
|
|
||||||
gbuf = &gctx->draw;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gsurf = egl_g3d_surface(gctx->base.ReadSurface);
|
|
||||||
gbuf = &gctx->read;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gctx->force_validate) {
|
|
||||||
unsigned int seq_num;
|
|
||||||
|
|
||||||
gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
|
|
||||||
&seq_num, NULL, NULL, NULL);
|
|
||||||
/* skip validation */
|
|
||||||
if (gsurf->sequence_number == seq_num)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pipe_surface_reference(&gsurf->render_surface, NULL);
|
|
||||||
memset(textures, 0, sizeof(textures));
|
|
||||||
|
|
||||||
gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
|
|
||||||
&gsurf->sequence_number, textures,
|
|
||||||
&gsurf->base.Width, &gsurf->base.Height);
|
|
||||||
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
|
|
||||||
struct pipe_texture *pt = textures[att];
|
|
||||||
struct pipe_surface *ps;
|
|
||||||
|
|
||||||
if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) {
|
|
||||||
ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
|
|
||||||
PIPE_BUFFER_USAGE_GPU_READ |
|
|
||||||
PIPE_BUFFER_USAGE_GPU_WRITE);
|
|
||||||
gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
|
|
||||||
st_att_map[att], ps);
|
|
||||||
|
|
||||||
if (gsurf->render_att == att)
|
|
||||||
pipe_surface_reference(&gsurf->render_surface, ps);
|
|
||||||
|
|
||||||
pipe_surface_reference(&ps, NULL);
|
|
||||||
pipe_texture_reference(&pt, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gctx->stapi->st_resize_framebuffer(gbuf->st_fb,
|
|
||||||
gsurf->base.Width, gsurf->base.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
gctx->force_validate = EGL_FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a st_framebuffer.
|
|
||||||
*/
|
|
||||||
static struct st_framebuffer *
|
|
||||||
create_framebuffer(_EGLContext *ctx, _EGLSurface *surf)
|
|
||||||
{
|
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
|
||||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
|
||||||
struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
|
|
||||||
|
|
||||||
return gctx->stapi->st_create_framebuffer(&gconf->native->mode,
|
|
||||||
gconf->native->color_format, gconf->native->depth_format,
|
|
||||||
gconf->native->stencil_format,
|
|
||||||
gsurf->base.Width, gsurf->base.Height, &gsurf->base);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the attachments of draw/read surfaces.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|
||||||
{
|
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
|
||||||
EGLint s;
|
|
||||||
|
|
||||||
/* route draw and read buffers' attachments */
|
|
||||||
for (s = 0; s < 2; s++) {
|
|
||||||
struct egl_g3d_surface *gsurf;
|
|
||||||
struct egl_g3d_buffer *gbuf;
|
|
||||||
|
|
||||||
if (s == 0) {
|
|
||||||
gsurf = egl_g3d_surface(gctx->base.DrawSurface);
|
|
||||||
gbuf = &gctx->draw;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gsurf = egl_g3d_surface(gctx->base.ReadSurface);
|
|
||||||
gbuf = &gctx->read;
|
|
||||||
}
|
|
||||||
|
|
||||||
gbuf->attachment_mask = (1 << gsurf->render_att);
|
|
||||||
|
|
||||||
/* FIXME OpenGL defaults to draw the front or back buffer when the
|
|
||||||
* context is single-buffered or double-buffered respectively. In EGL,
|
|
||||||
* however, the buffer to be drawn is determined by the surface, instead
|
|
||||||
* of the context. As a result, rendering to a pixmap surface with a
|
|
||||||
* double-buffered context does not work as expected.
|
|
||||||
*
|
|
||||||
* gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
|
|
||||||
* NATIVE_ATTACHMENT_FRONT_LEFT);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME If the back buffer is asked for here, and the front buffer is
|
|
||||||
* later needed by the client API (e.g. glDrawBuffer is called to draw
|
|
||||||
* the front buffer), it will create a new pipe texture and draw there.
|
|
||||||
* One fix is to ask for both buffers here, but it would be a waste if
|
|
||||||
* the front buffer is never used. A better fix is to add a callback to
|
|
||||||
* the pipe screen with context private (just like flush_frontbuffer).
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reallocate the context's framebuffers after draw/read surfaces change.
|
|
||||||
*/
|
|
||||||
static EGLBoolean
|
|
||||||
egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|
||||||
{
|
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
|
||||||
struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface);
|
|
||||||
struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface);
|
|
||||||
|
|
||||||
/* unreference the old framebuffers */
|
|
||||||
if (gctx->draw.st_fb) {
|
|
||||||
EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb);
|
|
||||||
void *priv;
|
|
||||||
|
|
||||||
priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb);
|
|
||||||
if (!gdraw || priv != (void *) &gdraw->base) {
|
|
||||||
gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
|
|
||||||
gctx->draw.st_fb = NULL;
|
|
||||||
gctx->draw.attachment_mask = 0x0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_equal) {
|
|
||||||
gctx->read.st_fb = NULL;
|
|
||||||
gctx->draw.attachment_mask = 0x0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
|
|
||||||
if (!gread || priv != (void *) &gread->base) {
|
|
||||||
gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
|
|
||||||
gctx->read.st_fb = NULL;
|
|
||||||
gctx->draw.attachment_mask = 0x0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gdraw)
|
|
||||||
return EGL_TRUE;
|
|
||||||
|
|
||||||
/* create the draw fb */
|
|
||||||
if (!gctx->draw.st_fb) {
|
|
||||||
gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base);
|
|
||||||
if (!gctx->draw.st_fb)
|
|
||||||
return EGL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the read fb */
|
|
||||||
if (!gctx->read.st_fb) {
|
|
||||||
if (gread != gdraw) {
|
|
||||||
gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base);
|
|
||||||
if (!gctx->read.st_fb) {
|
|
||||||
gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
|
|
||||||
gctx->draw.st_fb = NULL;
|
|
||||||
return EGL_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* there is no st_reference_framebuffer... */
|
|
||||||
gctx->read.st_fb = gctx->draw.st_fb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
egl_g3d_route_context(dpy, &gctx->base);
|
|
||||||
gctx->force_validate = EGL_TRUE;
|
|
||||||
|
|
||||||
return EGL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the state tracker for the given context.
|
* Return the state tracker for the given context.
|
||||||
*/
|
*/
|
||||||
static const struct egl_g3d_st *
|
static struct st_api *
|
||||||
egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
|
egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
|
||||||
{
|
{
|
||||||
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
||||||
const struct egl_g3d_st *stapi;
|
struct st_api *stapi;
|
||||||
EGLint idx = -1;
|
EGLint idx = -1;
|
||||||
|
|
||||||
switch (ctx->ClientAPI) {
|
switch (ctx->ClientAPI) {
|
||||||
case EGL_OPENGL_ES_API:
|
case EGL_OPENGL_ES_API:
|
||||||
switch (ctx->ClientVersion) {
|
switch (ctx->ClientVersion) {
|
||||||
case 1:
|
case 1:
|
||||||
idx = EGL_G3D_ST_OPENGL_ES;
|
idx = ST_API_OPENGL_ES1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
idx = EGL_G3D_ST_OPENGL_ES2;
|
idx = ST_API_OPENGL_ES2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_eglLog(_EGL_WARNING, "unknown client version %d",
|
_eglLog(_EGL_WARNING, "unknown client version %d",
|
||||||
|
|
@ -272,10 +65,10 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EGL_OPENVG_API:
|
case EGL_OPENVG_API:
|
||||||
idx = EGL_G3D_ST_OPENVG;
|
idx = ST_API_OPENVG;
|
||||||
break;
|
break;
|
||||||
case EGL_OPENGL_API:
|
case EGL_OPENGL_API:
|
||||||
idx = EGL_G3D_ST_OPENGL;
|
idx = ST_API_OPENGL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
|
_eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
|
||||||
|
|
@ -299,10 +92,10 @@ egl_g3d_init_st(_EGLDriver *drv)
|
||||||
if (gdrv->api_mask)
|
if (gdrv->api_mask)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < NUM_EGL_G3D_STS; i++) {
|
for (i = 0; i < ST_API_COUNT; i++) {
|
||||||
gdrv->stapis[i] = egl_g3d_get_st(i);
|
gdrv->stapis[i] = egl_g3d_create_st_api(i);
|
||||||
if (gdrv->stapis[i])
|
if (gdrv->stapis[i])
|
||||||
gdrv->api_mask |= gdrv->stapis[i]->api_bit;
|
gdrv->api_mask |= egl_g3d_st_api_bit(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gdrv->api_mask)
|
if (gdrv->api_mask)
|
||||||
|
|
@ -351,35 +144,6 @@ egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an API mask that consists of the state trackers that supports the
|
|
||||||
* given mode.
|
|
||||||
*
|
|
||||||
* FIXME add st_is_mode_supported()?
|
|
||||||
*/
|
|
||||||
static EGLint
|
|
||||||
get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask)
|
|
||||||
{
|
|
||||||
EGLint check;
|
|
||||||
|
|
||||||
/* OpenGL ES 1.x and 2.x are checked together */
|
|
||||||
check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
|
|
||||||
if (api_mask & check) {
|
|
||||||
/* this is required by EGL, not by OpenGL ES */
|
|
||||||
if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode)
|
|
||||||
api_mask &= ~check;
|
|
||||||
}
|
|
||||||
|
|
||||||
check = EGL_OPENVG_BIT;
|
|
||||||
if (api_mask & check) {
|
|
||||||
/* vega st needs the depth/stencil rb */
|
|
||||||
if (!mode->depthBits && !mode->stencilBits)
|
|
||||||
api_mask &= ~check;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef EGL_MESA_screen_surface
|
#ifdef EGL_MESA_screen_surface
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -443,19 +207,89 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||||
|
|
||||||
#endif /* EGL_MESA_screen_surface */
|
#endif /* EGL_MESA_screen_surface */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize an EGL config from the native config.
|
||||||
|
*/
|
||||||
|
static EGLBoolean
|
||||||
|
egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
|
_EGLConfig *conf, const struct native_config *nconf)
|
||||||
|
{
|
||||||
|
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
||||||
|
struct egl_g3d_config *gconf = egl_g3d_config(conf);
|
||||||
|
const __GLcontextModes *mode = &nconf->mode;
|
||||||
|
EGLint buffer_mask, api_mask;
|
||||||
|
EGLBoolean valid;
|
||||||
|
EGLint i;
|
||||||
|
|
||||||
|
buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
|
||||||
|
if (mode->doubleBufferMode)
|
||||||
|
buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
|
||||||
|
if (mode->stereoMode) {
|
||||||
|
buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
|
||||||
|
if (mode->doubleBufferMode)
|
||||||
|
buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
gconf->stvis.buffer_mask = buffer_mask;
|
||||||
|
gconf->stvis.color_format = nconf->color_format;
|
||||||
|
gconf->stvis.depth_stencil_format = nconf->depth_format;
|
||||||
|
gconf->stvis.accum_format = PIPE_FORMAT_NONE;
|
||||||
|
gconf->stvis.samples = 0;
|
||||||
|
|
||||||
|
gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT) ?
|
||||||
|
ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
|
||||||
|
|
||||||
|
api_mask = 0;
|
||||||
|
for (i = 0; i < ST_API_COUNT; i++) {
|
||||||
|
struct st_api *stapi = gdrv->stapis[i];
|
||||||
|
if (stapi) {
|
||||||
|
if (stapi->is_visual_supported(stapi, &gconf->stvis))
|
||||||
|
api_mask |= egl_g3d_st_api_bit(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* this is required by EGL, not by OpenGL ES */
|
||||||
|
if ((mode->drawableType & GLX_WINDOW_BIT) && !mode->doubleBufferMode)
|
||||||
|
api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
|
||||||
|
|
||||||
|
if (!api_mask) {
|
||||||
|
_eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
|
||||||
|
mode->visualID);
|
||||||
|
}
|
||||||
|
|
||||||
|
valid = _eglConfigFromContextModesRec(&gconf->base,
|
||||||
|
mode, api_mask, api_mask);
|
||||||
|
if (valid) {
|
||||||
|
#ifdef EGL_MESA_screen_surface
|
||||||
|
/* check if scanout surface bit is set */
|
||||||
|
if (nconf->scanout_bit) {
|
||||||
|
EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE);
|
||||||
|
val |= EGL_SCREEN_BIT_MESA;
|
||||||
|
SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
|
||||||
|
}
|
||||||
|
if (!valid) {
|
||||||
|
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x", mode->visualID);
|
||||||
|
return EGL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gconf->native = nconf;
|
||||||
|
|
||||||
|
return EGL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add configs to display and return the next config ID.
|
* Add configs to display and return the next config ID.
|
||||||
*/
|
*/
|
||||||
static EGLint
|
static EGLint
|
||||||
egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
|
egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
|
||||||
{
|
{
|
||||||
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
|
||||||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||||
const struct native_config **native_configs;
|
const struct native_config **native_configs;
|
||||||
int num_configs, i;
|
int num_configs, i;
|
||||||
|
|
||||||
native_configs = gdpy->native->get_configs(gdpy->native,
|
native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
|
||||||
&num_configs);
|
|
||||||
if (!num_configs) {
|
if (!num_configs) {
|
||||||
if (native_configs)
|
if (native_configs)
|
||||||
free(native_configs);
|
free(native_configs);
|
||||||
|
|
@ -463,61 +297,25 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_configs; i++) {
|
for (i = 0; i < num_configs; i++) {
|
||||||
EGLint api_mask;
|
|
||||||
struct egl_g3d_config *gconf;
|
struct egl_g3d_config *gconf;
|
||||||
EGLBoolean valid;
|
|
||||||
|
|
||||||
gconf = CALLOC_STRUCT(egl_g3d_config);
|
gconf = CALLOC_STRUCT(egl_g3d_config);
|
||||||
if (!gconf)
|
if (gconf) {
|
||||||
continue;
|
_eglInitConfig(&gconf->base, dpy, id);
|
||||||
|
if (!egl_g3d_init_config(drv, dpy, &gconf->base, native_configs[i])) {
|
||||||
_eglInitConfig(&gconf->base, dpy, id);
|
free(gconf);
|
||||||
|
continue;
|
||||||
api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask);
|
|
||||||
if (!api_mask) {
|
|
||||||
_eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
|
|
||||||
native_configs[i]->mode.visualID);
|
|
||||||
}
|
|
||||||
|
|
||||||
valid = _eglConfigFromContextModesRec(&gconf->base,
|
|
||||||
&native_configs[i]->mode, api_mask, api_mask);
|
|
||||||
if (valid) {
|
|
||||||
#ifdef EGL_MESA_screen_surface
|
|
||||||
/* check if scanout surface bit is set */
|
|
||||||
if (native_configs[i]->scanout_bit) {
|
|
||||||
EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE);
|
|
||||||
val |= EGL_SCREEN_BIT_MESA;
|
|
||||||
SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
|
|
||||||
}
|
|
||||||
if (!valid) {
|
|
||||||
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x",
|
|
||||||
native_configs[i]->mode.visualID);
|
|
||||||
free(gconf);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
gconf->native = native_configs[i];
|
_eglAddConfig(dpy, &gconf->base);
|
||||||
_eglAddConfig(dpy, &gconf->base);
|
id++;
|
||||||
id++;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(native_configs);
|
free(native_configs);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-validate the context.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
|
|
||||||
{
|
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(context_private);
|
|
||||||
egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
egl_g3d_invalid_surface(struct native_display *ndpy,
|
egl_g3d_invalid_surface(struct native_display *ndpy,
|
||||||
struct native_surface *nsurf,
|
struct native_surface *nsurf,
|
||||||
|
|
@ -525,11 +323,15 @@ egl_g3d_invalid_surface(struct native_display *ndpy,
|
||||||
{
|
{
|
||||||
/* XXX not thread safe? */
|
/* XXX not thread safe? */
|
||||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
|
struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(gsurf->base.CurrentContext);
|
struct egl_g3d_context *gctx;
|
||||||
|
|
||||||
/* set force_validate to skip an unnecessary check */
|
/*
|
||||||
|
* Some functions such as egl_g3d_copy_buffers create a temporary native
|
||||||
|
* surface. There is no gsurf associated with it.
|
||||||
|
*/
|
||||||
|
gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
|
||||||
if (gctx)
|
if (gctx)
|
||||||
gctx->force_validate = TRUE;
|
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct native_event_handler egl_g3d_native_event_handler = {
|
static struct native_event_handler egl_g3d_native_event_handler = {
|
||||||
|
|
@ -545,6 +347,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||||
_eglReleaseDisplayResources(drv, dpy);
|
_eglReleaseDisplayResources(drv, dpy);
|
||||||
_eglCleanupDisplay(dpy);
|
_eglCleanupDisplay(dpy);
|
||||||
|
|
||||||
|
if (gdpy->pipe)
|
||||||
|
gdpy->pipe->destroy(gdpy->pipe);
|
||||||
|
|
||||||
if (dpy->Screens) {
|
if (dpy->Screens) {
|
||||||
for (i = 0; i < dpy->NumScreens; i++) {
|
for (i = 0; i < dpy->NumScreens; i++) {
|
||||||
struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
|
struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
|
||||||
|
|
@ -554,6 +359,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||||
free(dpy->Screens);
|
free(dpy->Screens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gdpy->smapi)
|
||||||
|
egl_g3d_destroy_st_manager(gdpy->smapi);
|
||||||
|
|
||||||
if (gdpy->native)
|
if (gdpy->native)
|
||||||
gdpy->native->destroy(gdpy->native);
|
gdpy->native->destroy(gdpy->native);
|
||||||
|
|
||||||
|
|
@ -588,11 +396,17 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
}
|
}
|
||||||
|
|
||||||
gdpy->native->user_data = (void *) dpy;
|
gdpy->native->user_data = (void *) dpy;
|
||||||
gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
|
|
||||||
|
|
||||||
egl_g3d_init_st(&gdrv->base);
|
egl_g3d_init_st(&gdrv->base);
|
||||||
dpy->ClientAPIsMask = gdrv->api_mask;
|
dpy->ClientAPIsMask = gdrv->api_mask;
|
||||||
|
|
||||||
|
gdpy->smapi = egl_g3d_create_st_manager(dpy);
|
||||||
|
if (!gdpy->smapi) {
|
||||||
|
_eglError(EGL_NOT_INITIALIZED,
|
||||||
|
"eglInitialize(failed to create st manager)");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef EGL_MESA_screen_surface
|
#ifdef EGL_MESA_screen_surface
|
||||||
/* enable MESA_screen_surface before adding (and validating) configs */
|
/* enable MESA_screen_surface before adding (and validating) configs */
|
||||||
if (gdpy->native->modeset) {
|
if (gdpy->native->modeset) {
|
||||||
|
|
@ -629,7 +443,6 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
|
||||||
struct egl_g3d_context *gshare = egl_g3d_context(share);
|
struct egl_g3d_context *gshare = egl_g3d_context(share);
|
||||||
struct egl_g3d_config *gconf = egl_g3d_config(conf);
|
struct egl_g3d_config *gconf = egl_g3d_config(conf);
|
||||||
struct egl_g3d_context *gctx;
|
struct egl_g3d_context *gctx;
|
||||||
const __GLcontextModes *mode;
|
|
||||||
|
|
||||||
gctx = CALLOC_STRUCT(egl_g3d_context);
|
gctx = CALLOC_STRUCT(egl_g3d_context);
|
||||||
if (!gctx) {
|
if (!gctx) {
|
||||||
|
|
@ -648,24 +461,14 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = &gconf->native->mode;
|
gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi,
|
||||||
|
&gconf->stvis, (gshare) ? gshare->stctxi : NULL);
|
||||||
gctx->pipe = gdpy->native->screen->context_create(
|
if (!gctx->stctxi) {
|
||||||
gdpy->native->screen,
|
|
||||||
(void *) &gctx->base);
|
|
||||||
|
|
||||||
if (!gctx->pipe) {
|
|
||||||
free(gctx);
|
free(gctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
|
gctx->stctxi->st_manager_private = (void *) &gctx->base;
|
||||||
(gshare) ? gshare->st_ctx : NULL);
|
|
||||||
if (!gctx->st_ctx) {
|
|
||||||
gctx->pipe->destroy(gctx->pipe);
|
|
||||||
free(gctx);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &gctx->base;
|
return &gctx->base;
|
||||||
}
|
}
|
||||||
|
|
@ -682,9 +485,7 @@ destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
||||||
if (!dpy->Initialized)
|
if (!dpy->Initialized)
|
||||||
_eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
|
_eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
|
||||||
|
|
||||||
egl_g3d_realloc_context(dpy, &gctx->base);
|
gctx->stctxi->destroy(gctx->stctxi);
|
||||||
/* it will destroy the associated pipe context */
|
|
||||||
gctx->stapi->st_destroy_context(gctx->st_ctx);
|
|
||||||
|
|
||||||
free(gctx);
|
free(gctx);
|
||||||
}
|
}
|
||||||
|
|
@ -786,14 +587,20 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gsurf->stvis = gconf->stvis;
|
||||||
|
if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER)
|
||||||
|
gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT;
|
||||||
|
|
||||||
|
gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base);
|
||||||
|
if (!gsurf->stfbi) {
|
||||||
|
gsurf->native->destroy(gsurf->native);
|
||||||
|
free(gsurf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
nsurf->user_data = &gsurf->base;
|
nsurf->user_data = &gsurf->base;
|
||||||
gsurf->native = nsurf;
|
gsurf->native = nsurf;
|
||||||
|
|
||||||
gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ?
|
|
||||||
NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
|
|
||||||
if (!gconf->native->mode.doubleBufferMode)
|
|
||||||
gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
|
|
||||||
|
|
||||||
return &gsurf->base;
|
return &gsurf->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -849,7 +656,8 @@ destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
|
||||||
if (!dpy->Initialized)
|
if (!dpy->Initialized)
|
||||||
_eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
|
_eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
|
||||||
|
|
||||||
pipe_surface_reference(&gsurf->render_surface, NULL);
|
pipe_texture_reference(&gsurf->render_texture, NULL);
|
||||||
|
egl_g3d_destroy_st_framebuffer(gsurf->stfbi);
|
||||||
gsurf->native->destroy(gsurf->native);
|
gsurf->native->destroy(gsurf->native);
|
||||||
free(gsurf);
|
free(gsurf);
|
||||||
}
|
}
|
||||||
|
|
@ -868,6 +676,7 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
{
|
{
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||||
struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
|
struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
|
||||||
|
struct egl_g3d_surface *gread = egl_g3d_surface(read);
|
||||||
struct egl_g3d_context *old_gctx;
|
struct egl_g3d_context *old_gctx;
|
||||||
EGLBoolean ok = EGL_TRUE;
|
EGLBoolean ok = EGL_TRUE;
|
||||||
|
|
||||||
|
|
@ -878,39 +687,29 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
|
|
||||||
if (old_gctx) {
|
if (old_gctx) {
|
||||||
/* flush old context */
|
/* flush old context */
|
||||||
old_gctx->stapi->st_flush(old_gctx->st_ctx,
|
old_gctx->stctxi->flush(old_gctx->stctxi,
|
||||||
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
||||||
|
|
||||||
/*
|
|
||||||
* The old context is no longer current, and egl_g3d_realloc_context()
|
|
||||||
* should be called to destroy the framebuffers. However, it is possible
|
|
||||||
* that it will be made current again with the same draw/read surfaces.
|
|
||||||
* It might be better to keep it around.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gctx) {
|
if (gctx) {
|
||||||
ok = egl_g3d_realloc_context(dpy, &gctx->base);
|
ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi,
|
||||||
|
(gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
/* XXX: need to pass the winsys argument for
|
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi);
|
||||||
* flush_frontbuffer in the fourth parameter here:
|
if (gread != gdraw) {
|
||||||
*/
|
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi,
|
||||||
ok = gctx->stapi->st_make_current(gctx->st_ctx,
|
gread->stfbi);
|
||||||
gctx->draw.st_fb,
|
}
|
||||||
gctx->read.st_fb,
|
|
||||||
NULL);
|
if (gdraw->base.Type == EGL_WINDOW_BIT) {
|
||||||
if (ok) {
|
gctx->base.WindowRenderBuffer =
|
||||||
egl_g3d_validate_context(dpy, &gctx->base);
|
(gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
|
||||||
if (gdraw->base.Type == EGL_WINDOW_BIT) {
|
EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
|
||||||
gctx->base.WindowRenderBuffer =
|
|
||||||
(gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
|
|
||||||
EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (old_gctx) {
|
else if (old_gctx) {
|
||||||
ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL, NULL);
|
ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL);
|
||||||
old_gctx->base.WindowRenderBuffer = EGL_NONE;
|
old_gctx->base.WindowRenderBuffer = EGL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -937,15 +736,17 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
|
|
||||||
/* or when the surface is single-buffered */
|
/* or when the surface is single-buffered */
|
||||||
if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
|
if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT)
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
|
|
||||||
if (ctx && ctx->DrawSurface == surf)
|
if (ctx && ctx->DrawSurface == surf)
|
||||||
gctx = egl_g3d_context(ctx);
|
gctx = egl_g3d_context(ctx);
|
||||||
|
|
||||||
/* flush if the surface is current */
|
/* flush if the surface is current */
|
||||||
if (gctx)
|
if (gctx) {
|
||||||
gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
|
gctx->stctxi->flush(gctx->stctxi,
|
||||||
|
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return gsurf->native->swap_buffers(gsurf->native);
|
return gsurf->native->swap_buffers(gsurf->native);
|
||||||
}
|
}
|
||||||
|
|
@ -985,7 +786,7 @@ get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt],
|
psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt],
|
||||||
0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE);
|
0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||||
pipe_texture_reference(&textures[natt], NULL);
|
pipe_texture_reference(&textures[natt], NULL);
|
||||||
|
|
||||||
return psurf;
|
return psurf;
|
||||||
|
|
@ -1003,7 +804,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
||||||
struct pipe_screen *screen = gdpy->native->screen;
|
struct pipe_screen *screen = gdpy->native->screen;
|
||||||
struct pipe_surface *psurf;
|
struct pipe_surface *psurf;
|
||||||
|
|
||||||
if (!gsurf->render_surface)
|
if (!gsurf->render_texture)
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
|
|
||||||
gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target));
|
gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target));
|
||||||
|
|
@ -1018,26 +819,33 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
||||||
/* flush if the surface is current */
|
/* flush if the surface is current */
|
||||||
if (ctx && ctx->DrawSurface == &gsurf->base) {
|
if (ctx && ctx->DrawSurface == &gsurf->base) {
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||||
gctx->stapi->st_flush(gctx->st_ctx,
|
gctx->stctxi->flush(gctx->stctxi,
|
||||||
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create a pipe context to copy surfaces */
|
||||||
|
if (!gdpy->pipe) {
|
||||||
|
gdpy->pipe =
|
||||||
|
gdpy->native->screen->context_create(gdpy->native->screen, NULL);
|
||||||
|
if (!gdpy->pipe)
|
||||||
|
return EGL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
|
psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
|
||||||
if (psurf) {
|
if (psurf) {
|
||||||
struct pipe_context pipe;
|
struct pipe_surface *psrc;
|
||||||
|
|
||||||
/**
|
psrc = screen->get_tex_surface(screen, gsurf->render_texture,
|
||||||
* XXX This is hacky. If we might allow the EGLDisplay to create a pipe
|
0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
|
||||||
* context of its own and use the blitter context for this.
|
if (psrc) {
|
||||||
*/
|
gdpy->pipe->surface_copy(gdpy->pipe, psurf, 0, 0,
|
||||||
memset(&pipe, 0, sizeof(pipe));
|
psrc, 0, 0, psurf->width, psurf->height);
|
||||||
pipe.screen = screen;
|
pipe_surface_reference(&psrc, NULL);
|
||||||
|
|
||||||
util_surface_copy(&pipe, FALSE, psurf, 0, 0,
|
nsurf->flush_frontbuffer(nsurf);
|
||||||
gsurf->render_surface, 0, 0, psurf->width, psurf->height);
|
}
|
||||||
|
|
||||||
pipe_surface_reference(&psurf, NULL);
|
pipe_surface_reference(&psurf, NULL);
|
||||||
nsurf->flush_frontbuffer(nsurf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsurf->destroy(nsurf);
|
nsurf->destroy(nsurf);
|
||||||
|
|
@ -1048,8 +856,16 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
||||||
static EGLBoolean
|
static EGLBoolean
|
||||||
egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
|
egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
|
||||||
{
|
{
|
||||||
|
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||||
gctx->stapi->st_finish(gctx->st_ctx);
|
struct pipe_screen *screen = gdpy->native->screen;
|
||||||
|
struct pipe_fence_handle *fence = NULL;
|
||||||
|
|
||||||
|
gctx->stctxi->flush(gctx->stctxi,
|
||||||
|
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
|
||||||
|
screen->fence_finish(screen, fence, 0);
|
||||||
|
screen->fence_reference(screen, &fence, NULL);
|
||||||
|
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1079,10 +895,10 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
|
||||||
/* in case this is called before a display is initialized */
|
/* in case this is called before a display is initialized */
|
||||||
egl_g3d_init_st(&gdrv->base);
|
egl_g3d_init_st(&gdrv->base);
|
||||||
|
|
||||||
for (i = 0; i < NUM_EGL_G3D_STS; i++) {
|
for (i = 0; i < ST_API_COUNT; i++) {
|
||||||
const struct egl_g3d_st *stapi = gdrv->stapis[i];
|
struct st_api *stapi = gdrv->stapis[i];
|
||||||
if (stapi) {
|
if (stapi) {
|
||||||
proc = (_EGLProc) stapi->st_get_proc_address(procname);
|
proc = (_EGLProc) stapi->get_proc_address(stapi, procname);
|
||||||
if (proc)
|
if (proc)
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
@ -1098,8 +914,8 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||||
_EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
|
_EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
|
||||||
struct egl_g3d_context *gctx;
|
struct egl_g3d_context *gctx;
|
||||||
enum pipe_format target_format;
|
enum pipe_format internal_format;
|
||||||
int target;
|
enum st_texture_type target;
|
||||||
|
|
||||||
if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
|
if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
|
||||||
return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
|
return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
|
||||||
|
|
@ -1110,10 +926,10 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
|
|
||||||
switch (gsurf->base.TextureFormat) {
|
switch (gsurf->base.TextureFormat) {
|
||||||
case EGL_TEXTURE_RGB:
|
case EGL_TEXTURE_RGB:
|
||||||
target_format = PIPE_FORMAT_R8G8B8_UNORM;
|
internal_format = PIPE_FORMAT_R8G8B8_UNORM;
|
||||||
break;
|
break;
|
||||||
case EGL_TEXTURE_RGBA:
|
case EGL_TEXTURE_RGBA:
|
||||||
target_format = PIPE_FORMAT_B8G8R8A8_UNORM;
|
internal_format = PIPE_FORMAT_B8G8R8A8_UNORM;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
|
return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
|
||||||
|
|
@ -1129,21 +945,24 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
|
|
||||||
if (!es1)
|
if (!es1)
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
if (!gsurf->render_surface)
|
if (!gsurf->render_texture)
|
||||||
return EGL_FALSE;
|
return EGL_FALSE;
|
||||||
|
|
||||||
/* flush properly if the surface is bound */
|
/* flush properly if the surface is bound */
|
||||||
if (gsurf->base.CurrentContext) {
|
if (gsurf->base.CurrentContext) {
|
||||||
gctx = egl_g3d_context(gsurf->base.CurrentContext);
|
gctx = egl_g3d_context(gsurf->base.CurrentContext);
|
||||||
gctx->stapi->st_flush(gctx->st_ctx,
|
gctx->stctxi->flush(gctx->stctxi,
|
||||||
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
gctx = egl_g3d_context(es1);
|
gctx = egl_g3d_context(es1);
|
||||||
gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
|
if (gctx->stctxi->teximage) {
|
||||||
target, gsurf->base.MipmapLevel, target_format);
|
if (!gctx->stctxi->teximage(gctx->stctxi, target,
|
||||||
|
gsurf->base.MipmapLevel, internal_format,
|
||||||
gsurf->base.BoundToTexture = EGL_TRUE;
|
gsurf->render_texture, gsurf->base.MipmapTexture))
|
||||||
|
return EGL_FALSE;
|
||||||
|
gsurf->base.BoundToTexture = EGL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -1160,14 +979,15 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||||
if (buffer != EGL_BACK_BUFFER)
|
if (buffer != EGL_BACK_BUFFER)
|
||||||
return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
|
return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
|
||||||
|
|
||||||
if (gsurf->render_surface) {
|
if (gsurf->render_texture) {
|
||||||
_EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
|
_EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
|
||||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||||
|
|
||||||
/* what if the context the surface binds to is no longer current? */
|
/* what if the context the surface binds to is no longer current? */
|
||||||
if (gctx)
|
if (gctx) {
|
||||||
gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
|
gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D,
|
||||||
ST_TEXTURE_2D, gsurf->base.MipmapLevel);
|
gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gsurf->base.BoundToTexture = EGL_FALSE;
|
gsurf->base.BoundToTexture = EGL_FALSE;
|
||||||
|
|
@ -1279,6 +1099,12 @@ static void
|
||||||
egl_g3d_unload(_EGLDriver *drv)
|
egl_g3d_unload(_EGLDriver *drv)
|
||||||
{
|
{
|
||||||
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
||||||
|
EGLint i;
|
||||||
|
|
||||||
|
for (i = 0; i < ST_API_COUNT; i++) {
|
||||||
|
if (gdrv->stapis[i])
|
||||||
|
gdrv->stapis[i]->destroy(gdrv->stapis[i]);
|
||||||
|
}
|
||||||
|
|
||||||
egl_g3d_destroy_probe(drv, NULL);
|
egl_g3d_destroy_probe(drv, NULL);
|
||||||
free(gdrv);
|
free(gdrv);
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,11 @@
|
||||||
#include "eglmode.h"
|
#include "eglmode.h"
|
||||||
|
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
#include "egl_st.h"
|
#include "egl_g3d_st.h"
|
||||||
|
|
||||||
struct egl_g3d_driver {
|
struct egl_g3d_driver {
|
||||||
_EGLDriver base;
|
_EGLDriver base;
|
||||||
const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS];
|
struct st_api *stapis[ST_API_COUNT];
|
||||||
EGLint api_mask;
|
EGLint api_mask;
|
||||||
|
|
||||||
EGLint probe_key;
|
EGLint probe_key;
|
||||||
|
|
@ -51,35 +51,34 @@ struct egl_g3d_driver {
|
||||||
|
|
||||||
struct egl_g3d_display {
|
struct egl_g3d_display {
|
||||||
struct native_display *native;
|
struct native_display *native;
|
||||||
};
|
|
||||||
|
|
||||||
struct egl_g3d_buffer {
|
struct st_manager *smapi;
|
||||||
struct st_framebuffer *st_fb;
|
struct pipe_context *pipe;
|
||||||
uint attachment_mask;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct egl_g3d_context {
|
struct egl_g3d_context {
|
||||||
_EGLContext base;
|
_EGLContext base;
|
||||||
|
|
||||||
const struct egl_g3d_st *stapi;
|
struct st_api *stapi;
|
||||||
struct pipe_context *pipe;
|
|
||||||
|
|
||||||
struct st_context *st_ctx;
|
struct st_context_iface *stctxi;
|
||||||
EGLBoolean force_validate;
|
|
||||||
struct egl_g3d_buffer draw, read;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct egl_g3d_surface {
|
struct egl_g3d_surface {
|
||||||
_EGLSurface base;
|
_EGLSurface base;
|
||||||
|
|
||||||
|
struct st_visual stvis;
|
||||||
|
struct st_framebuffer_iface *stfbi;
|
||||||
|
|
||||||
struct native_surface *native;
|
struct native_surface *native;
|
||||||
enum native_attachment render_att;
|
struct pipe_texture *render_texture;
|
||||||
struct pipe_surface *render_surface;
|
|
||||||
unsigned int sequence_number;
|
unsigned int sequence_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct egl_g3d_config {
|
struct egl_g3d_config {
|
||||||
_EGLConfig base;
|
_EGLConfig base;
|
||||||
const struct native_config *native;
|
const struct native_config *native;
|
||||||
|
struct st_visual stvis;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct egl_g3d_image {
|
struct egl_g3d_image {
|
||||||
|
|
|
||||||
227
src/gallium/state_trackers/egl/common/egl_g3d_st.c
Normal file
227
src/gallium/state_trackers/egl/common/egl_g3d_st.c
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
/*
|
||||||
|
* Mesa 3-D graphics library
|
||||||
|
* Version: 7.9
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 LunarG Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
#include "util/u_dl.h"
|
||||||
|
#include "eglimage.h"
|
||||||
|
#include "eglmutex.h"
|
||||||
|
|
||||||
|
#include "egl_g3d.h"
|
||||||
|
#include "egl_g3d_st.h"
|
||||||
|
|
||||||
|
struct egl_g3d_st_manager {
|
||||||
|
struct st_manager base;
|
||||||
|
_EGLDisplay *display;
|
||||||
|
};
|
||||||
|
|
||||||
|
static INLINE struct egl_g3d_st_manager *
|
||||||
|
egl_g3d_st_manager(struct st_manager *smapi)
|
||||||
|
{
|
||||||
|
return (struct egl_g3d_st_manager *) smapi;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st_api *
|
||||||
|
egl_g3d_create_st_api(enum st_api_type api)
|
||||||
|
{
|
||||||
|
const char *stmod_name;
|
||||||
|
struct util_dl_library *lib;
|
||||||
|
const struct st_module *mod;
|
||||||
|
|
||||||
|
switch (api) {
|
||||||
|
case ST_API_OPENGL:
|
||||||
|
stmod_name = ST_MODULE_OPENGL_SYMBOL;
|
||||||
|
break;
|
||||||
|
case ST_API_OPENGL_ES1:
|
||||||
|
stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL;
|
||||||
|
break;
|
||||||
|
case ST_API_OPENGL_ES2:
|
||||||
|
stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL;
|
||||||
|
break;
|
||||||
|
case ST_API_OPENVG:
|
||||||
|
stmod_name = ST_MODULE_OPENVG_SYMBOL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
stmod_name = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!stmod_name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mod = NULL;
|
||||||
|
lib = util_dl_open(NULL);
|
||||||
|
if (lib) {
|
||||||
|
mod = (const struct st_module *)
|
||||||
|
util_dl_get_proc_address(lib, stmod_name);
|
||||||
|
util_dl_close(lib);
|
||||||
|
}
|
||||||
|
if (!mod || mod->api != api)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return mod->create_api();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st_manager *
|
||||||
|
egl_g3d_create_st_manager(_EGLDisplay *dpy)
|
||||||
|
{
|
||||||
|
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||||
|
struct egl_g3d_st_manager *gsmapi;
|
||||||
|
|
||||||
|
gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
|
||||||
|
if (gsmapi) {
|
||||||
|
gsmapi->display = dpy;
|
||||||
|
|
||||||
|
gsmapi->base.screen = gdpy->native->screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &gsmapi->base;;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
egl_g3d_destroy_st_manager(struct st_manager *smapi)
|
||||||
|
{
|
||||||
|
struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
|
||||||
|
free(gsmapi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
|
||||||
|
enum st_attachment_type statt)
|
||||||
|
{
|
||||||
|
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
|
||||||
|
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||||
|
|
||||||
|
return gsurf->native->flush_frontbuffer(gsurf->native);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
|
||||||
|
const enum st_attachment_type *statts,
|
||||||
|
unsigned count,
|
||||||
|
struct pipe_texture **out)
|
||||||
|
{
|
||||||
|
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
|
||||||
|
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||||
|
struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
|
||||||
|
uint attachment_mask = 0;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
int natt;
|
||||||
|
|
||||||
|
switch (statts[i]) {
|
||||||
|
case ST_ATTACHMENT_FRONT_LEFT:
|
||||||
|
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_LEFT:
|
||||||
|
natt = NATIVE_ATTACHMENT_BACK_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||||
|
natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_RIGHT:
|
||||||
|
natt = NATIVE_ATTACHMENT_BACK_RIGHT;
|
||||||
|
default:
|
||||||
|
natt = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (natt >= 0)
|
||||||
|
attachment_mask |= 1 << natt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gsurf->native->validate(gsurf->native, attachment_mask,
|
||||||
|
&gsurf->sequence_number, textures, &gsurf->base.Width,
|
||||||
|
&gsurf->base.Height))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
struct pipe_texture *tex;
|
||||||
|
int natt;
|
||||||
|
|
||||||
|
switch (statts[i]) {
|
||||||
|
case ST_ATTACHMENT_FRONT_LEFT:
|
||||||
|
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_LEFT:
|
||||||
|
natt = NATIVE_ATTACHMENT_BACK_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||||
|
natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_RIGHT:
|
||||||
|
natt = NATIVE_ATTACHMENT_BACK_RIGHT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
natt = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (natt >= 0) {
|
||||||
|
tex = textures[natt];
|
||||||
|
|
||||||
|
if (statts[i] == stfbi->visual->render_buffer)
|
||||||
|
pipe_texture_reference(&gsurf->render_texture, tex);
|
||||||
|
|
||||||
|
if (attachment_mask & (1 << natt)) {
|
||||||
|
/* transfer the ownership to the caller */
|
||||||
|
out[i] = tex;
|
||||||
|
attachment_mask &= ~(1 << natt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* the attachment is listed more than once */
|
||||||
|
pipe_texture_reference(&out[i], tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st_framebuffer_iface *
|
||||||
|
egl_g3d_create_st_framebuffer(_EGLSurface *surf)
|
||||||
|
{
|
||||||
|
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||||
|
struct st_framebuffer_iface *stfbi;
|
||||||
|
|
||||||
|
stfbi = CALLOC_STRUCT(st_framebuffer_iface);
|
||||||
|
if (!stfbi)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
stfbi->visual = &gsurf->stvis;
|
||||||
|
stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
|
||||||
|
stfbi->validate = egl_g3d_st_framebuffer_validate;
|
||||||
|
stfbi->st_manager_private = (void *) &gsurf->base;
|
||||||
|
|
||||||
|
return stfbi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
|
||||||
|
{
|
||||||
|
free(stfbi);
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Mesa 3-D graphics library
|
* Mesa 3-D graphics library
|
||||||
* Version: 7.8
|
* Version: 7.9
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
|
* Copyright (C) 2010 LunarG Inc.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
|
@ -20,54 +20,60 @@
|
||||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 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.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _EGL_ST_H_
|
#ifndef _EGL_G3D_ST_H_
|
||||||
#define _EGL_ST_H_
|
#define _EGL_G3D_ST_H_
|
||||||
|
|
||||||
#include "GL/gl.h" /* for GL types */
|
|
||||||
#include "GL/internal/glcore.h" /* for __GLcontextModes */
|
|
||||||
|
|
||||||
#include "pipe/p_compiler.h"
|
#include "pipe/p_compiler.h"
|
||||||
#include "pipe/p_format.h"
|
#include "state_tracker/st_api.h"
|
||||||
#include "pipe/p_context.h"
|
#include "egltypedefs.h"
|
||||||
|
|
||||||
/* avoid calling st functions directly */
|
struct st_api *
|
||||||
#if 1
|
egl_g3d_create_st_api(enum st_api_type api);
|
||||||
|
|
||||||
#define ST_SURFACE_FRONT_LEFT 0
|
struct st_manager *
|
||||||
#define ST_SURFACE_BACK_LEFT 1
|
egl_g3d_create_st_manager(_EGLDisplay *dpy);
|
||||||
#define ST_SURFACE_FRONT_RIGHT 2
|
|
||||||
#define ST_SURFACE_BACK_RIGHT 3
|
|
||||||
|
|
||||||
#define ST_TEXTURE_2D 0x2
|
void
|
||||||
|
egl_g3d_destroy_st_manager(struct st_manager *smapi);
|
||||||
|
|
||||||
struct st_context;
|
struct st_framebuffer_iface *
|
||||||
struct st_framebuffer;
|
egl_g3d_create_st_framebuffer(_EGLSurface *surf);
|
||||||
typedef void (*st_proc)();
|
|
||||||
|
|
||||||
#else
|
void
|
||||||
#include "state_tracker/st_public.h"
|
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* remember to update egl_g3d_get_st() when update the enums */
|
/**
|
||||||
enum egl_g3d_st_api {
|
* Return the EGL_<api>_BIT of the st api.
|
||||||
EGL_G3D_ST_OPENGL_ES = 0,
|
*/
|
||||||
EGL_G3D_ST_OPENVG,
|
static INLINE int
|
||||||
EGL_G3D_ST_OPENGL_ES2,
|
egl_g3d_st_api_bit(enum st_api_type api)
|
||||||
EGL_G3D_ST_OPENGL,
|
{
|
||||||
|
int bit;
|
||||||
|
|
||||||
NUM_EGL_G3D_STS
|
switch (api) {
|
||||||
};
|
case ST_API_OPENGL:
|
||||||
|
bit = EGL_OPENGL_BIT;
|
||||||
|
break;
|
||||||
|
case ST_API_OPENGL_ES1:
|
||||||
|
bit = EGL_OPENGL_ES_BIT;
|
||||||
|
break;
|
||||||
|
case ST_API_OPENGL_ES2:
|
||||||
|
bit = EGL_OPENGL_ES2_BIT;
|
||||||
|
break;
|
||||||
|
case ST_API_OPENVG:
|
||||||
|
bit = EGL_OPENVG_BIT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bit = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
struct egl_g3d_st {
|
return bit;
|
||||||
#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__);
|
}
|
||||||
#include "st_public_tmp.h"
|
|
||||||
/* fields must be added here */
|
|
||||||
EGLint api_bit;
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct egl_g3d_st *
|
#endif /* _EGL_G3D_ST_H_ */
|
||||||
egl_g3d_get_st(enum egl_g3d_st_api api);
|
|
||||||
|
|
||||||
#endif /* _EGL_ST_H_ */
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
/*
|
|
||||||
* Mesa 3-D graphics library
|
|
||||||
* Version: 7.8
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* BRIAN PAUL 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 <dlfcn.h>
|
|
||||||
#include "pipe/p_compiler.h"
|
|
||||||
#include "util/u_memory.h"
|
|
||||||
#include "egllog.h"
|
|
||||||
#include "EGL/egl.h" /* for EGL_api_BIT */
|
|
||||||
|
|
||||||
#include "egl_st.h"
|
|
||||||
|
|
||||||
#ifndef HAVE_DLADDR
|
|
||||||
#define HAVE_DLADDR 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_DLADDR
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
egl_g3d_st_names[] = {
|
|
||||||
#define ST_PUBLIC(name, ...) #name,
|
|
||||||
#include "st_public_tmp.h"
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static boolean
|
|
||||||
egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
|
|
||||||
{
|
|
||||||
st_proc *procs = (st_proc *) stapi;
|
|
||||||
void *handle;
|
|
||||||
Dl_info info;
|
|
||||||
const char **name;
|
|
||||||
|
|
||||||
if (!dladdr(sym, &info))
|
|
||||||
return FALSE;
|
|
||||||
handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
|
|
||||||
if (!handle)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
for (name = egl_g3d_st_names; *name; name++) {
|
|
||||||
st_proc proc = (st_proc) dlsym(handle, *name);
|
|
||||||
if (!proc) {
|
|
||||||
_eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname);
|
|
||||||
memset(stapi, 0, sizeof(*stapi));
|
|
||||||
dlclose(handle);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
*procs++ = proc;
|
|
||||||
}
|
|
||||||
|
|
||||||
dlclose(handle);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* HAVE_DLADDR */
|
|
||||||
|
|
||||||
static boolean
|
|
||||||
egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
|
|
||||||
{
|
|
||||||
#define ST_PUBLIC(name, ...) stapi->name = name;
|
|
||||||
#include "st_public_tmp.h"
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_DLADDR */
|
|
||||||
|
|
||||||
static boolean
|
|
||||||
egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api)
|
|
||||||
{
|
|
||||||
void *handle, *sym;
|
|
||||||
boolean res = FALSE;
|
|
||||||
|
|
||||||
/* already initialized */
|
|
||||||
if (stapi->st_notify_swapbuffers != NULL)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
|
|
||||||
if (!handle)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
sym = dlsym(handle, api);
|
|
||||||
if (sym && egl_g3d_fill_st(stapi, sym))
|
|
||||||
res = TRUE;
|
|
||||||
|
|
||||||
dlclose(handle);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
const char *symbol;
|
|
||||||
EGLint api_bit;
|
|
||||||
} egl_g3d_st_info[NUM_EGL_G3D_STS] = {
|
|
||||||
{ "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT },
|
|
||||||
{ "st_api_OpenVG", EGL_OPENVG_BIT },
|
|
||||||
{ "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT },
|
|
||||||
{ "st_api_OpenGL", EGL_OPENGL_BIT },
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct egl_g3d_st *
|
|
||||||
egl_g3d_get_st(enum egl_g3d_st_api api)
|
|
||||||
{
|
|
||||||
static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS];
|
|
||||||
|
|
||||||
if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) {
|
|
||||||
all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit;
|
|
||||||
return &all_trackers[api];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share)
|
|
||||||
ST_PUBLIC(st_destroy_context, void, struct st_context *st)
|
|
||||||
ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask)
|
|
||||||
ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData)
|
|
||||||
ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height)
|
|
||||||
ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf)
|
|
||||||
ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height)
|
|
||||||
ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
|
|
||||||
ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
|
|
||||||
ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb)
|
|
||||||
ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb)
|
|
||||||
ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read, void *winsys_drawable_handle)
|
|
||||||
ST_PUBLIC(st_get_current, struct st_context *, void)
|
|
||||||
ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence)
|
|
||||||
ST_PUBLIC(st_finish, void, struct st_context *st)
|
|
||||||
ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb)
|
|
||||||
ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format)
|
|
||||||
ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level)
|
|
||||||
ST_PUBLIC(st_get_proc_address, st_proc, const char *procname)
|
|
||||||
#undef ST_PUBLIC
|
|
||||||
|
|
@ -38,6 +38,7 @@ SYS_LIBS = -lm -pthread
|
||||||
|
|
||||||
|
|
||||||
INCLUDE_DIRS = \
|
INCLUDE_DIRS = \
|
||||||
|
-I$(TOP)/src/mesa \
|
||||||
-I$(TOP)/src/gallium/include
|
-I$(TOP)/src/gallium/include
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
#include "pipe/p_compiler.h"
|
#include "state_tracker/st_manager.h"
|
||||||
|
|
||||||
PUBLIC const int st_api_OpenGL_ES1 = 1;
|
PUBLIC const int st_api_OpenGL_ES1 = 1;
|
||||||
|
|
||||||
|
PUBLIC const struct st_module st_module_OpenGL_ES1 = {
|
||||||
|
.api = ST_API_OPENGL_ES1,
|
||||||
|
.create_api = st_manager_create_api
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
#include "pipe/p_compiler.h"
|
#include "state_tracker/st_manager.h"
|
||||||
|
|
||||||
PUBLIC const int st_api_OpenGL_ES2 = 1;
|
PUBLIC const int st_api_OpenGL_ES2 = 1;
|
||||||
|
|
||||||
|
PUBLIC const struct st_module st_module_OpenGL_ES2 = {
|
||||||
|
.api = ST_API_OPENGL_ES2,
|
||||||
|
.create_api = st_manager_create_api
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ C_SOURCES = \
|
||||||
glx_api.c \
|
glx_api.c \
|
||||||
glx_getproc.c \
|
glx_getproc.c \
|
||||||
glx_usefont.c \
|
glx_usefont.c \
|
||||||
xm_api.c
|
xm_api.c \
|
||||||
|
xm_st.c
|
||||||
|
|
||||||
include ../../../Makefile.template
|
include ../../../Makefile.template
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ if env['platform'] == 'linux' \
|
||||||
'glx_getproc.c',
|
'glx_getproc.c',
|
||||||
'glx_usefont.c',
|
'glx_usefont.c',
|
||||||
'xm_api.c',
|
'xm_api.c',
|
||||||
|
'xm_st.c',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
Export('st_xlib')
|
Export('st_xlib')
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,9 @@
|
||||||
|
|
||||||
#include "xm_api.h"
|
#include "xm_api.h"
|
||||||
#include "main/context.h"
|
#include "main/context.h"
|
||||||
#include "main/config.h"
|
|
||||||
#include "main/macros.h"
|
#include "main/macros.h"
|
||||||
#include "main/imports.h"
|
#include "main/imports.h"
|
||||||
#include "main/version.h"
|
#include "main/version.h"
|
||||||
#include "state_tracker/st_context.h"
|
|
||||||
#include "state_tracker/st_public.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* This indicates the client-side GLX API and GLX encoder version. */
|
/* This indicates the client-side GLX API and GLX encoder version. */
|
||||||
|
|
@ -1304,7 +1301,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
|
||||||
if (MakeCurrent_PrevContext == src) {
|
if (MakeCurrent_PrevContext == src) {
|
||||||
_mesa_Flush();
|
_mesa_Flush();
|
||||||
}
|
}
|
||||||
st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask );
|
XMesaCopyContext(xm_src, xm_dst, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "xm_api.h"
|
#include "xm_api.h"
|
||||||
#include "main/context.h"
|
#include "xm_st.h"
|
||||||
#include "main/framebuffer.h"
|
|
||||||
|
|
||||||
#include "state_tracker/st_public.h"
|
#include "main/context.h"
|
||||||
#include "state_tracker/st_context.h"
|
|
||||||
#include "pipe/p_defines.h"
|
#include "pipe/p_defines.h"
|
||||||
#include "pipe/p_screen.h"
|
#include "pipe/p_screen.h"
|
||||||
#include "pipe/p_context.h"
|
#include "pipe/p_context.h"
|
||||||
|
|
@ -72,19 +70,56 @@
|
||||||
* global.
|
* global.
|
||||||
*/
|
*/
|
||||||
static struct xm_driver driver;
|
static struct xm_driver driver;
|
||||||
|
static struct st_api *stapi;
|
||||||
|
|
||||||
void xmesa_set_driver( const struct xm_driver *templ )
|
void xmesa_set_driver( const struct xm_driver *templ )
|
||||||
{
|
{
|
||||||
driver = *templ;
|
driver = *templ;
|
||||||
|
stapi = driver.create_st_api();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static XMesaDisplay
|
||||||
* Global X driver lock
|
xmesa_init_display( Display *display )
|
||||||
*/
|
{
|
||||||
pipe_mutex _xmesa_lock;
|
pipe_static_mutex(init_mutex);
|
||||||
|
static struct xmesa_display xm_display;
|
||||||
|
XMesaDisplay xmdpy;
|
||||||
|
|
||||||
static struct pipe_screen *screen = NULL;
|
pipe_mutex_lock(init_mutex);
|
||||||
|
|
||||||
|
/* TODO support for multiple displays */
|
||||||
|
xmdpy = &xm_display;
|
||||||
|
|
||||||
|
if (!xmdpy->display && display) {
|
||||||
|
xmdpy->display = display;
|
||||||
|
xmdpy->screen = driver.create_pipe_screen(display);
|
||||||
|
xmdpy->smapi = CALLOC_STRUCT(st_manager);
|
||||||
|
if (xmdpy->smapi)
|
||||||
|
xmdpy->smapi->screen = xmdpy->screen;
|
||||||
|
|
||||||
|
if (xmdpy->screen && xmdpy->smapi) {
|
||||||
|
pipe_mutex_init(xmdpy->mutex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (xmdpy->screen) {
|
||||||
|
xmdpy->screen->destroy(xmdpy->screen);
|
||||||
|
xmdpy->screen = NULL;
|
||||||
|
}
|
||||||
|
if (xmdpy->smapi) {
|
||||||
|
FREE(xmdpy->smapi);
|
||||||
|
xmdpy->smapi = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmdpy->display = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!xmdpy->display || xmdpy->display != display)
|
||||||
|
xmdpy = NULL;
|
||||||
|
|
||||||
|
pipe_mutex_unlock(init_mutex);
|
||||||
|
|
||||||
|
return xmdpy;
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/***** X Utility Functions *****/
|
/***** X Utility Functions *****/
|
||||||
|
|
@ -194,12 +229,13 @@ void
|
||||||
xmesa_get_window_size(Display *dpy, XMesaBuffer b,
|
xmesa_get_window_size(Display *dpy, XMesaBuffer b,
|
||||||
GLuint *width, GLuint *height)
|
GLuint *width, GLuint *height)
|
||||||
{
|
{
|
||||||
|
XMesaDisplay xmdpy = xmesa_init_display(dpy);
|
||||||
Status stat;
|
Status stat;
|
||||||
|
|
||||||
pipe_mutex_lock(_xmesa_lock);
|
pipe_mutex_lock(xmdpy->mutex);
|
||||||
XSync(b->xm_visual->display, 0); /* added for Chromium */
|
XSync(b->xm_visual->display, 0); /* added for Chromium */
|
||||||
stat = get_drawable_size(dpy, b->ws.drawable, width, height);
|
stat = get_drawable_size(dpy, b->ws.drawable, width, height);
|
||||||
pipe_mutex_unlock(_xmesa_lock);
|
pipe_mutex_unlock(xmdpy->mutex);
|
||||||
|
|
||||||
if (!stat) {
|
if (!stat) {
|
||||||
/* probably querying a window that's recently been destroyed */
|
/* probably querying a window that's recently been destroyed */
|
||||||
|
|
@ -273,49 +309,43 @@ choose_pixel_format(XMesaVisual v)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the default gallium screen for a Z/Stencil format that
|
* Choose a depth/stencil format that is "better" than the given depth and
|
||||||
* at least matches the given depthBits and stencilBits.
|
* stencil sizes.
|
||||||
*/
|
*/
|
||||||
static void
|
static enum pipe_format
|
||||||
xmesa_choose_z_stencil_format(int depthBits, int stencilBits,
|
choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil)
|
||||||
enum pipe_format *depthFormat,
|
|
||||||
enum pipe_format *stencilFormat)
|
|
||||||
{
|
{
|
||||||
const enum pipe_texture_target target = PIPE_TEXTURE_2D;
|
const enum pipe_texture_target target = PIPE_TEXTURE_2D;
|
||||||
const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
|
const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
|
||||||
const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE |
|
const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE |
|
||||||
PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO);
|
PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO);
|
||||||
static enum pipe_format formats[] = {
|
enum pipe_format formats[8], fmt;
|
||||||
PIPE_FORMAT_S8Z24_UNORM,
|
int count, i;
|
||||||
PIPE_FORMAT_Z24S8_UNORM,
|
|
||||||
PIPE_FORMAT_Z16_UNORM,
|
|
||||||
PIPE_FORMAT_Z32_UNORM
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
assert(screen);
|
count = 0;
|
||||||
|
if (depth <= 24 && stencil <= 8) {
|
||||||
|
formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
|
||||||
|
formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
|
||||||
|
}
|
||||||
|
|
||||||
*depthFormat = *stencilFormat = PIPE_FORMAT_NONE;
|
if (!stencil) {
|
||||||
|
if (depth <= 16)
|
||||||
|
formats[count++] = PIPE_FORMAT_Z16_UNORM;
|
||||||
|
if (depth <= 32)
|
||||||
|
formats[count++] = PIPE_FORMAT_Z32_UNORM;
|
||||||
|
}
|
||||||
|
|
||||||
/* search for supported format */
|
fmt = PIPE_FORMAT_NONE;
|
||||||
for (i = 0; i < Elements(formats); i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if (screen->is_format_supported(screen, formats[i],
|
if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
|
||||||
target, tex_usage, geom_flags)) {
|
target, tex_usage, geom_flags)) {
|
||||||
*depthFormat = formats[i];
|
fmt = formats[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stencilBits) {
|
return fmt;
|
||||||
*stencilFormat = *depthFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX we should check that he chosen format has at least as many bits
|
|
||||||
* as what was requested.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -324,7 +354,7 @@ xmesa_choose_z_stencil_format(int depthBits, int stencilBits,
|
||||||
/***** Linked list of XMesaBuffers *****/
|
/***** Linked list of XMesaBuffers *****/
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
XMesaBuffer XMesaBufferList = NULL;
|
static XMesaBuffer XMesaBufferList = NULL;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -342,13 +372,15 @@ static XMesaBuffer
|
||||||
create_xmesa_buffer(Drawable d, BufferType type,
|
create_xmesa_buffer(Drawable d, BufferType type,
|
||||||
XMesaVisual vis, Colormap cmap)
|
XMesaVisual vis, Colormap cmap)
|
||||||
{
|
{
|
||||||
|
XMesaDisplay xmdpy = xmesa_init_display(vis->display);
|
||||||
XMesaBuffer b;
|
XMesaBuffer b;
|
||||||
GLframebuffer *fb;
|
|
||||||
enum pipe_format colorFormat, depthFormat, stencilFormat;
|
|
||||||
uint width, height;
|
uint width, height;
|
||||||
|
|
||||||
ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
|
ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
|
||||||
|
|
||||||
|
if (!xmdpy)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
|
b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
|
||||||
if (!b)
|
if (!b)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -361,24 +393,12 @@ create_xmesa_buffer(Drawable d, BufferType type,
|
||||||
b->type = type;
|
b->type = type;
|
||||||
b->cmap = cmap;
|
b->cmap = cmap;
|
||||||
|
|
||||||
/* determine PIPE_FORMATs for buffers */
|
|
||||||
colorFormat = choose_pixel_format(vis);
|
|
||||||
|
|
||||||
xmesa_choose_z_stencil_format(vis->mesa_visual.depthBits,
|
|
||||||
vis->mesa_visual.stencilBits,
|
|
||||||
&depthFormat, &stencilFormat);
|
|
||||||
|
|
||||||
|
|
||||||
get_drawable_size(vis->display, d, &width, &height);
|
get_drawable_size(vis->display, d, &width, &height);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create framebuffer, but we'll plug in our own renderbuffers below.
|
* Create framebuffer, but we'll plug in our own renderbuffers below.
|
||||||
*/
|
*/
|
||||||
b->stfb = st_create_framebuffer(&vis->mesa_visual,
|
b->stfb = xmesa_create_st_framebuffer(xmdpy, b);
|
||||||
colorFormat, depthFormat, stencilFormat,
|
|
||||||
width, height,
|
|
||||||
(void *) b);
|
|
||||||
fb = &b->stfb->Base;
|
|
||||||
|
|
||||||
/* GLX_EXT_texture_from_pixmap */
|
/* GLX_EXT_texture_from_pixmap */
|
||||||
b->TextureTarget = 0;
|
b->TextureTarget = 0;
|
||||||
|
|
@ -422,24 +442,21 @@ xmesa_free_buffer(XMesaBuffer buffer)
|
||||||
|
|
||||||
for (b = XMesaBufferList; b; b = b->Next) {
|
for (b = XMesaBufferList; b; b = b->Next) {
|
||||||
if (b == buffer) {
|
if (b == buffer) {
|
||||||
struct gl_framebuffer *fb = &buffer->stfb->Base;
|
|
||||||
|
|
||||||
/* unlink buffer from list */
|
/* unlink buffer from list */
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->Next = buffer->Next;
|
prev->Next = buffer->Next;
|
||||||
else
|
else
|
||||||
XMesaBufferList = buffer->Next;
|
XMesaBufferList = buffer->Next;
|
||||||
|
|
||||||
/* mark as delete pending */
|
|
||||||
fb->DeletePending = GL_TRUE;
|
|
||||||
|
|
||||||
/* Since the X window for the XMesaBuffer is going away, we don't
|
/* Since the X window for the XMesaBuffer is going away, we don't
|
||||||
* want to dereference this pointer in the future.
|
* want to dereference this pointer in the future.
|
||||||
*/
|
*/
|
||||||
b->ws.drawable = 0;
|
b->ws.drawable = 0;
|
||||||
|
|
||||||
/* Unreference. If count = zero we'll really delete the buffer */
|
/* XXX we should move the buffer to a delete-pending list and destroy
|
||||||
_mesa_reference_framebuffer(&fb, NULL);
|
* the buffer until it is no longer current.
|
||||||
|
*/
|
||||||
|
xmesa_destroy_st_framebuffer(buffer->stfb);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
|
|
@ -596,10 +613,12 @@ XMesaVisual XMesaCreateVisual( Display *display,
|
||||||
GLint level,
|
GLint level,
|
||||||
GLint visualCaveat )
|
GLint visualCaveat )
|
||||||
{
|
{
|
||||||
|
XMesaDisplay xmdpy = xmesa_init_display(display);
|
||||||
XMesaVisual v;
|
XMesaVisual v;
|
||||||
GLint red_bits, green_bits, blue_bits, alpha_bits;
|
GLint red_bits, green_bits, blue_bits, alpha_bits;
|
||||||
|
|
||||||
xmesa_init( display );
|
if (!xmdpy)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* For debugging only */
|
/* For debugging only */
|
||||||
if (_mesa_getenv("MESA_XSYNC")) {
|
if (_mesa_getenv("MESA_XSYNC")) {
|
||||||
|
|
@ -681,6 +700,26 @@ XMesaVisual XMesaCreateVisual( Display *display,
|
||||||
accum_blue_size, accum_alpha_size,
|
accum_blue_size, accum_alpha_size,
|
||||||
0 );
|
0 );
|
||||||
|
|
||||||
|
v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
|
||||||
|
if (db_flag)
|
||||||
|
v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
|
||||||
|
if (stereo_flag) {
|
||||||
|
v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
|
||||||
|
if (db_flag)
|
||||||
|
v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->stvis.color_format = choose_pixel_format(v);
|
||||||
|
v->stvis.depth_stencil_format =
|
||||||
|
choose_depth_stencil_format(xmdpy, depth_size, stencil_size);
|
||||||
|
|
||||||
|
v->stvis.accum_format = (accum_red_size +
|
||||||
|
accum_green_size + accum_blue_size + accum_alpha_size) ?
|
||||||
|
PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
|
||||||
|
|
||||||
|
v->stvis.samples = num_samples;
|
||||||
|
v->stvis.render_buffer = ST_ATTACHMENT_INVALID;
|
||||||
|
|
||||||
/* XXX minor hack */
|
/* XXX minor hack */
|
||||||
v->mesa_visual.level = level;
|
v->mesa_visual.level = level;
|
||||||
return v;
|
return v;
|
||||||
|
|
@ -696,17 +735,12 @@ void XMesaDestroyVisual( XMesaVisual v )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do one-time initializations.
|
* Do per-display initializations.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmesa_init( Display *display )
|
xmesa_init( Display *display )
|
||||||
{
|
{
|
||||||
static GLboolean firstTime = GL_TRUE;
|
xmesa_init_display(display);
|
||||||
if (firstTime) {
|
|
||||||
pipe_mutex_init(_xmesa_lock);
|
|
||||||
screen = driver.create_pipe_screen( display );
|
|
||||||
firstTime = GL_FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -720,51 +754,33 @@ xmesa_init( Display *display )
|
||||||
PUBLIC
|
PUBLIC
|
||||||
XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
|
XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
|
||||||
{
|
{
|
||||||
struct pipe_context *pipe = NULL;
|
XMesaDisplay xmdpy = xmesa_init_display(v->display);
|
||||||
XMesaContext c;
|
XMesaContext c;
|
||||||
GLcontext *mesaCtx;
|
|
||||||
uint pf;
|
|
||||||
|
|
||||||
xmesa_init( v->display );
|
if (!xmdpy)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
|
/* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
|
||||||
c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
|
c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
|
||||||
if (!c)
|
if (!c)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pf = choose_pixel_format(v);
|
|
||||||
assert(pf);
|
|
||||||
|
|
||||||
c->xm_visual = v;
|
c->xm_visual = v;
|
||||||
c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
|
c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
|
||||||
c->xm_read_buffer = NULL;
|
c->xm_read_buffer = NULL;
|
||||||
|
|
||||||
if (screen == NULL)
|
c->st = stapi->create_context(stapi, xmdpy->smapi,
|
||||||
goto fail;
|
&v->stvis, (share_list) ? share_list->st : NULL);
|
||||||
|
|
||||||
/* Trace screen knows how to properly wrap context creation in the
|
|
||||||
* wrapped screen, so nothing special to do here:
|
|
||||||
*/
|
|
||||||
pipe = screen->context_create(screen, (void *) c);
|
|
||||||
if (pipe == NULL)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
c->st = st_create_context(pipe,
|
|
||||||
&v->mesa_visual,
|
|
||||||
share_list ? share_list->st : NULL);
|
|
||||||
if (c->st == NULL)
|
if (c->st == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
mesaCtx = c->st->ctx;
|
c->st->st_manager_private = (void *) c;
|
||||||
c->st->ctx->DriverCtx = c;
|
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (c->st)
|
if (c->st)
|
||||||
st_destroy_context(c->st);
|
c->st->destroy(c->st);
|
||||||
else if (pipe)
|
|
||||||
pipe->destroy(pipe);
|
|
||||||
|
|
||||||
free(c);
|
free(c);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -775,7 +791,7 @@ fail:
|
||||||
PUBLIC
|
PUBLIC
|
||||||
void XMesaDestroyContext( XMesaContext c )
|
void XMesaDestroyContext( XMesaContext c )
|
||||||
{
|
{
|
||||||
st_destroy_context(c->st);
|
c->st->destroy(c->st);
|
||||||
|
|
||||||
/* FIXME: We should destroy the screen here, but if we do so, surfaces may
|
/* FIXME: We should destroy the screen here, but if we do so, surfaces may
|
||||||
* outlive it, causing segfaults
|
* outlive it, causing segfaults
|
||||||
|
|
@ -881,7 +897,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
|
||||||
{
|
{
|
||||||
GET_CURRENT_CONTEXT(ctx);
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
XMesaBuffer b;
|
XMesaBuffer b;
|
||||||
GLuint width, height;
|
|
||||||
|
|
||||||
assert(v);
|
assert(v);
|
||||||
|
|
||||||
|
|
@ -889,19 +904,18 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
|
||||||
if (!b)
|
if (!b)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* get pixmap size, update framebuffer/renderbuffer dims */
|
/* get pixmap size */
|
||||||
xmesa_get_window_size(v->display, b, &width, &height);
|
xmesa_get_window_size(v->display, b, &b->width, &b->height);
|
||||||
_mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
|
|
||||||
|
|
||||||
if (target == 0) {
|
if (target == 0) {
|
||||||
/* examine dims */
|
/* examine dims */
|
||||||
if (ctx->Extensions.ARB_texture_non_power_of_two) {
|
if (ctx->Extensions.ARB_texture_non_power_of_two) {
|
||||||
target = GLX_TEXTURE_2D_EXT;
|
target = GLX_TEXTURE_2D_EXT;
|
||||||
}
|
}
|
||||||
else if ( _mesa_bitcount(width) == 1
|
else if ( _mesa_bitcount(b->width) == 1
|
||||||
&& _mesa_bitcount(height) == 1) {
|
&& _mesa_bitcount(b->height) == 1) {
|
||||||
/* power of two size */
|
/* power of two size */
|
||||||
if (height == 1) {
|
if (b->height == 1) {
|
||||||
target = GLX_TEXTURE_1D_EXT;
|
target = GLX_TEXTURE_1D_EXT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -974,25 +988,22 @@ XMesaDestroyBuffer(XMesaBuffer b)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the current window size and update the corresponding GLframebuffer
|
* Query the current drawable size and notify the binding context.
|
||||||
* and all attached renderbuffers.
|
|
||||||
* Called when:
|
|
||||||
* 1. the first time a buffer is bound to a context.
|
|
||||||
* 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too...
|
|
||||||
* Note: it's possible (and legal) for xmctx to be NULL. That can happen
|
|
||||||
* when resizing a buffer when no rendering context is bound.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
|
xmesa_check_buffer_size(XMesaBuffer b)
|
||||||
{
|
{
|
||||||
GLuint width, height;
|
XMesaContext xmctx = XMesaGetCurrentContext();
|
||||||
xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
|
|
||||||
st_resize_framebuffer(drawBuffer->stfb, width, height);
|
if (b->type == PBUFFER)
|
||||||
|
return;
|
||||||
|
|
||||||
|
xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height);
|
||||||
|
if (xmctx && xmctx->xm_buffer == b)
|
||||||
|
xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bind buffer b to context c and make c the current rendering context.
|
* Bind buffer b to context c and make c the current rendering context.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1017,22 +1028,21 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
|
||||||
c->xm_read_buffer == readBuffer)
|
c->xm_read_buffer == readBuffer)
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
|
|
||||||
|
xmesa_check_buffer_size(drawBuffer);
|
||||||
|
if (readBuffer != drawBuffer)
|
||||||
|
xmesa_check_buffer_size(readBuffer);
|
||||||
|
|
||||||
c->xm_buffer = drawBuffer;
|
c->xm_buffer = drawBuffer;
|
||||||
c->xm_read_buffer = readBuffer;
|
c->xm_read_buffer = readBuffer;
|
||||||
|
|
||||||
st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb,
|
stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb);
|
||||||
&drawBuffer->ws);
|
|
||||||
|
|
||||||
xmesa_check_and_update_buffer_size(c, drawBuffer);
|
|
||||||
if (readBuffer != drawBuffer)
|
|
||||||
xmesa_check_and_update_buffer_size(c, readBuffer);
|
|
||||||
|
|
||||||
/* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
|
/* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
|
||||||
drawBuffer->wasCurrent = GL_TRUE;
|
drawBuffer->wasCurrent = GL_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Detach */
|
/* Detach */
|
||||||
st_make_current( NULL, NULL, NULL, NULL );
|
stapi->make_current(stapi, NULL, NULL, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
|
|
@ -1051,14 +1061,8 @@ GLboolean XMesaUnbindContext( XMesaContext c )
|
||||||
|
|
||||||
XMesaContext XMesaGetCurrentContext( void )
|
XMesaContext XMesaGetCurrentContext( void )
|
||||||
{
|
{
|
||||||
GET_CURRENT_CONTEXT(ctx);
|
struct st_context_iface *st = stapi->get_current(stapi);
|
||||||
if (ctx) {
|
return (XMesaContext) (st) ? st->st_manager_private : NULL;
|
||||||
XMesaContext xmesa = xmesa_context(ctx);
|
|
||||||
return xmesa;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1070,17 +1074,17 @@ XMesaContext XMesaGetCurrentContext( void )
|
||||||
PUBLIC
|
PUBLIC
|
||||||
void XMesaSwapBuffers( XMesaBuffer b )
|
void XMesaSwapBuffers( XMesaBuffer b )
|
||||||
{
|
{
|
||||||
struct pipe_surface *frontLeftSurf;
|
XMesaContext xmctx = XMesaGetCurrentContext();
|
||||||
|
|
||||||
st_swapbuffers(b->stfb, &frontLeftSurf, NULL);
|
if (xmctx && xmctx->xm_buffer == b) {
|
||||||
|
xmctx->st->flush( xmctx->st,
|
||||||
if (frontLeftSurf) {
|
PIPE_FLUSH_RENDER_CACHE |
|
||||||
screen->flush_frontbuffer( screen,
|
PIPE_FLUSH_SWAPBUFFERS |
|
||||||
frontLeftSurf,
|
PIPE_FLUSH_FRAME,
|
||||||
&b->ws );
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
xmesa_check_and_update_buffer_size(NULL, b);
|
xmesa_swap_st_framebuffer(b->stfb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1090,21 +1094,9 @@ void XMesaSwapBuffers( XMesaBuffer b )
|
||||||
*/
|
*/
|
||||||
void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
|
void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
|
||||||
{
|
{
|
||||||
struct pipe_surface *surf_front;
|
xmesa_copy_st_framebuffer(b->stfb,
|
||||||
struct pipe_surface *surf_back;
|
ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT,
|
||||||
struct pipe_context *pipe = NULL; /* XXX fix */
|
x, y, width, height);
|
||||||
|
|
||||||
st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front);
|
|
||||||
st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back);
|
|
||||||
|
|
||||||
if (!surf_front || !surf_back)
|
|
||||||
return;
|
|
||||||
|
|
||||||
assert(pipe);
|
|
||||||
pipe->surface_copy(pipe,
|
|
||||||
surf_front, x, y, /* dest */
|
|
||||||
surf_back, x, y, /* src */
|
|
||||||
width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1112,7 +1104,14 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
|
||||||
void XMesaFlush( XMesaContext c )
|
void XMesaFlush( XMesaContext c )
|
||||||
{
|
{
|
||||||
if (c && c->xm_visual->display) {
|
if (c && c->xm_visual->display) {
|
||||||
st_finish(c->st);
|
XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
|
||||||
|
struct pipe_fence_handle *fence = NULL;
|
||||||
|
|
||||||
|
c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
|
||||||
|
if (fence) {
|
||||||
|
xmdpy->screen->fence_finish(xmdpy->screen, fence, 0);
|
||||||
|
xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
|
||||||
|
}
|
||||||
XSync( c->xm_visual->display, False );
|
XSync( c->xm_visual->display, False );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1186,3 +1185,10 @@ XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask)
|
||||||
|
{
|
||||||
|
if (dst->st->copy)
|
||||||
|
dst->st->copy(dst->st, src->st, mask);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,7 @@ and create a window, you must do the following to use the X/Mesa interface:
|
||||||
|
|
||||||
|
|
||||||
#include "main/mtypes.h"
|
#include "main/mtypes.h"
|
||||||
#include "state_tracker/st_context.h"
|
#include "state_tracker/st_api.h"
|
||||||
#include "state_tracker/st_public.h"
|
|
||||||
#include "os/os_thread.h"
|
#include "os/os_thread.h"
|
||||||
|
|
||||||
#include "state_tracker/xlib_sw_winsys.h"
|
#include "state_tracker/xlib_sw_winsys.h"
|
||||||
|
|
@ -68,11 +67,22 @@ and create a window, you must do the following to use the X/Mesa interface:
|
||||||
# include <X11/Xlibint.h>
|
# include <X11/Xlibint.h>
|
||||||
# include <X11/Xutil.h>
|
# include <X11/Xutil.h>
|
||||||
|
|
||||||
|
typedef struct xmesa_display *XMesaDisplay;
|
||||||
typedef struct xmesa_buffer *XMesaBuffer;
|
typedef struct xmesa_buffer *XMesaBuffer;
|
||||||
typedef struct xmesa_context *XMesaContext;
|
typedef struct xmesa_context *XMesaContext;
|
||||||
typedef struct xmesa_visual *XMesaVisual;
|
typedef struct xmesa_visual *XMesaVisual;
|
||||||
|
|
||||||
|
|
||||||
|
struct xmesa_display {
|
||||||
|
pipe_mutex mutex;
|
||||||
|
|
||||||
|
Display *display;
|
||||||
|
struct pipe_screen *screen;
|
||||||
|
struct st_manager *smapi;
|
||||||
|
|
||||||
|
struct pipe_context *pipe;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new X/Mesa visual.
|
* Create a new X/Mesa visual.
|
||||||
|
|
@ -258,16 +268,13 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
|
||||||
int format, int target, int mipmap);
|
int format, int target, int mipmap);
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask);
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern pipe_mutex _xmesa_lock;
|
|
||||||
|
|
||||||
extern struct xmesa_buffer *XMesaBufferList;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visual inforation, derived from GLvisual.
|
* Visual inforation, derived from GLvisual.
|
||||||
* Basically corresponds to an XVisualInfo.
|
* Basically corresponds to an XVisualInfo.
|
||||||
|
|
@ -280,6 +287,8 @@ struct xmesa_visual {
|
||||||
GLint BitsPerPixel; /* True bits per pixel for XImages */
|
GLint BitsPerPixel; /* True bits per pixel for XImages */
|
||||||
|
|
||||||
GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */
|
GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */
|
||||||
|
|
||||||
|
struct st_visual stvis;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -288,7 +297,7 @@ struct xmesa_visual {
|
||||||
* Basically corresponds to a GLXContext.
|
* Basically corresponds to a GLXContext.
|
||||||
*/
|
*/
|
||||||
struct xmesa_context {
|
struct xmesa_context {
|
||||||
struct st_context *st;
|
struct st_context_iface *st;
|
||||||
XMesaVisual xm_visual; /** pixel format info */
|
XMesaVisual xm_visual; /** pixel format info */
|
||||||
XMesaBuffer xm_buffer; /** current drawbuffer */
|
XMesaBuffer xm_buffer; /** current drawbuffer */
|
||||||
XMesaBuffer xm_read_buffer; /** current readbuffer */
|
XMesaBuffer xm_read_buffer; /** current readbuffer */
|
||||||
|
|
@ -311,7 +320,7 @@ typedef enum {
|
||||||
* Basically corresponds to a GLXDrawable.
|
* Basically corresponds to a GLXDrawable.
|
||||||
*/
|
*/
|
||||||
struct xmesa_buffer {
|
struct xmesa_buffer {
|
||||||
struct st_framebuffer *stfb;
|
struct st_framebuffer_iface *stfb;
|
||||||
struct xlib_drawable ws;
|
struct xlib_drawable ws;
|
||||||
|
|
||||||
GLboolean wasCurrent; /* was ever the current buffer? */
|
GLboolean wasCurrent; /* was ever the current buffer? */
|
||||||
|
|
@ -335,33 +344,15 @@ struct xmesa_buffer {
|
||||||
GLint TextureMipmap; /** 0 or 1 */
|
GLint TextureMipmap; /** 0 or 1 */
|
||||||
|
|
||||||
struct xmesa_buffer *Next; /* Linked list pointer: */
|
struct xmesa_buffer *Next; /* Linked list pointer: */
|
||||||
|
|
||||||
|
unsigned width, height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** cast wrapper */
|
|
||||||
static INLINE XMesaContext
|
|
||||||
xmesa_context(GLcontext *ctx)
|
|
||||||
{
|
|
||||||
return (XMesaContext) ctx->DriverCtx;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** cast wrapper */
|
|
||||||
static INLINE XMesaBuffer
|
|
||||||
xmesa_buffer(GLframebuffer *fb)
|
|
||||||
{
|
|
||||||
struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
|
|
||||||
return (XMesaBuffer) st_framebuffer_private(stfb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
xmesa_init(Display *dpy);
|
xmesa_init(Display *dpy);
|
||||||
|
|
||||||
extern void
|
|
||||||
xmesa_delete_framebuffer(struct gl_framebuffer *fb);
|
|
||||||
|
|
||||||
extern XMesaBuffer
|
extern XMesaBuffer
|
||||||
xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis);
|
xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis);
|
||||||
|
|
||||||
|
|
@ -370,7 +361,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b,
|
||||||
GLuint *width, GLuint *height);
|
GLuint *width, GLuint *height);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer);
|
xmesa_check_buffer_size(XMesaBuffer b);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
xmesa_destroy_buffers_on_display(Display *dpy);
|
xmesa_destroy_buffers_on_display(Display *dpy);
|
||||||
|
|
@ -378,13 +369,13 @@ xmesa_destroy_buffers_on_display(Display *dpy);
|
||||||
static INLINE GLuint
|
static INLINE GLuint
|
||||||
xmesa_buffer_width(XMesaBuffer b)
|
xmesa_buffer_width(XMesaBuffer b)
|
||||||
{
|
{
|
||||||
return b->stfb->Base.Width;
|
return b->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE GLuint
|
static INLINE GLuint
|
||||||
xmesa_buffer_height(XMesaBuffer b)
|
xmesa_buffer_height(XMesaBuffer b)
|
||||||
{
|
{
|
||||||
return b->stfb->Base.Height;
|
return b->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,19 +26,23 @@
|
||||||
*
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef XM_WINSYS_H
|
#ifndef XM_PUBLIC_H
|
||||||
#define XM_WINSYS_H
|
#define XM_PUBLIC_H
|
||||||
|
|
||||||
struct xm_driver;
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
struct pipe_screen;
|
||||||
|
struct st_api;
|
||||||
|
|
||||||
/* This is the driver interface required by the glx/xlib state tracker.
|
/* This is the driver interface required by the glx/xlib state tracker.
|
||||||
*/
|
*/
|
||||||
struct xm_driver {
|
struct xm_driver {
|
||||||
struct pipe_screen *(*create_pipe_screen)( Display *display );
|
struct pipe_screen *(*create_pipe_screen)( Display *display );
|
||||||
|
struct st_api *(*create_st_api)( void );
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
xmesa_set_driver( const struct xm_driver *driver );
|
xmesa_set_driver( const struct xm_driver *driver );
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif /* XM_PUBLIC_H */
|
||||||
|
|
|
||||||
332
src/gallium/state_trackers/glx/xlib/xm_st.c
Normal file
332
src/gallium/state_trackers/glx/xlib/xm_st.c
Normal file
|
|
@ -0,0 +1,332 @@
|
||||||
|
/*
|
||||||
|
* Mesa 3-D graphics library
|
||||||
|
* Version: 7.9
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 LunarG Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
|
||||||
|
#include "xm_api.h"
|
||||||
|
#include "xm_st.h"
|
||||||
|
|
||||||
|
struct xmesa_st_framebuffer {
|
||||||
|
XMesaDisplay display;
|
||||||
|
XMesaBuffer buffer;
|
||||||
|
struct pipe_screen *screen;
|
||||||
|
|
||||||
|
struct st_visual stvis;
|
||||||
|
|
||||||
|
unsigned texture_width, texture_height, texture_mask;
|
||||||
|
struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
|
||||||
|
|
||||||
|
struct pipe_surface *display_surface;
|
||||||
|
};
|
||||||
|
|
||||||
|
static INLINE struct xmesa_st_framebuffer *
|
||||||
|
xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi)
|
||||||
|
{
|
||||||
|
return (struct xmesa_st_framebuffer *) stfbi->st_manager_private;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display an attachment to the xlib_drawable of the framebuffer.
|
||||||
|
*/
|
||||||
|
static boolean
|
||||||
|
xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi,
|
||||||
|
enum st_attachment_type statt)
|
||||||
|
{
|
||||||
|
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||||
|
struct pipe_texture *ptex = xstfb->textures[statt];
|
||||||
|
struct pipe_surface *psurf;
|
||||||
|
|
||||||
|
if (!ptex)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
psurf = xstfb->display_surface;
|
||||||
|
/* (re)allocate the surface for the texture to be displayed */
|
||||||
|
if (!psurf || psurf->texture != ptex) {
|
||||||
|
pipe_surface_reference(&xstfb->display_surface, NULL);
|
||||||
|
|
||||||
|
psurf = xstfb->screen->get_tex_surface(xstfb->screen,
|
||||||
|
ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ);
|
||||||
|
if (!psurf)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
xstfb->display_surface = psurf;
|
||||||
|
}
|
||||||
|
|
||||||
|
xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the contents between the attachments.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi,
|
||||||
|
enum st_attachment_type src_statt,
|
||||||
|
enum st_attachment_type dst_statt,
|
||||||
|
unsigned x, unsigned y,
|
||||||
|
unsigned width, unsigned height)
|
||||||
|
{
|
||||||
|
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||||
|
struct pipe_texture *src_ptex = xstfb->textures[src_statt];
|
||||||
|
struct pipe_texture *dst_ptex = xstfb->textures[dst_statt];
|
||||||
|
struct pipe_surface *src, *dst;
|
||||||
|
struct pipe_context *pipe;
|
||||||
|
|
||||||
|
if (!src_ptex || !dst_ptex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pipe = xstfb->display->pipe;
|
||||||
|
if (!pipe) {
|
||||||
|
pipe = xstfb->screen->context_create(xstfb->screen, NULL);
|
||||||
|
if (!pipe)
|
||||||
|
return;
|
||||||
|
xstfb->display->pipe = pipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = xstfb->screen->get_tex_surface(xstfb->screen,
|
||||||
|
src_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
|
||||||
|
dst = xstfb->screen->get_tex_surface(xstfb->screen,
|
||||||
|
dst_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||||
|
|
||||||
|
if (src && dst)
|
||||||
|
pipe->surface_copy(pipe, dst, x, y, src, x, y, width, height);
|
||||||
|
|
||||||
|
pipe_surface_reference(&src, NULL);
|
||||||
|
pipe_surface_reference(&dst, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove outdated textures and create the requested ones.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
|
||||||
|
unsigned width, unsigned height,
|
||||||
|
unsigned mask)
|
||||||
|
{
|
||||||
|
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||||
|
struct pipe_texture templ;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
/* remove outdated textures */
|
||||||
|
if (xstfb->texture_width != width || xstfb->texture_height != height) {
|
||||||
|
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
|
||||||
|
pipe_texture_reference(&xstfb->textures[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&templ, 0, sizeof(templ));
|
||||||
|
templ.target = PIPE_TEXTURE_2D;
|
||||||
|
templ.width0 = width;
|
||||||
|
templ.height0 = height;
|
||||||
|
templ.depth0 = 1;
|
||||||
|
templ.last_level = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
|
||||||
|
enum pipe_format format;
|
||||||
|
unsigned tex_usage;
|
||||||
|
|
||||||
|
/* the texture already exists or not requested */
|
||||||
|
if (xstfb->textures[i] || !(mask & (1 << i))) {
|
||||||
|
/* remember the texture */
|
||||||
|
if (xstfb->textures[i])
|
||||||
|
mask |= (1 << i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case ST_ATTACHMENT_FRONT_LEFT:
|
||||||
|
case ST_ATTACHMENT_BACK_LEFT:
|
||||||
|
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||||
|
case ST_ATTACHMENT_BACK_RIGHT:
|
||||||
|
format = xstfb->stvis.color_format;
|
||||||
|
tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
|
||||||
|
PIPE_TEXTURE_USAGE_RENDER_TARGET;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_DEPTH_STENCIL:
|
||||||
|
format = xstfb->stvis.depth_stencil_format;
|
||||||
|
tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
format = PIPE_FORMAT_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format != PIPE_FORMAT_NONE) {
|
||||||
|
templ.format = format;
|
||||||
|
templ.tex_usage = tex_usage;
|
||||||
|
|
||||||
|
xstfb->textures[i] =
|
||||||
|
xstfb->screen->texture_create(xstfb->screen, &templ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xstfb->texture_width = width;
|
||||||
|
xstfb->texture_height = height;
|
||||||
|
xstfb->texture_mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
|
||||||
|
const enum st_attachment_type *statts,
|
||||||
|
unsigned count,
|
||||||
|
struct pipe_texture **out)
|
||||||
|
{
|
||||||
|
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||||
|
unsigned statt_mask, new_mask, i;
|
||||||
|
boolean resized;
|
||||||
|
|
||||||
|
statt_mask = 0x0;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
statt_mask |= 1 << statts[i];
|
||||||
|
/* record newly allocated textures */
|
||||||
|
new_mask = statt_mask & ~xstfb->texture_mask;
|
||||||
|
|
||||||
|
resized = (xstfb->buffer->width != xstfb->texture_width ||
|
||||||
|
xstfb->buffer->height != xstfb->texture_height);
|
||||||
|
|
||||||
|
/* revalidate textures */
|
||||||
|
if (resized || new_mask) {
|
||||||
|
xmesa_st_framebuffer_validate_textures(stfbi,
|
||||||
|
xstfb->buffer->width, xstfb->buffer->height, statt_mask);
|
||||||
|
|
||||||
|
if (!resized) {
|
||||||
|
enum st_attachment_type back, front;
|
||||||
|
|
||||||
|
back = ST_ATTACHMENT_BACK_LEFT;
|
||||||
|
front = ST_ATTACHMENT_FRONT_LEFT;
|
||||||
|
/* copy the contents if front is newly allocated and back is not */
|
||||||
|
if ((statt_mask & (1 << back)) &&
|
||||||
|
(new_mask & (1 << front)) &&
|
||||||
|
!(new_mask & (1 << back))) {
|
||||||
|
xmesa_st_framebuffer_copy_textures(stfbi, back, front,
|
||||||
|
0, 0, xstfb->texture_width, xstfb->texture_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
out[i] = NULL;
|
||||||
|
pipe_texture_reference(&out[i], xstfb->textures[statts[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
|
||||||
|
enum st_attachment_type statt)
|
||||||
|
{
|
||||||
|
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||||
|
boolean ret;
|
||||||
|
|
||||||
|
ret = xmesa_st_framebuffer_display(stfbi, statt);
|
||||||
|
if (ret)
|
||||||
|
xmesa_check_buffer_size(xstfb->buffer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st_framebuffer_iface *
|
||||||
|
xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b)
|
||||||
|
{
|
||||||
|
struct st_framebuffer_iface *stfbi;
|
||||||
|
struct xmesa_st_framebuffer *xstfb;
|
||||||
|
|
||||||
|
assert(xmdpy->display == b->xm_visual->display);
|
||||||
|
|
||||||
|
stfbi = CALLOC_STRUCT(st_framebuffer_iface);
|
||||||
|
xstfb = CALLOC_STRUCT(xmesa_st_framebuffer);
|
||||||
|
if (!stfbi || !xstfb) {
|
||||||
|
if (stfbi)
|
||||||
|
FREE(stfbi);
|
||||||
|
if (xstfb)
|
||||||
|
FREE(xstfb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xstfb->display = xmdpy;
|
||||||
|
xstfb->buffer = b;
|
||||||
|
xstfb->screen = xmdpy->screen;
|
||||||
|
xstfb->stvis = b->xm_visual->stvis;
|
||||||
|
|
||||||
|
stfbi->visual = &xstfb->stvis;
|
||||||
|
stfbi->flush_front = xmesa_st_framebuffer_flush_front;
|
||||||
|
stfbi->validate = xmesa_st_framebuffer_validate;
|
||||||
|
stfbi->st_manager_private = (void *) xstfb;
|
||||||
|
|
||||||
|
return stfbi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
|
||||||
|
{
|
||||||
|
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pipe_surface_reference(&xstfb->display_surface, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
|
||||||
|
pipe_texture_reference(&xstfb->textures[i], NULL);
|
||||||
|
|
||||||
|
FREE(xstfb);
|
||||||
|
FREE(stfbi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi)
|
||||||
|
{
|
||||||
|
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||||
|
boolean ret;
|
||||||
|
|
||||||
|
ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT);
|
||||||
|
if (ret) {
|
||||||
|
struct pipe_texture **front, **back, *tmp;
|
||||||
|
|
||||||
|
front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT];
|
||||||
|
back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT];
|
||||||
|
/* swap textures only if the front texture has been allocated */
|
||||||
|
if (*front) {
|
||||||
|
tmp = *front;
|
||||||
|
*front = *back;
|
||||||
|
*back = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmesa_check_buffer_size(xstfb->buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
|
||||||
|
enum st_attachment_type src,
|
||||||
|
enum st_attachment_type dst,
|
||||||
|
int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h);
|
||||||
|
if (dst == ST_ATTACHMENT_FRONT_LEFT)
|
||||||
|
xmesa_st_framebuffer_display(stfbi, dst);
|
||||||
|
}
|
||||||
51
src/gallium/state_trackers/glx/xlib/xm_st.h
Normal file
51
src/gallium/state_trackers/glx/xlib/xm_st.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Mesa 3-D graphics library
|
||||||
|
* Version: 7.9
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 LunarG Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _XM_ST_H_
|
||||||
|
#define _XM_ST_H_
|
||||||
|
|
||||||
|
#include "pipe/p_compiler.h"
|
||||||
|
#include "state_tracker/st_api.h"
|
||||||
|
|
||||||
|
#include "xm_api.h"
|
||||||
|
|
||||||
|
struct st_framebuffer_iface *
|
||||||
|
xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b);
|
||||||
|
|
||||||
|
void
|
||||||
|
xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
|
||||||
|
|
||||||
|
void
|
||||||
|
xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi);
|
||||||
|
|
||||||
|
void
|
||||||
|
xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
|
||||||
|
enum st_attachment_type src,
|
||||||
|
enum st_attachment_type dst,
|
||||||
|
int x, int y, int w, int h);
|
||||||
|
|
||||||
|
#endif /* _XM_ST_H_ */
|
||||||
|
|
@ -25,6 +25,7 @@ VG_SOURCES = \
|
||||||
api_transform.c \
|
api_transform.c \
|
||||||
vgu.c \
|
vgu.c \
|
||||||
vg_context.c \
|
vg_context.c \
|
||||||
|
vg_manager.c \
|
||||||
vg_state.c \
|
vg_state.c \
|
||||||
vg_tracker.c \
|
vg_tracker.c \
|
||||||
vg_translate.c \
|
vg_translate.c \
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "VG/openvg.h"
|
#include "VG/openvg.h"
|
||||||
|
|
||||||
|
#include "vg_manager.h"
|
||||||
#include "vg_context.h"
|
#include "vg_context.h"
|
||||||
|
|
||||||
#include "pipe/p_context.h"
|
#include "pipe/p_context.h"
|
||||||
|
|
@ -55,6 +56,8 @@ void vgFlush(void)
|
||||||
|
|
||||||
pipe = ctx->pipe;
|
pipe = ctx->pipe;
|
||||||
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
|
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
|
||||||
|
|
||||||
|
vg_manager_flush_frontbuffer(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vgFinish(void)
|
void vgFinish(void)
|
||||||
|
|
|
||||||
|
|
@ -117,10 +117,6 @@ clear_with_quad(struct vg_context *st, float x0, float y0,
|
||||||
x1, y1);
|
x1, y1);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (st->pipe->screen && st->pipe->screen->update_buffer)
|
|
||||||
st->pipe->screen->update_buffer( st->pipe->screen,
|
|
||||||
st->pipe->priv );
|
|
||||||
|
|
||||||
cso_save_blend(st->cso_context);
|
cso_save_blend(st->cso_context);
|
||||||
cso_save_rasterizer(st->cso_context);
|
cso_save_rasterizer(st->cso_context);
|
||||||
cso_save_fragment_shader(st->cso_context);
|
cso_save_fragment_shader(st->cso_context);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "asm_util.h"
|
#include "asm_util.h"
|
||||||
#include "st_inlines.h"
|
#include "st_inlines.h"
|
||||||
|
#include "vg_manager.h"
|
||||||
|
|
||||||
#include "pipe/p_context.h"
|
#include "pipe/p_context.h"
|
||||||
#include "util/u_inlines.h"
|
#include "util/u_inlines.h"
|
||||||
|
|
@ -305,6 +306,8 @@ static void update_clip_state(struct vg_context *ctx)
|
||||||
|
|
||||||
void vg_validate_state(struct vg_context *ctx)
|
void vg_validate_state(struct vg_context *ctx)
|
||||||
{
|
{
|
||||||
|
vg_manager_validate_framebuffer(ctx);
|
||||||
|
|
||||||
if ((ctx->state.dirty & BLEND_DIRTY)) {
|
if ((ctx->state.dirty & BLEND_DIRTY)) {
|
||||||
struct pipe_blend_state *blend = &ctx->state.g3d.blend;
|
struct pipe_blend_state *blend = &ctx->state.g3d.blend;
|
||||||
memset(blend, 0, sizeof(struct pipe_blend_state));
|
memset(blend, 0, sizeof(struct pipe_blend_state));
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
#include "pipe/p_state.h"
|
#include "pipe/p_state.h"
|
||||||
#include "util/u_pointer.h"
|
#include "util/u_pointer.h"
|
||||||
#include "util/u_math.h"
|
#include "util/u_math.h"
|
||||||
|
#include "state_tracker/st_api.h"
|
||||||
|
|
||||||
#include "cso_cache/cso_hash.h"
|
#include "cso_cache/cso_hash.h"
|
||||||
#include "cso_cache/cso_context.h"
|
#include "cso_cache/cso_context.h"
|
||||||
|
|
@ -58,6 +59,9 @@ struct st_framebuffer {
|
||||||
|
|
||||||
struct pipe_texture *blend_texture;
|
struct pipe_texture *blend_texture;
|
||||||
|
|
||||||
|
struct st_framebuffer_iface *iface;
|
||||||
|
enum st_attachment_type strb_att;
|
||||||
|
|
||||||
void *privateData;
|
void *privateData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -84,6 +88,8 @@ enum dirty_state {
|
||||||
|
|
||||||
struct vg_context
|
struct vg_context
|
||||||
{
|
{
|
||||||
|
struct st_context_iface iface;
|
||||||
|
|
||||||
struct pipe_context *pipe;
|
struct pipe_context *pipe;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -101,6 +107,7 @@ struct vg_context
|
||||||
VGErrorCode _error;
|
VGErrorCode _error;
|
||||||
|
|
||||||
struct st_framebuffer *draw_buffer;
|
struct st_framebuffer *draw_buffer;
|
||||||
|
int32_t draw_buffer_invalid;
|
||||||
|
|
||||||
struct cso_hash *owned_objects[VG_OBJECT_LAST];
|
struct cso_hash *owned_objects[VG_OBJECT_LAST];
|
||||||
|
|
||||||
|
|
|
||||||
373
src/gallium/state_trackers/vega/vg_manager.c
Normal file
373
src/gallium/state_trackers/vega/vg_manager.c
Normal file
|
|
@ -0,0 +1,373 @@
|
||||||
|
/*
|
||||||
|
* Mesa 3-D graphics library
|
||||||
|
* Version: 7.9
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 LunarG Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "state_tracker/st_api.h"
|
||||||
|
|
||||||
|
#include "pipe/p_context.h"
|
||||||
|
#include "pipe/p_screen.h"
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
|
||||||
|
#include "vg_manager.h"
|
||||||
|
#include "vg_context.h"
|
||||||
|
#include "vg_tracker.h" /* for st_resize_framebuffer */
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush the front buffer if the current context renders to the front buffer.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vg_manager_flush_frontbuffer(struct vg_context *ctx)
|
||||||
|
{
|
||||||
|
struct st_framebuffer *stfb = ctx->draw_buffer;
|
||||||
|
|
||||||
|
if (!stfb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* st_public.h is used */
|
||||||
|
if (!stfb->iface) {
|
||||||
|
struct pipe_screen *screen = ctx->pipe->screen;
|
||||||
|
if (screen->flush_frontbuffer) {
|
||||||
|
screen->flush_frontbuffer(screen,
|
||||||
|
stfb->strb->surface, ctx->pipe->priv);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (stfb->strb_att) {
|
||||||
|
case ST_ATTACHMENT_FRONT_LEFT:
|
||||||
|
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||||
|
stfb->iface->flush_front(stfb->iface, stfb->strb_att);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-validate the framebuffer.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vg_manager_validate_framebuffer(struct vg_context *ctx)
|
||||||
|
{
|
||||||
|
struct pipe_screen *screen = ctx->pipe->screen;
|
||||||
|
struct st_framebuffer *stfb = ctx->draw_buffer;
|
||||||
|
struct st_renderbuffer *rb;
|
||||||
|
struct pipe_texture *pt;
|
||||||
|
|
||||||
|
/* no binding surface */
|
||||||
|
if (!stfb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* st_public.h is used */
|
||||||
|
if (!stfb->iface) {
|
||||||
|
struct pipe_screen *screen = ctx->pipe->screen;
|
||||||
|
if (screen->update_buffer)
|
||||||
|
screen->update_buffer(screen, ctx->pipe->priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p_atomic_read(&ctx->draw_buffer_invalid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* validate the fb */
|
||||||
|
if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb = stfb->strb;
|
||||||
|
if (rb->texture == pt) {
|
||||||
|
pipe_texture_reference(&pt, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unreference existing ones */
|
||||||
|
pipe_surface_reference(&rb->surface, NULL);
|
||||||
|
pipe_texture_reference(&rb->texture, NULL);
|
||||||
|
|
||||||
|
rb->texture = pt;
|
||||||
|
rb->surface = screen->get_tex_surface(screen, rb->texture, 0, 0, 0,
|
||||||
|
PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||||
|
|
||||||
|
rb->width = rb->surface->width;
|
||||||
|
rb->height = rb->surface->height;
|
||||||
|
|
||||||
|
st_resize_framebuffer(stfb, rb->width, rb->height);
|
||||||
|
|
||||||
|
p_atomic_set(&ctx->draw_buffer_invalid, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
vg_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
|
||||||
|
struct st_framebuffer_iface *stfbi)
|
||||||
|
{
|
||||||
|
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||||
|
p_atomic_set(&ctx->draw_buffer_invalid, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vg_context_flush(struct st_context_iface *stctxi, unsigned flags,
|
||||||
|
struct pipe_fence_handle **fence)
|
||||||
|
{
|
||||||
|
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||||
|
ctx->pipe->flush(ctx->pipe, flags, fence);
|
||||||
|
if (flags & PIPE_FLUSH_RENDER_CACHE)
|
||||||
|
vg_manager_flush_frontbuffer(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vg_context_destroy(struct st_context_iface *stctxi)
|
||||||
|
{
|
||||||
|
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||||
|
vg_destroy_context(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct st_context_iface *
|
||||||
|
vg_api_create_context(struct st_api *stapi, struct st_manager *smapi,
|
||||||
|
const struct st_visual *visual,
|
||||||
|
struct st_context_iface *shared_stctxi)
|
||||||
|
{
|
||||||
|
struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi;
|
||||||
|
struct vg_context *ctx;
|
||||||
|
struct pipe_context *pipe;
|
||||||
|
|
||||||
|
pipe = smapi->screen->context_create(smapi->screen, NULL);
|
||||||
|
if (!pipe)
|
||||||
|
return NULL;
|
||||||
|
ctx = vg_create_context(pipe, NULL, shared_ctx);
|
||||||
|
if (!ctx) {
|
||||||
|
pipe->destroy(pipe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->iface.destroy = vg_context_destroy;
|
||||||
|
|
||||||
|
ctx->iface.notify_invalid_framebuffer =
|
||||||
|
vg_context_notify_invalid_framebuffer;
|
||||||
|
ctx->iface.flush = vg_context_flush;
|
||||||
|
|
||||||
|
ctx->iface.teximage = NULL;
|
||||||
|
ctx->iface.copy = NULL;
|
||||||
|
|
||||||
|
ctx->iface.st_context_private = (void *) smapi;
|
||||||
|
|
||||||
|
return &ctx->iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct st_renderbuffer *
|
||||||
|
create_renderbuffer(enum pipe_format format)
|
||||||
|
{
|
||||||
|
struct st_renderbuffer *strb;
|
||||||
|
|
||||||
|
strb = CALLOC_STRUCT(st_renderbuffer);
|
||||||
|
if (strb)
|
||||||
|
strb->format = format;
|
||||||
|
|
||||||
|
return strb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_renderbuffer(struct st_renderbuffer *strb)
|
||||||
|
{
|
||||||
|
pipe_surface_reference(&strb->surface, NULL);
|
||||||
|
pipe_texture_reference(&strb->texture, NULL);
|
||||||
|
free(strb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decide the buffer to render to.
|
||||||
|
*/
|
||||||
|
static enum st_attachment_type
|
||||||
|
choose_attachment(struct st_framebuffer_iface *stfbi)
|
||||||
|
{
|
||||||
|
enum st_attachment_type statt;
|
||||||
|
|
||||||
|
statt = stfbi->visual->render_buffer;
|
||||||
|
if (statt != ST_ATTACHMENT_INVALID) {
|
||||||
|
/* use the buffer given by the visual, unless it is unavailable */
|
||||||
|
if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) {
|
||||||
|
switch (statt) {
|
||||||
|
case ST_ATTACHMENT_BACK_LEFT:
|
||||||
|
statt = ST_ATTACHMENT_FRONT_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_RIGHT:
|
||||||
|
statt = ST_ATTACHMENT_FRONT_RIGHT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!st_visual_have_buffers(stfbi->visual, 1 << statt))
|
||||||
|
statt = ST_ATTACHMENT_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return statt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind the context to the given framebuffers.
|
||||||
|
*/
|
||||||
|
static boolean
|
||||||
|
vg_context_bind_framebuffers(struct st_context_iface *stctxi,
|
||||||
|
struct st_framebuffer_iface *stdrawi,
|
||||||
|
struct st_framebuffer_iface *streadi)
|
||||||
|
{
|
||||||
|
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||||
|
struct st_framebuffer *stfb;
|
||||||
|
enum st_attachment_type strb_att;
|
||||||
|
|
||||||
|
/* the draw and read framebuffers must be the same */
|
||||||
|
if (stdrawi != streadi)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
p_atomic_set(&ctx->draw_buffer_invalid, TRUE);
|
||||||
|
|
||||||
|
strb_att = (stdrawi) ? choose_attachment(stdrawi) : ST_ATTACHMENT_INVALID;
|
||||||
|
|
||||||
|
if (ctx->draw_buffer) {
|
||||||
|
stfb = ctx->draw_buffer;
|
||||||
|
|
||||||
|
/* free the existing fb */
|
||||||
|
if (!stdrawi ||
|
||||||
|
stfb->strb_att != strb_att ||
|
||||||
|
stfb->strb->format != stdrawi->visual->color_format ||
|
||||||
|
stfb->dsrb->format != stdrawi->visual->depth_stencil_format) {
|
||||||
|
destroy_renderbuffer(stfb->strb);
|
||||||
|
destroy_renderbuffer(stfb->dsrb);
|
||||||
|
free(stfb);
|
||||||
|
|
||||||
|
ctx->draw_buffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stdrawi)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (strb_att == ST_ATTACHMENT_INVALID)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* create a new fb */
|
||||||
|
if (!ctx->draw_buffer) {
|
||||||
|
stfb = CALLOC_STRUCT(st_framebuffer);
|
||||||
|
if (!stfb)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
stfb->strb = create_renderbuffer(stdrawi->visual->color_format);
|
||||||
|
if (!stfb->strb) {
|
||||||
|
free(stfb);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
stfb->dsrb = create_renderbuffer(stdrawi->visual->depth_stencil_format);
|
||||||
|
if (!stfb->dsrb) {
|
||||||
|
free(stfb->strb);
|
||||||
|
free(stfb);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
stfb->width = 0;
|
||||||
|
stfb->height = 0;
|
||||||
|
stfb->strb_att = strb_att;
|
||||||
|
|
||||||
|
ctx->draw_buffer = stfb;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->draw_buffer->iface = stdrawi;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
vg_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
|
||||||
|
struct st_framebuffer_iface *stdrawi,
|
||||||
|
struct st_framebuffer_iface *streadi)
|
||||||
|
{
|
||||||
|
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||||
|
|
||||||
|
if (stctxi)
|
||||||
|
vg_context_bind_framebuffers(stctxi, stdrawi, streadi);
|
||||||
|
vg_set_current_context(ctx);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct st_context_iface *
|
||||||
|
vg_api_get_current(struct st_api *stapi)
|
||||||
|
{
|
||||||
|
struct vg_context *ctx = vg_current_context();
|
||||||
|
|
||||||
|
return (ctx) ? &ctx->iface : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
vg_api_is_visual_supported(struct st_api *stapi,
|
||||||
|
const struct st_visual *visual)
|
||||||
|
{
|
||||||
|
/* the impl requires a depth/stencil buffer */
|
||||||
|
if (visual->depth_stencil_format == PIPE_FORMAT_NONE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static st_proc_t
|
||||||
|
vg_api_get_proc_address(struct st_api *stapi, const char *procname)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return (st_proc_t) NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vg_api_destroy(struct st_api *stapi)
|
||||||
|
{
|
||||||
|
free(stapi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct st_api *
|
||||||
|
vg_module_create_api(void)
|
||||||
|
{
|
||||||
|
struct st_api *stapi;
|
||||||
|
|
||||||
|
stapi = CALLOC_STRUCT(st_api);
|
||||||
|
if (stapi) {
|
||||||
|
stapi->destroy = vg_api_destroy;
|
||||||
|
stapi->get_proc_address = vg_api_get_proc_address;
|
||||||
|
stapi->is_visual_supported = vg_api_is_visual_supported;
|
||||||
|
|
||||||
|
stapi->create_context = vg_api_create_context;
|
||||||
|
stapi->make_current = vg_api_make_current;
|
||||||
|
stapi->get_current = vg_api_get_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stapi;
|
||||||
|
}
|
||||||
|
|
||||||
|
PUBLIC const struct st_module st_module_OpenVG = {
|
||||||
|
.api = ST_API_OPENVG,
|
||||||
|
.create_api = vg_module_create_api,
|
||||||
|
};
|
||||||
40
src/gallium/state_trackers/vega/vg_manager.h
Normal file
40
src/gallium/state_trackers/vega/vg_manager.h
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Mesa 3-D graphics library
|
||||||
|
* Version: 7.9
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 LunarG Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VG_MANAGER_H
|
||||||
|
#define VG_MANAGER_H
|
||||||
|
|
||||||
|
#include "state_tracker/st_api.h"
|
||||||
|
#include "vg_context.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
vg_manager_flush_frontbuffer(struct vg_context *ctx);
|
||||||
|
|
||||||
|
void
|
||||||
|
vg_manager_validate_framebuffer(struct vg_context *ctx);
|
||||||
|
|
||||||
|
#endif /* VG_MANAGER_H */
|
||||||
|
|
@ -39,9 +39,15 @@
|
||||||
#include "target-helpers/wrap_screen.h"
|
#include "target-helpers/wrap_screen.h"
|
||||||
#include "xm_public.h"
|
#include "xm_public.h"
|
||||||
|
|
||||||
|
#include "state_tracker/st_manager.h"
|
||||||
|
|
||||||
/* advertise OpenGL support */
|
/* advertise OpenGL support */
|
||||||
PUBLIC const int st_api_OpenGL = 1;
|
PUBLIC const int st_api_OpenGL = 1;
|
||||||
|
|
||||||
|
PUBLIC const struct st_module st_module_OpenGL = {
|
||||||
|
.api = ST_API_OPENGL,
|
||||||
|
.create_api = st_manager_create_api
|
||||||
|
};
|
||||||
|
|
||||||
/* Helper function to build a subset of a driver stack consisting of
|
/* Helper function to build a subset of a driver stack consisting of
|
||||||
* one of the software rasterizers (cell, llvmpipe, softpipe) and the
|
* one of the software rasterizers (cell, llvmpipe, softpipe) and the
|
||||||
|
|
@ -81,8 +87,10 @@ swrast_xlib_create_screen( Display *display )
|
||||||
screen = llvmpipe_create_screen( winsys );
|
screen = llvmpipe_create_screen( winsys );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(GALLIUM_SOFTPIPE)
|
||||||
if (screen == NULL)
|
if (screen == NULL)
|
||||||
screen = softpipe_create_screen( winsys );
|
screen = softpipe_create_screen( winsys );
|
||||||
|
#endif
|
||||||
|
|
||||||
if (screen == NULL)
|
if (screen == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -98,9 +106,10 @@ fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xm_driver xlib_driver =
|
static struct xm_driver xlib_driver =
|
||||||
{
|
{
|
||||||
.create_pipe_screen = swrast_xlib_create_screen,
|
.create_pipe_screen = swrast_xlib_create_screen,
|
||||||
|
.create_st_api = st_manager_create_api,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
TOP = ../../../..
|
TOP = ../../../..
|
||||||
include $(TOP)/configs/current
|
include $(TOP)/configs/current
|
||||||
|
|
||||||
SUBDIRS = $(GALLIUM_WINSYS_DRM_DIRS)
|
SUBDIRS = sw $(GALLIUM_WINSYS_DRM_DIRS)
|
||||||
|
|
||||||
default install clean:
|
default install clean:
|
||||||
@for dir in $(SUBDIRS) ; do \
|
@for dir in $(SUBDIRS) ; do \
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ PIPE_DRIVERS = \
|
||||||
$(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
|
$(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
|
||||||
$(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \
|
$(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \
|
||||||
$(TOP)/src/gallium/drivers/trace/libtrace.a \
|
$(TOP)/src/gallium/drivers/trace/libtrace.a \
|
||||||
|
$(TOP)/src/gallium/winsys/drm/sw/libswdrm.a \
|
||||||
$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
|
$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
|
||||||
$(TOP)/src/gallium/drivers/identity/libidentity.a \
|
$(TOP)/src/gallium/drivers/identity/libidentity.a \
|
||||||
$(TOP)/src/gallium/drivers/i965/libi965.a
|
$(TOP)/src/gallium/drivers/i965/libi965.a
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include "trace/tr_drm.h"
|
#include "trace/tr_drm.h"
|
||||||
|
|
||||||
|
#include "../../sw/sw_drm_api.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper functions
|
* Helper functions
|
||||||
*/
|
*/
|
||||||
|
|
@ -108,5 +110,13 @@ struct drm_api i965_libdrm_api =
|
||||||
struct drm_api *
|
struct drm_api *
|
||||||
drm_api_create()
|
drm_api_create()
|
||||||
{
|
{
|
||||||
return trace_drm_create(&i965_libdrm_api);
|
struct drm_api *api = NULL;
|
||||||
|
|
||||||
|
if (api == NULL && debug_get_bool_option("BRW_SOFTPIPE", FALSE))
|
||||||
|
api = sw_drm_api_create(&i965_libdrm_api);
|
||||||
|
|
||||||
|
if (api == NULL)
|
||||||
|
api = &i965_libdrm_api;
|
||||||
|
|
||||||
|
return trace_drm_create(api);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
src/gallium/winsys/drm/sw/Makefile
Normal file
14
src/gallium/winsys/drm/sw/Makefile
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
TOP = ../../../../..
|
||||||
|
include $(TOP)/configs/current
|
||||||
|
|
||||||
|
LIBNAME = swdrm
|
||||||
|
|
||||||
|
C_SOURCES = \
|
||||||
|
wrapper_sw_winsys.c \
|
||||||
|
sw_drm_api.c
|
||||||
|
|
||||||
|
LIBRARY_INCLUDES =
|
||||||
|
|
||||||
|
LIBRARY_DEFINES =
|
||||||
|
|
||||||
|
include ../../../Makefile.template
|
||||||
97
src/gallium/winsys/drm/sw/sw_drm_api.c
Normal file
97
src/gallium/winsys/drm/sw/sw_drm_api.c
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
/**********************************************************
|
||||||
|
* Copyright 2010 VMware, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "softpipe/sp_public.h"
|
||||||
|
#include "state_tracker/drm_api.h"
|
||||||
|
#include "wrapper_sw_winsys.h"
|
||||||
|
#include "sw_drm_api.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct sw_drm_api
|
||||||
|
{
|
||||||
|
struct drm_api base;
|
||||||
|
struct drm_api *api;
|
||||||
|
struct sw_winsys *sw;
|
||||||
|
};
|
||||||
|
|
||||||
|
static INLINE struct sw_drm_api *
|
||||||
|
sw_drm_api(struct drm_api *api)
|
||||||
|
{
|
||||||
|
return (struct sw_drm_api *)api;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exported functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static struct pipe_screen *
|
||||||
|
sw_drm_create_screen(struct drm_api *_api, int drmFD,
|
||||||
|
struct drm_create_screen_arg *arg)
|
||||||
|
{
|
||||||
|
struct sw_drm_api *swapi = sw_drm_api(_api);
|
||||||
|
struct drm_api *api = swapi->api;
|
||||||
|
struct sw_winsys *sww;
|
||||||
|
struct pipe_screen *screen;
|
||||||
|
|
||||||
|
screen = api->create_screen(api, drmFD, arg);
|
||||||
|
|
||||||
|
sww = wrapper_sw_winsys_warp_pipe_screen(screen);
|
||||||
|
|
||||||
|
return softpipe_create_screen(sww);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sw_drm_destroy(struct drm_api *api)
|
||||||
|
{
|
||||||
|
struct sw_drm_api *swapi = sw_drm_api(api);
|
||||||
|
if (swapi->api->destroy)
|
||||||
|
swapi->api->destroy(swapi->api);
|
||||||
|
|
||||||
|
FREE(swapi);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drm_api *
|
||||||
|
sw_drm_api_create(struct drm_api *api)
|
||||||
|
{
|
||||||
|
struct sw_drm_api *swapi = CALLOC_STRUCT(sw_drm_api);
|
||||||
|
|
||||||
|
swapi->base.name = "sw";
|
||||||
|
swapi->base.driver_name = api->driver_name;
|
||||||
|
swapi->base.create_screen = sw_drm_create_screen;
|
||||||
|
swapi->base.destroy = sw_drm_destroy;
|
||||||
|
|
||||||
|
swapi->api = api;
|
||||||
|
|
||||||
|
return &swapi->base;
|
||||||
|
}
|
||||||
34
src/gallium/winsys/drm/sw/sw_drm_api.h
Normal file
34
src/gallium/winsys/drm/sw/sw_drm_api.h
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**********************************************************
|
||||||
|
* Copyright 2010 VMware, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SW_DRM_API_H
|
||||||
|
#define SW_DRM_API_H
|
||||||
|
|
||||||
|
struct drm_api;
|
||||||
|
|
||||||
|
struct drm_api * sw_drm_api_create(struct drm_api *api);
|
||||||
|
|
||||||
|
#endif
|
||||||
282
src/gallium/winsys/drm/sw/wrapper_sw_winsys.c
Normal file
282
src/gallium/winsys/drm/sw/wrapper_sw_winsys.c
Normal file
|
|
@ -0,0 +1,282 @@
|
||||||
|
/**********************************************************
|
||||||
|
* Copyright 2010 VMware, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "wrapper_sw_winsys.h"
|
||||||
|
|
||||||
|
#include "pipe/p_format.h"
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
#include "state_tracker/sw_winsys.h"
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code wraps a pipe_screen and exposes a sw_winsys interface for use
|
||||||
|
* with software resterizers. This code is used by the DRM based winsys to
|
||||||
|
* allow access to the drm driver.
|
||||||
|
*
|
||||||
|
* We must borrow the whole stack because only the pipe screen knows how
|
||||||
|
* to decode the content of a buffer. Or how to create a buffer that
|
||||||
|
* can still be used by drivers using real hardware (as the case is
|
||||||
|
* with software st/xorg but hw st/dri).
|
||||||
|
*
|
||||||
|
* We also need a pipe context for the transfers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct wrapper_sw_winsys
|
||||||
|
{
|
||||||
|
struct sw_winsys base;
|
||||||
|
struct pipe_screen *screen;
|
||||||
|
struct pipe_context *pipe;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wrapper_sw_displaytarget
|
||||||
|
{
|
||||||
|
struct wrapper_sw_winsys *winsys;
|
||||||
|
struct pipe_texture *tex;
|
||||||
|
struct pipe_transfer *transfer;
|
||||||
|
|
||||||
|
unsigned width;
|
||||||
|
unsigned height;
|
||||||
|
unsigned map_count;
|
||||||
|
unsigned stride; /**< because we give stride at create */
|
||||||
|
void *ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static INLINE struct wrapper_sw_winsys *
|
||||||
|
wrapper_sw_winsys(struct sw_winsys *ws)
|
||||||
|
{
|
||||||
|
return (struct wrapper_sw_winsys *)ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE struct wrapper_sw_displaytarget *
|
||||||
|
wrapper_sw_displaytarget(struct sw_displaytarget *dt)
|
||||||
|
{
|
||||||
|
return (struct wrapper_sw_displaytarget *)dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride)
|
||||||
|
{
|
||||||
|
struct pipe_context *pipe = wdt->winsys->pipe;
|
||||||
|
struct pipe_texture *tex = wdt->tex;
|
||||||
|
struct pipe_transfer *tr;
|
||||||
|
|
||||||
|
tr = pipe->get_tex_transfer(pipe, tex, 0, 0, 0,
|
||||||
|
PIPE_TRANSFER_READ_WRITE,
|
||||||
|
0, 0, wdt->width, wdt->height);
|
||||||
|
if (!tr)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*stride = tr->stride;
|
||||||
|
wdt->stride = tr->stride;
|
||||||
|
|
||||||
|
pipe->tex_transfer_destroy(pipe, tr);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sw_displaytarget *
|
||||||
|
wsw_dt_wrap_texture(struct wrapper_sw_winsys *wsw,
|
||||||
|
struct pipe_texture *tex, unsigned *stride)
|
||||||
|
{
|
||||||
|
struct wrapper_sw_displaytarget *wdt = CALLOC_STRUCT(wrapper_sw_displaytarget);
|
||||||
|
if (!wdt)
|
||||||
|
goto err_unref;
|
||||||
|
|
||||||
|
wdt->tex = tex;
|
||||||
|
wdt->winsys = wsw;
|
||||||
|
|
||||||
|
if (!wsw_dt_get_stride(wdt, stride))
|
||||||
|
goto err_free;
|
||||||
|
|
||||||
|
return (struct sw_displaytarget *)wdt;
|
||||||
|
|
||||||
|
err_free:
|
||||||
|
FREE(wdt);
|
||||||
|
err_unref:
|
||||||
|
pipe_texture_reference(&tex, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sw_displaytarget *
|
||||||
|
wsw_dt_create(struct sw_winsys *ws,
|
||||||
|
unsigned tex_usage,
|
||||||
|
enum pipe_format format,
|
||||||
|
unsigned width, unsigned height,
|
||||||
|
unsigned alignment,
|
||||||
|
unsigned *stride)
|
||||||
|
{
|
||||||
|
struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
|
||||||
|
struct pipe_texture templ;
|
||||||
|
struct pipe_texture *tex;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Why don't we just get the template.
|
||||||
|
*/
|
||||||
|
memset(&templ, 0, sizeof(templ));
|
||||||
|
templ.width0 = width;
|
||||||
|
templ.height0 = height;
|
||||||
|
templ.format = format;
|
||||||
|
templ.tex_usage = tex_usage;
|
||||||
|
|
||||||
|
/* XXX alignment: we can't do anything about this */
|
||||||
|
|
||||||
|
tex = wsw->screen->texture_create(wsw->screen, &templ);
|
||||||
|
if (!tex)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return wsw_dt_wrap_texture(wsw, tex, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sw_displaytarget *
|
||||||
|
wsw_dt_from_handle(struct sw_winsys *ws,
|
||||||
|
const struct pipe_texture *templ,
|
||||||
|
struct winsys_handle *whandle,
|
||||||
|
unsigned *stride)
|
||||||
|
{
|
||||||
|
struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
|
||||||
|
struct pipe_texture *tex;
|
||||||
|
|
||||||
|
tex = wsw->screen->texture_from_handle(wsw->screen, templ, whandle);
|
||||||
|
if (!tex)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return wsw_dt_wrap_texture(wsw, tex, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
wsw_dt_map(struct sw_winsys *ws,
|
||||||
|
struct sw_displaytarget *dt,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
|
||||||
|
struct pipe_context *pipe = wdt->winsys->pipe;
|
||||||
|
struct pipe_texture *tex = wdt->tex;
|
||||||
|
struct pipe_transfer *tr;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
if (!wdt->map_count) {
|
||||||
|
|
||||||
|
assert(!wdt->transfer);
|
||||||
|
|
||||||
|
tr = pipe->get_tex_transfer(pipe, tex, 0, 0, 0,
|
||||||
|
PIPE_TRANSFER_READ_WRITE,
|
||||||
|
0, 0, wdt->width, wdt->height);
|
||||||
|
if (!tr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ptr = pipe->transfer_map(pipe, tr);
|
||||||
|
if (!ptr)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
wdt->transfer = tr;
|
||||||
|
wdt->ptr = ptr;
|
||||||
|
|
||||||
|
/* XXX Handle this case */
|
||||||
|
assert(tr->stride == wdt->stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
wdt->map_count++;
|
||||||
|
|
||||||
|
return wdt->ptr;
|
||||||
|
|
||||||
|
err:
|
||||||
|
pipe->tex_transfer_destroy(pipe, tr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wsw_dt_unmap(struct sw_winsys *ws,
|
||||||
|
struct sw_displaytarget *dt)
|
||||||
|
{
|
||||||
|
struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
|
||||||
|
struct pipe_context *pipe = wdt->winsys->pipe;
|
||||||
|
|
||||||
|
assert(wdt->transfer);
|
||||||
|
|
||||||
|
wdt->map_count--;
|
||||||
|
|
||||||
|
if (wdt->map_count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pipe->transfer_unmap(pipe, wdt->transfer);
|
||||||
|
pipe->tex_transfer_destroy(pipe, wdt->transfer);
|
||||||
|
wdt->transfer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wsw_dt_destroy(struct sw_winsys *ws,
|
||||||
|
struct sw_displaytarget *dt)
|
||||||
|
{
|
||||||
|
struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
|
||||||
|
|
||||||
|
pipe_texture_reference(&wdt->tex, NULL);
|
||||||
|
|
||||||
|
FREE(wdt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wsw_destroy(struct sw_winsys *ws)
|
||||||
|
{
|
||||||
|
struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
|
||||||
|
|
||||||
|
wsw->pipe->destroy(wsw->pipe);
|
||||||
|
wsw->screen->destroy(wsw->screen);
|
||||||
|
|
||||||
|
FREE(wsw);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sw_winsys *
|
||||||
|
wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen)
|
||||||
|
{
|
||||||
|
struct wrapper_sw_winsys *wsw = CALLOC_STRUCT(wrapper_sw_winsys);
|
||||||
|
|
||||||
|
wsw->base.displaytarget_create = wsw_dt_create;
|
||||||
|
wsw->base.displaytarget_from_handle = wsw_dt_from_handle;
|
||||||
|
wsw->base.displaytarget_map = wsw_dt_map;
|
||||||
|
wsw->base.displaytarget_unmap = wsw_dt_unmap;
|
||||||
|
wsw->base.displaytarget_destroy = wsw_dt_destroy;
|
||||||
|
wsw->base.destroy = wsw_destroy;
|
||||||
|
|
||||||
|
wsw->screen = screen;
|
||||||
|
wsw->pipe = screen->context_create(screen, NULL);
|
||||||
|
if (!wsw->pipe)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return &wsw->base;
|
||||||
|
|
||||||
|
err:
|
||||||
|
FREE(wsw);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
35
src/gallium/winsys/drm/sw/wrapper_sw_winsys.h
Normal file
35
src/gallium/winsys/drm/sw/wrapper_sw_winsys.h
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**********************************************************
|
||||||
|
* Copyright 2010 VMware, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WRAPPER_SW_WINSYS
|
||||||
|
#define WRAPPER_SW_WINSYS
|
||||||
|
|
||||||
|
struct sw_winsys;
|
||||||
|
struct pipe_screen;
|
||||||
|
|
||||||
|
struct sw_winsys *wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -71,6 +71,7 @@ gdi_sw_displaytarget( struct sw_displaytarget *buf )
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
gdi_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
|
gdi_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
|
||||||
|
unsigned tex_usage,
|
||||||
enum pipe_format format )
|
enum pipe_format format )
|
||||||
{
|
{
|
||||||
switch(format) {
|
switch(format) {
|
||||||
|
|
@ -119,6 +120,7 @@ gdi_sw_displaytarget_destroy(struct sw_winsys *winsys,
|
||||||
|
|
||||||
static struct sw_displaytarget *
|
static struct sw_displaytarget *
|
||||||
gdi_sw_displaytarget_create(struct sw_winsys *winsys,
|
gdi_sw_displaytarget_create(struct sw_winsys *winsys,
|
||||||
|
unsigned tex_usage,
|
||||||
enum pipe_format format,
|
enum pipe_format format,
|
||||||
unsigned width, unsigned height,
|
unsigned width, unsigned height,
|
||||||
unsigned alignment,
|
unsigned alignment,
|
||||||
|
|
@ -168,6 +170,27 @@ no_gdt:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct sw_displaytarget *
|
||||||
|
gdi_sw_displaytarget_from_handle(struct sw_winsys *winsys,
|
||||||
|
const struct pipe_texture *templet,
|
||||||
|
struct winsys_handle *whandle,
|
||||||
|
unsigned *stride)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
gdi_sw_displaytarget_get_handle(struct sw_winsys *winsys,
|
||||||
|
struct sw_displaytarget *dt,
|
||||||
|
struct winsys_handle *whandle)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gdi_sw_display( struct sw_winsys *winsys,
|
gdi_sw_display( struct sw_winsys *winsys,
|
||||||
struct sw_displaytarget *dt,
|
struct sw_displaytarget *dt,
|
||||||
|
|
@ -212,6 +235,8 @@ gdi_create_sw_winsys(void)
|
||||||
winsys->destroy = gdi_sw_destroy;
|
winsys->destroy = gdi_sw_destroy;
|
||||||
winsys->is_displaytarget_format_supported = gdi_sw_is_displaytarget_format_supported;
|
winsys->is_displaytarget_format_supported = gdi_sw_is_displaytarget_format_supported;
|
||||||
winsys->displaytarget_create = gdi_sw_displaytarget_create;
|
winsys->displaytarget_create = gdi_sw_displaytarget_create;
|
||||||
|
winsys->displaytarget_from_handle = gdi_sw_displaytarget_from_handle;
|
||||||
|
winsys->displaytarget_get_handle = gdi_sw_displaytarget_get_handle;
|
||||||
winsys->displaytarget_map = gdi_sw_displaytarget_map;
|
winsys->displaytarget_map = gdi_sw_displaytarget_map;
|
||||||
winsys->displaytarget_unmap = gdi_sw_displaytarget_unmap;
|
winsys->displaytarget_unmap = gdi_sw_displaytarget_unmap;
|
||||||
winsys->displaytarget_display = gdi_sw_displaytarget_display;
|
winsys->displaytarget_display = gdi_sw_displaytarget_display;
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
null_sw_is_displaytarget_format_supported(struct sw_winsys *ws,
|
null_sw_is_displaytarget_format_supported(struct sw_winsys *ws,
|
||||||
|
unsigned tex_usage,
|
||||||
enum pipe_format format )
|
enum pipe_format format )
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
@ -78,6 +79,7 @@ null_sw_displaytarget_destroy(struct sw_winsys *winsys,
|
||||||
|
|
||||||
static struct sw_displaytarget *
|
static struct sw_displaytarget *
|
||||||
null_sw_displaytarget_create(struct sw_winsys *winsys,
|
null_sw_displaytarget_create(struct sw_winsys *winsys,
|
||||||
|
unsigned tex_usage,
|
||||||
enum pipe_format format,
|
enum pipe_format format,
|
||||||
unsigned width, unsigned height,
|
unsigned width, unsigned height,
|
||||||
unsigned alignment,
|
unsigned alignment,
|
||||||
|
|
@ -87,6 +89,26 @@ null_sw_displaytarget_create(struct sw_winsys *winsys,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct sw_displaytarget *
|
||||||
|
null_sw_displaytarget_from_handle(struct sw_winsys *winsys,
|
||||||
|
const struct pipe_texture *templet,
|
||||||
|
struct winsys_handle *whandle,
|
||||||
|
unsigned *stride)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
null_sw_displaytarget_get_handle(struct sw_winsys *winsys,
|
||||||
|
struct sw_displaytarget *dt,
|
||||||
|
struct winsys_handle *whandle)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
null_sw_displaytarget_display(struct sw_winsys *winsys,
|
null_sw_displaytarget_display(struct sw_winsys *winsys,
|
||||||
struct sw_displaytarget *dt,
|
struct sw_displaytarget *dt,
|
||||||
|
|
@ -115,6 +137,8 @@ null_sw_create(void)
|
||||||
winsys->destroy = null_sw_destroy;
|
winsys->destroy = null_sw_destroy;
|
||||||
winsys->is_displaytarget_format_supported = null_sw_is_displaytarget_format_supported;
|
winsys->is_displaytarget_format_supported = null_sw_is_displaytarget_format_supported;
|
||||||
winsys->displaytarget_create = null_sw_displaytarget_create;
|
winsys->displaytarget_create = null_sw_displaytarget_create;
|
||||||
|
winsys->displaytarget_from_handle = null_sw_displaytarget_from_handle;
|
||||||
|
winsys->displaytarget_get_handle = null_sw_displaytarget_get_handle;
|
||||||
winsys->displaytarget_map = null_sw_displaytarget_map;
|
winsys->displaytarget_map = null_sw_displaytarget_map;
|
||||||
winsys->displaytarget_unmap = null_sw_displaytarget_unmap;
|
winsys->displaytarget_unmap = null_sw_displaytarget_unmap;
|
||||||
winsys->displaytarget_display = null_sw_displaytarget_display;
|
winsys->displaytarget_display = null_sw_displaytarget_display;
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,7 @@ alloc_ximage(struct xm_displaytarget *xm_dt,
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
xm_is_displaytarget_format_supported( struct sw_winsys *ws,
|
xm_is_displaytarget_format_supported( struct sw_winsys *ws,
|
||||||
|
unsigned tex_usage,
|
||||||
enum pipe_format format )
|
enum pipe_format format )
|
||||||
{
|
{
|
||||||
/* TODO: check visuals or other sensible thing here */
|
/* TODO: check visuals or other sensible thing here */
|
||||||
|
|
@ -358,6 +359,7 @@ xm_displaytarget_display(struct sw_winsys *ws,
|
||||||
|
|
||||||
static struct sw_displaytarget *
|
static struct sw_displaytarget *
|
||||||
xm_displaytarget_create(struct sw_winsys *winsys,
|
xm_displaytarget_create(struct sw_winsys *winsys,
|
||||||
|
unsigned tex_usage,
|
||||||
enum pipe_format format,
|
enum pipe_format format,
|
||||||
unsigned width, unsigned height,
|
unsigned width, unsigned height,
|
||||||
unsigned alignment,
|
unsigned alignment,
|
||||||
|
|
@ -406,6 +408,27 @@ no_xm_dt:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct sw_displaytarget *
|
||||||
|
xm_displaytarget_from_handle(struct sw_winsys *winsys,
|
||||||
|
const struct pipe_texture *templet,
|
||||||
|
struct winsys_handle *whandle,
|
||||||
|
unsigned *stride)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
xm_displaytarget_get_handle(struct sw_winsys *winsys,
|
||||||
|
struct sw_displaytarget *dt,
|
||||||
|
struct winsys_handle *whandle)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xm_destroy( struct sw_winsys *ws )
|
xm_destroy( struct sw_winsys *ws )
|
||||||
{
|
{
|
||||||
|
|
@ -428,6 +451,8 @@ xlib_create_sw_winsys( Display *display )
|
||||||
ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported;
|
ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported;
|
||||||
|
|
||||||
ws->base.displaytarget_create = xm_displaytarget_create;
|
ws->base.displaytarget_create = xm_displaytarget_create;
|
||||||
|
ws->base.displaytarget_from_handle = xm_displaytarget_from_handle;
|
||||||
|
ws->base.displaytarget_get_handle = xm_displaytarget_get_handle;
|
||||||
ws->base.displaytarget_map = xm_displaytarget_map;
|
ws->base.displaytarget_map = xm_displaytarget_map;
|
||||||
ws->base.displaytarget_unmap = xm_displaytarget_unmap;
|
ws->base.displaytarget_unmap = xm_displaytarget_unmap;
|
||||||
ws->base.displaytarget_destroy = xm_displaytarget_destroy;
|
ws->base.displaytarget_destroy = xm_displaytarget_destroy;
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,7 @@ if env['platform'] != 'winddk':
|
||||||
'state_tracker/st_format.c',
|
'state_tracker/st_format.c',
|
||||||
'state_tracker/st_framebuffer.c',
|
'state_tracker/st_framebuffer.c',
|
||||||
'state_tracker/st_gen_mipmap.c',
|
'state_tracker/st_gen_mipmap.c',
|
||||||
|
'state_tracker/st_manager.c',
|
||||||
'state_tracker/st_mesa_to_tgsi.c',
|
'state_tracker/st_mesa_to_tgsi.c',
|
||||||
'state_tracker/st_program.c',
|
'state_tracker/st_program.c',
|
||||||
'state_tracker/st_texture.c',
|
'state_tracker/st_texture.c',
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,7 @@ STATETRACKER_SOURCES = \
|
||||||
state_tracker/st_format.c \
|
state_tracker/st_format.c \
|
||||||
state_tracker/st_framebuffer.c \
|
state_tracker/st_framebuffer.c \
|
||||||
state_tracker/st_gen_mipmap.c \
|
state_tracker/st_gen_mipmap.c \
|
||||||
|
state_tracker/st_manager.c \
|
||||||
state_tracker/st_mesa_to_tgsi.c \
|
state_tracker/st_mesa_to_tgsi.c \
|
||||||
state_tracker/st_program.c \
|
state_tracker/st_program.c \
|
||||||
state_tracker/st_texture.c
|
state_tracker/st_texture.c
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include "st_atom.h"
|
#include "st_atom.h"
|
||||||
#include "st_cb_bitmap.h"
|
#include "st_cb_bitmap.h"
|
||||||
#include "st_program.h"
|
#include "st_program.h"
|
||||||
|
#include "st_manager.h"
|
||||||
|
|
||||||
#include "pipe/p_context.h"
|
#include "pipe/p_context.h"
|
||||||
|
|
||||||
|
|
@ -136,9 +137,7 @@ void st_validate_state( struct st_context *st )
|
||||||
|
|
||||||
check_program_state( st );
|
check_program_state( st );
|
||||||
|
|
||||||
if (st->pipe->screen->update_buffer)
|
st_manager_validate_framebuffers(st);
|
||||||
st->pipe->screen->update_buffer(st->pipe->screen,
|
|
||||||
st->pipe->priv);
|
|
||||||
|
|
||||||
if (state->st == 0)
|
if (state->st == 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@
|
||||||
#include "st_format.h"
|
#include "st_format.h"
|
||||||
#include "st_public.h"
|
#include "st_public.h"
|
||||||
#include "st_texture.h"
|
#include "st_texture.h"
|
||||||
|
#include "st_manager.h"
|
||||||
|
|
||||||
#include "util/u_format.h"
|
#include "util/u_format.h"
|
||||||
#include "util/u_rect.h"
|
#include "util/u_rect.h"
|
||||||
|
|
@ -618,8 +619,18 @@ check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
|
||||||
static void
|
static void
|
||||||
st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
|
st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
|
||||||
{
|
{
|
||||||
|
GLframebuffer *fb = ctx->DrawBuffer;
|
||||||
|
GLuint i;
|
||||||
|
|
||||||
(void) count;
|
(void) count;
|
||||||
(void) buffers;
|
(void) buffers;
|
||||||
|
|
||||||
|
/* add the renderbuffers on demand */
|
||||||
|
for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
|
||||||
|
gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
|
||||||
|
st_manager_add_color_renderbuffer(ctx->st, fb, idx);
|
||||||
|
}
|
||||||
|
|
||||||
check_create_front_buffers(ctx, ctx->DrawBuffer);
|
check_create_front_buffers(ctx, ctx->DrawBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -630,8 +641,13 @@ st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
|
||||||
static void
|
static void
|
||||||
st_ReadBuffer(GLcontext *ctx, GLenum buffer)
|
st_ReadBuffer(GLcontext *ctx, GLenum buffer)
|
||||||
{
|
{
|
||||||
|
GLframebuffer *fb = ctx->ReadBuffer;
|
||||||
|
|
||||||
(void) buffer;
|
(void) buffer;
|
||||||
check_create_front_buffers(ctx, ctx->ReadBuffer);
|
|
||||||
|
/* add the renderbuffer on demand */
|
||||||
|
st_manager_add_color_renderbuffer(ctx->st, fb, fb->_ColorReadBufferIndex);
|
||||||
|
check_create_front_buffers(ctx, fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include "st_cb_clear.h"
|
#include "st_cb_clear.h"
|
||||||
#include "st_cb_fbo.h"
|
#include "st_cb_fbo.h"
|
||||||
#include "st_public.h"
|
#include "st_public.h"
|
||||||
|
#include "st_manager.h"
|
||||||
#include "pipe/p_context.h"
|
#include "pipe/p_context.h"
|
||||||
#include "pipe/p_defines.h"
|
#include "pipe/p_defines.h"
|
||||||
#include "pipe/p_screen.h"
|
#include "pipe/p_screen.h"
|
||||||
|
|
@ -74,12 +75,9 @@ display_front_buffer(struct st_context *st)
|
||||||
= st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
|
= st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
|
||||||
|
|
||||||
if (strb) {
|
if (strb) {
|
||||||
struct pipe_surface *front_surf = strb->surface;
|
|
||||||
|
|
||||||
/* Hook for copying "fake" frontbuffer if necessary:
|
/* Hook for copying "fake" frontbuffer if necessary:
|
||||||
*/
|
*/
|
||||||
st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf,
|
st_manager_flush_frontbuffer(st);
|
||||||
st->winsys_drawable_handle );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
st->frontbuffer_status = FRONT_STATUS_UNDEFINED;
|
st->frontbuffer_status = FRONT_STATUS_UNDEFINED;
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
|
|
||||||
#include "st_debug.h"
|
#include "st_debug.h"
|
||||||
#include "st_context.h"
|
#include "st_context.h"
|
||||||
|
#include "st_atom.h"
|
||||||
#include "st_cb_readpixels.h"
|
#include "st_cb_readpixels.h"
|
||||||
#include "st_cb_fbo.h"
|
#include "st_cb_fbo.h"
|
||||||
#include "st_public.h"
|
#include "st_public.h"
|
||||||
|
|
@ -350,6 +351,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
|
||||||
/* XXX convolution not done yet */
|
/* XXX convolution not done yet */
|
||||||
assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
|
assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
|
||||||
|
|
||||||
|
st_validate_state(ctx->st);
|
||||||
|
|
||||||
/* Do all needed clipping here, so that we can forget about it later */
|
/* Do all needed clipping here, so that we can forget about it later */
|
||||||
if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
|
if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
|
||||||
/* The ReadPixels transfer is totally outside the window bounds */
|
/* The ReadPixels transfer is totally outside the window bounds */
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@
|
||||||
#include "vbo/vbo.h"
|
#include "vbo/vbo.h"
|
||||||
#include "shader/shader_api.h"
|
#include "shader/shader_api.h"
|
||||||
#include "glapi/glapi.h"
|
#include "glapi/glapi.h"
|
||||||
|
#include "st_context.h"
|
||||||
#include "st_public.h"
|
#include "st_public.h"
|
||||||
#include "st_debug.h"
|
#include "st_debug.h"
|
||||||
#include "st_context.h"
|
|
||||||
#include "st_cb_accum.h"
|
#include "st_cb_accum.h"
|
||||||
#include "st_cb_bitmap.h"
|
#include "st_cb_bitmap.h"
|
||||||
#include "st_cb_blit.h"
|
#include "st_cb_blit.h"
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include "main/mtypes.h"
|
#include "main/mtypes.h"
|
||||||
#include "shader/prog_cache.h"
|
#include "shader/prog_cache.h"
|
||||||
#include "pipe/p_state.h"
|
#include "pipe/p_state.h"
|
||||||
|
#include "state_tracker/st_api.h"
|
||||||
|
|
||||||
|
|
||||||
struct st_context;
|
struct st_context;
|
||||||
|
|
@ -73,6 +74,8 @@ struct st_tracked_state {
|
||||||
|
|
||||||
struct st_context
|
struct st_context
|
||||||
{
|
{
|
||||||
|
struct st_context_iface iface;
|
||||||
|
|
||||||
GLcontext *ctx;
|
GLcontext *ctx;
|
||||||
|
|
||||||
struct pipe_context *pipe;
|
struct pipe_context *pipe;
|
||||||
|
|
@ -207,6 +210,11 @@ struct st_framebuffer
|
||||||
GLframebuffer Base;
|
GLframebuffer Base;
|
||||||
void *Private;
|
void *Private;
|
||||||
GLuint InitWidth, InitHeight;
|
GLuint InitWidth, InitHeight;
|
||||||
|
|
||||||
|
struct st_framebuffer_iface *iface;
|
||||||
|
enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
|
||||||
|
unsigned num_statts;
|
||||||
|
int32_t revalidate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
799
src/mesa/state_tracker/st_manager.c
Normal file
799
src/mesa/state_tracker/st_manager.c
Normal file
|
|
@ -0,0 +1,799 @@
|
||||||
|
/*
|
||||||
|
* Mesa 3-D graphics library
|
||||||
|
* Version: 7.9
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 LunarG Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "state_tracker/st_api.h"
|
||||||
|
|
||||||
|
#include "pipe/p_context.h"
|
||||||
|
#include "pipe/p_screen.h"
|
||||||
|
#include "util/u_format.h"
|
||||||
|
#include "util/u_pointer.h"
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
#include "util/u_atomic.h"
|
||||||
|
|
||||||
|
#include "main/mtypes.h"
|
||||||
|
#include "main/context.h"
|
||||||
|
#include "main/texobj.h"
|
||||||
|
#include "main/teximage.h"
|
||||||
|
#include "main/texstate.h"
|
||||||
|
#include "main/texfetch.h"
|
||||||
|
#include "main/fbobject.h"
|
||||||
|
#include "main/framebuffer.h"
|
||||||
|
#include "main/renderbuffer.h"
|
||||||
|
#include "st_texture.h"
|
||||||
|
|
||||||
|
#include "st_context.h"
|
||||||
|
#include "st_format.h"
|
||||||
|
#include "st_cb_fbo.h"
|
||||||
|
#include "st_manager.h"
|
||||||
|
|
||||||
|
/* these functions are defined in st_context.c */
|
||||||
|
struct st_context *
|
||||||
|
st_create_context(struct pipe_context *pipe,
|
||||||
|
const __GLcontextModes *visual,
|
||||||
|
struct st_context *share);
|
||||||
|
void st_destroy_context(struct st_context *st);
|
||||||
|
void st_flush(struct st_context *st, uint pipeFlushFlags,
|
||||||
|
struct pipe_fence_handle **fence);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that this function may fail.
|
||||||
|
*/
|
||||||
|
static INLINE struct st_framebuffer *
|
||||||
|
st_framebuffer(GLframebuffer *fb)
|
||||||
|
{
|
||||||
|
/* FBO cannot be casted. See st_new_framebuffer */
|
||||||
|
return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map an attachment to a buffer index.
|
||||||
|
*/
|
||||||
|
static INLINE gl_buffer_index
|
||||||
|
attachment_to_buffer_index(enum st_attachment_type statt)
|
||||||
|
{
|
||||||
|
gl_buffer_index index;
|
||||||
|
|
||||||
|
switch (statt) {
|
||||||
|
case ST_ATTACHMENT_FRONT_LEFT:
|
||||||
|
index = BUFFER_FRONT_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_LEFT:
|
||||||
|
index = BUFFER_BACK_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||||
|
index = BUFFER_FRONT_RIGHT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_RIGHT:
|
||||||
|
index = BUFFER_BACK_RIGHT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_DEPTH_STENCIL:
|
||||||
|
index = BUFFER_DEPTH;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_ACCUM:
|
||||||
|
index = BUFFER_ACCUM;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_SAMPLE:
|
||||||
|
default:
|
||||||
|
index = BUFFER_COUNT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a buffer index to an attachment.
|
||||||
|
*/
|
||||||
|
static INLINE enum st_attachment_type
|
||||||
|
buffer_index_to_attachment(gl_buffer_index index)
|
||||||
|
{
|
||||||
|
enum st_attachment_type statt;
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case BUFFER_FRONT_LEFT:
|
||||||
|
statt = ST_ATTACHMENT_FRONT_LEFT;
|
||||||
|
break;
|
||||||
|
case BUFFER_BACK_LEFT:
|
||||||
|
statt = ST_ATTACHMENT_BACK_LEFT;
|
||||||
|
break;
|
||||||
|
case BUFFER_FRONT_RIGHT:
|
||||||
|
statt = ST_ATTACHMENT_FRONT_RIGHT;
|
||||||
|
break;
|
||||||
|
case BUFFER_BACK_RIGHT:
|
||||||
|
statt = ST_ATTACHMENT_BACK_RIGHT;
|
||||||
|
break;
|
||||||
|
case BUFFER_DEPTH:
|
||||||
|
statt = ST_ATTACHMENT_DEPTH_STENCIL;
|
||||||
|
break;
|
||||||
|
case BUFFER_ACCUM:
|
||||||
|
statt = ST_ATTACHMENT_ACCUM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
statt = ST_ATTACHMENT_INVALID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return statt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a framebuffer to make sure up-to-date pipe_textures are used.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
|
||||||
|
{
|
||||||
|
struct pipe_screen *screen = st->pipe->screen;
|
||||||
|
struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
|
||||||
|
uint width, height;
|
||||||
|
unsigned i;
|
||||||
|
boolean changed = FALSE;
|
||||||
|
|
||||||
|
if (!p_atomic_read(&stfb->revalidate))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* validate the fb */
|
||||||
|
if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures))
|
||||||
|
return;
|
||||||
|
|
||||||
|
width = stfb->Base.Width;
|
||||||
|
height = stfb->Base.Height;
|
||||||
|
|
||||||
|
for (i = 0; i < stfb->num_statts; i++) {
|
||||||
|
struct st_renderbuffer *strb;
|
||||||
|
struct pipe_surface *ps;
|
||||||
|
gl_buffer_index idx;
|
||||||
|
|
||||||
|
if (!textures[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
idx = attachment_to_buffer_index(stfb->statts[i]);
|
||||||
|
if (idx >= BUFFER_COUNT) {
|
||||||
|
pipe_texture_reference(&textures[i], NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
|
||||||
|
assert(strb);
|
||||||
|
if (strb->texture == textures[i]) {
|
||||||
|
pipe_texture_reference(&textures[i], NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0,
|
||||||
|
PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||||
|
if (ps) {
|
||||||
|
pipe_surface_reference(&strb->surface, ps);
|
||||||
|
pipe_texture_reference(&strb->texture, ps->texture);
|
||||||
|
/* ownership transfered */
|
||||||
|
pipe_surface_reference(&ps, NULL);
|
||||||
|
|
||||||
|
changed = TRUE;
|
||||||
|
|
||||||
|
strb->Base.Width = strb->surface->width;
|
||||||
|
strb->Base.Height = strb->surface->height;
|
||||||
|
|
||||||
|
width = strb->Base.Width;
|
||||||
|
height = strb->Base.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe_texture_reference(&textures[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
st->dirty.st |= ST_NEW_FRAMEBUFFER;
|
||||||
|
_mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
|
||||||
|
|
||||||
|
assert(stfb->Base.Width == width);
|
||||||
|
assert(stfb->Base.Height == height);
|
||||||
|
}
|
||||||
|
|
||||||
|
p_atomic_set(&stfb->revalidate, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the attachments to validate by looping the existing renderbuffers.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
st_framebuffer_update_attachments(struct st_framebuffer *stfb)
|
||||||
|
{
|
||||||
|
gl_buffer_index idx;
|
||||||
|
|
||||||
|
stfb->num_statts = 0;
|
||||||
|
for (idx = 0; idx < BUFFER_COUNT; idx++) {
|
||||||
|
struct st_renderbuffer *strb;
|
||||||
|
enum st_attachment_type statt;
|
||||||
|
|
||||||
|
strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
|
||||||
|
if (!strb || strb->software)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
statt = buffer_index_to_attachment(idx);
|
||||||
|
if (statt != ST_ATTACHMENT_INVALID &&
|
||||||
|
st_visual_have_buffers(stfb->iface->visual, 1 << statt))
|
||||||
|
stfb->statts[stfb->num_statts++] = statt;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_atomic_set(&stfb->revalidate, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a renderbuffer to the framebuffer.
|
||||||
|
*/
|
||||||
|
static boolean
|
||||||
|
st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
|
||||||
|
gl_buffer_index idx)
|
||||||
|
{
|
||||||
|
struct gl_renderbuffer *rb;
|
||||||
|
enum pipe_format format;
|
||||||
|
int samples;
|
||||||
|
boolean sw;
|
||||||
|
|
||||||
|
/* do not distinguish depth/stencil buffers */
|
||||||
|
if (idx == BUFFER_STENCIL)
|
||||||
|
idx = BUFFER_DEPTH;
|
||||||
|
|
||||||
|
switch (idx) {
|
||||||
|
case BUFFER_DEPTH:
|
||||||
|
format = stfb->iface->visual->depth_stencil_format;
|
||||||
|
sw = FALSE;
|
||||||
|
break;
|
||||||
|
case BUFFER_ACCUM:
|
||||||
|
format = stfb->iface->visual->accum_format;
|
||||||
|
sw = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
format = stfb->iface->visual->color_format;
|
||||||
|
sw = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == PIPE_FORMAT_NONE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
samples = stfb->iface->visual->samples;
|
||||||
|
if (!samples)
|
||||||
|
samples = st_get_msaa();
|
||||||
|
|
||||||
|
rb = st_new_renderbuffer_fb(format, samples, sw);
|
||||||
|
if (!rb)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (idx != BUFFER_DEPTH) {
|
||||||
|
_mesa_add_renderbuffer(&stfb->Base, idx, rb);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0))
|
||||||
|
_mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb);
|
||||||
|
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1))
|
||||||
|
_mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intialize a __GLcontextModes from a visual.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
st_visual_to_context_mode(const struct st_visual *visual,
|
||||||
|
__GLcontextModes *mode)
|
||||||
|
{
|
||||||
|
memset(mode, 0, sizeof(*mode));
|
||||||
|
|
||||||
|
if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK))
|
||||||
|
mode->doubleBufferMode = GL_TRUE;
|
||||||
|
if (st_visual_have_buffers(visual,
|
||||||
|
ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK))
|
||||||
|
mode->stereoMode = GL_TRUE;
|
||||||
|
|
||||||
|
if (visual->color_format != PIPE_FORMAT_NONE) {
|
||||||
|
mode->rgbMode = GL_TRUE;
|
||||||
|
|
||||||
|
mode->redBits =
|
||||||
|
util_format_get_component_bits(visual->color_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 0);
|
||||||
|
mode->greenBits =
|
||||||
|
util_format_get_component_bits(visual->color_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 1);
|
||||||
|
mode->blueBits =
|
||||||
|
util_format_get_component_bits(visual->color_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 2);
|
||||||
|
mode->alphaBits =
|
||||||
|
util_format_get_component_bits(visual->color_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 3);
|
||||||
|
|
||||||
|
mode->rgbBits = mode->redBits +
|
||||||
|
mode->greenBits + mode->blueBits + mode->alphaBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visual->depth_stencil_format != PIPE_FORMAT_NONE) {
|
||||||
|
mode->haveDepthBuffer = GL_TRUE;
|
||||||
|
mode->haveStencilBuffer = GL_TRUE;
|
||||||
|
|
||||||
|
mode->depthBits =
|
||||||
|
util_format_get_component_bits(visual->depth_stencil_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_ZS, 0);
|
||||||
|
mode->stencilBits =
|
||||||
|
util_format_get_component_bits(visual->depth_stencil_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_ZS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visual->accum_format != PIPE_FORMAT_NONE) {
|
||||||
|
mode->haveAccumBuffer = GL_TRUE;
|
||||||
|
|
||||||
|
mode->accumRedBits =
|
||||||
|
util_format_get_component_bits(visual->accum_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 0);
|
||||||
|
mode->accumGreenBits =
|
||||||
|
util_format_get_component_bits(visual->accum_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 1);
|
||||||
|
mode->accumBlueBits =
|
||||||
|
util_format_get_component_bits(visual->accum_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 2);
|
||||||
|
mode->accumAlphaBits =
|
||||||
|
util_format_get_component_bits(visual->accum_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visual->samples) {
|
||||||
|
mode->sampleBuffers = 1;
|
||||||
|
mode->samples = visual->samples;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the default draw or read buffer from a visual.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
st_visual_to_default_buffer(const struct st_visual *visual,
|
||||||
|
GLenum *buffer, GLint *index)
|
||||||
|
{
|
||||||
|
enum st_attachment_type statt;
|
||||||
|
GLenum buf;
|
||||||
|
gl_buffer_index idx;
|
||||||
|
|
||||||
|
statt = visual->render_buffer;
|
||||||
|
/* do nothing if an invalid render buffer is specified */
|
||||||
|
if (statt == ST_ATTACHMENT_INVALID ||
|
||||||
|
!st_visual_have_buffers(visual, 1 << statt))
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (statt) {
|
||||||
|
case ST_ATTACHMENT_FRONT_LEFT:
|
||||||
|
buf = GL_FRONT_LEFT;
|
||||||
|
idx = BUFFER_FRONT_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_LEFT:
|
||||||
|
buf = GL_BACK_LEFT;
|
||||||
|
idx = BUFFER_BACK_LEFT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||||
|
buf = GL_FRONT_RIGHT;
|
||||||
|
idx = BUFFER_FRONT_RIGHT;
|
||||||
|
break;
|
||||||
|
case ST_ATTACHMENT_BACK_RIGHT:
|
||||||
|
buf = GL_BACK_RIGHT;
|
||||||
|
idx = BUFFER_BACK_RIGHT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buf = GL_NONE;
|
||||||
|
idx = BUFFER_COUNT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf != GL_NONE) {
|
||||||
|
if (buffer)
|
||||||
|
*buffer = buf;
|
||||||
|
if (index)
|
||||||
|
*index = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a framebuffer from a manager interface.
|
||||||
|
*/
|
||||||
|
static struct st_framebuffer *
|
||||||
|
st_framebuffer_create(struct st_framebuffer_iface *stfbi)
|
||||||
|
{
|
||||||
|
struct st_framebuffer *stfb;
|
||||||
|
__GLcontextModes mode;
|
||||||
|
gl_buffer_index idx;
|
||||||
|
|
||||||
|
stfb = CALLOC_STRUCT(st_framebuffer);
|
||||||
|
if (!stfb)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
st_visual_to_context_mode(stfbi->visual, &mode);
|
||||||
|
_mesa_initialize_window_framebuffer(&stfb->Base, &mode);
|
||||||
|
|
||||||
|
/* modify the draw/read buffers of the fb */
|
||||||
|
st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0],
|
||||||
|
&stfb->Base._ColorDrawBufferIndexes[0]);
|
||||||
|
st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer,
|
||||||
|
&stfb->Base._ColorReadBufferIndex);
|
||||||
|
|
||||||
|
stfb->iface = stfbi;
|
||||||
|
|
||||||
|
/* add the color buffer */
|
||||||
|
idx = stfb->Base._ColorDrawBufferIndexes[0];
|
||||||
|
if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
|
||||||
|
FREE(stfb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
|
||||||
|
st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
|
||||||
|
|
||||||
|
st_framebuffer_update_attachments(stfb);
|
||||||
|
|
||||||
|
stfb->Base.Initialized = GL_TRUE;
|
||||||
|
|
||||||
|
return stfb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference a framebuffer.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
st_framebuffer_reference(struct st_framebuffer **ptr,
|
||||||
|
struct st_framebuffer *stfb)
|
||||||
|
{
|
||||||
|
GLframebuffer *fb = &stfb->Base;
|
||||||
|
_mesa_reference_framebuffer((GLframebuffer **) ptr, fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
|
||||||
|
struct st_framebuffer_iface *stfbi)
|
||||||
|
{
|
||||||
|
struct st_context *st = (struct st_context *) stctxi;
|
||||||
|
struct st_framebuffer *stfb;
|
||||||
|
|
||||||
|
/* either draw or read winsys fb */
|
||||||
|
stfb = st_framebuffer(st->ctx->WinSysDrawBuffer);
|
||||||
|
if (!stfb || stfb->iface != stfbi)
|
||||||
|
stfb = st_framebuffer(st->ctx->WinSysReadBuffer);
|
||||||
|
assert(stfb && stfb->iface == stfbi);
|
||||||
|
|
||||||
|
p_atomic_set(&stfb->revalidate, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_context_flush(struct st_context_iface *stctxi, unsigned flags,
|
||||||
|
struct pipe_fence_handle **fence)
|
||||||
|
{
|
||||||
|
struct st_context *st = (struct st_context *) stctxi;
|
||||||
|
st_flush(st, flags, fence);
|
||||||
|
if (flags & PIPE_FLUSH_RENDER_CACHE)
|
||||||
|
st_manager_flush_frontbuffer(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target,
|
||||||
|
int level, enum pipe_format internal_format,
|
||||||
|
struct pipe_texture *tex, boolean mipmap)
|
||||||
|
{
|
||||||
|
struct st_context *st = (struct st_context *) stctxi;
|
||||||
|
GLcontext *ctx = st->ctx;
|
||||||
|
struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
|
||||||
|
struct gl_texture_object *texObj;
|
||||||
|
struct gl_texture_image *texImage;
|
||||||
|
struct st_texture_object *stObj;
|
||||||
|
struct st_texture_image *stImage;
|
||||||
|
GLenum internalFormat;
|
||||||
|
|
||||||
|
switch (target) {
|
||||||
|
case ST_TEXTURE_1D:
|
||||||
|
target = GL_TEXTURE_1D;
|
||||||
|
break;
|
||||||
|
case ST_TEXTURE_2D:
|
||||||
|
target = GL_TEXTURE_2D;
|
||||||
|
break;
|
||||||
|
case ST_TEXTURE_3D:
|
||||||
|
target = GL_TEXTURE_3D;
|
||||||
|
break;
|
||||||
|
case ST_TEXTURE_RECT:
|
||||||
|
target = GL_TEXTURE_RECTANGLE_ARB;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (util_format_get_component_bits(internal_format,
|
||||||
|
UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
|
||||||
|
internalFormat = GL_RGBA;
|
||||||
|
else
|
||||||
|
internalFormat = GL_RGB;
|
||||||
|
|
||||||
|
texObj = _mesa_select_tex_object(ctx, texUnit, target);
|
||||||
|
_mesa_lock_texture(ctx, texObj);
|
||||||
|
|
||||||
|
stObj = st_texture_object(texObj);
|
||||||
|
/* switch to surface based */
|
||||||
|
if (!stObj->surface_based) {
|
||||||
|
_mesa_clear_texture_object(ctx, texObj);
|
||||||
|
stObj->surface_based = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
|
||||||
|
stImage = st_texture_image(texImage);
|
||||||
|
if (tex) {
|
||||||
|
_mesa_init_teximage_fields(ctx, target, texImage,
|
||||||
|
tex->width0, tex->height0, 1, 0, internalFormat);
|
||||||
|
texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
|
||||||
|
GL_RGBA, GL_UNSIGNED_BYTE);
|
||||||
|
_mesa_set_fetch_functions(texImage, 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_mesa_clear_texture_image(ctx, texImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe_texture_reference(&stImage->pt, tex);
|
||||||
|
|
||||||
|
_mesa_dirty_texobj(ctx, texObj, GL_TRUE);
|
||||||
|
_mesa_unlock_texture(ctx, texObj);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_context_destroy(struct st_context_iface *stctxi)
|
||||||
|
{
|
||||||
|
struct st_context *st = (struct st_context *) stctxi;
|
||||||
|
st_destroy_context(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct st_context_iface *
|
||||||
|
st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
|
||||||
|
const struct st_visual *visual,
|
||||||
|
struct st_context_iface *shared_stctxi)
|
||||||
|
{
|
||||||
|
struct st_context *shared_ctx = (struct st_context *) shared_stctxi;
|
||||||
|
struct st_context *st;
|
||||||
|
struct pipe_context *pipe;
|
||||||
|
__GLcontextModes mode;
|
||||||
|
|
||||||
|
pipe = smapi->screen->context_create(smapi->screen, NULL);
|
||||||
|
if (!pipe)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
st_visual_to_context_mode(visual, &mode);
|
||||||
|
st = st_create_context(pipe, &mode, shared_ctx);
|
||||||
|
if (!st) {
|
||||||
|
pipe->destroy(pipe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
st->iface.destroy = st_context_destroy;
|
||||||
|
|
||||||
|
st->iface.notify_invalid_framebuffer =
|
||||||
|
st_context_notify_invalid_framebuffer;
|
||||||
|
st->iface.flush = st_context_flush;
|
||||||
|
|
||||||
|
st->iface.teximage = st_context_teximage;
|
||||||
|
st->iface.copy = NULL;
|
||||||
|
|
||||||
|
st->iface.st_context_private = (void *) smapi;
|
||||||
|
|
||||||
|
return &st->iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
|
||||||
|
struct st_framebuffer_iface *stdrawi,
|
||||||
|
struct st_framebuffer_iface *streadi)
|
||||||
|
{
|
||||||
|
struct st_context *st = (struct st_context *) stctxi;
|
||||||
|
struct st_framebuffer *stdraw, *stread, *stfb;
|
||||||
|
boolean ret;
|
||||||
|
|
||||||
|
_glapi_check_multithread();
|
||||||
|
|
||||||
|
if (st) {
|
||||||
|
/* reuse/create the draw fb */
|
||||||
|
stfb = st_framebuffer(st->ctx->WinSysDrawBuffer);
|
||||||
|
if (stfb && stfb->iface == stdrawi) {
|
||||||
|
stdraw = NULL;
|
||||||
|
st_framebuffer_reference(&stdraw, stfb);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stdraw = st_framebuffer_create(stdrawi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reuse/create the read fb */
|
||||||
|
stfb = st_framebuffer(st->ctx->WinSysReadBuffer);
|
||||||
|
if (!stfb || stfb->iface != streadi)
|
||||||
|
stfb = stdraw;
|
||||||
|
if (stfb && stfb->iface == streadi) {
|
||||||
|
stread = NULL;
|
||||||
|
st_framebuffer_reference(&stread, stfb);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stread = st_framebuffer_create(streadi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdraw && stread) {
|
||||||
|
st_framebuffer_validate(stdraw, st);
|
||||||
|
if (stread != stdraw)
|
||||||
|
st_framebuffer_validate(stread, st);
|
||||||
|
|
||||||
|
/* modify the draw/read buffers of the context */
|
||||||
|
st_visual_to_default_buffer(stdraw->iface->visual,
|
||||||
|
&st->ctx->Color.DrawBuffer[0], NULL);
|
||||||
|
st_visual_to_default_buffer(stread->iface->visual,
|
||||||
|
&st->ctx->Pixel.ReadBuffer, NULL);
|
||||||
|
|
||||||
|
ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
st_framebuffer_reference(&stdraw, NULL);
|
||||||
|
st_framebuffer_reference(&stread, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = _mesa_make_current(NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct st_context_iface *
|
||||||
|
st_api_get_current(struct st_api *stapi)
|
||||||
|
{
|
||||||
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
struct st_context *st = (ctx) ? ctx->st : NULL;
|
||||||
|
|
||||||
|
return (st) ? &st->iface : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
st_api_is_visual_supported(struct st_api *stapi,
|
||||||
|
const struct st_visual *visual)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static st_proc_t
|
||||||
|
st_api_get_proc_address(struct st_api *stapi, const char *procname)
|
||||||
|
{
|
||||||
|
return (st_proc_t) _glapi_get_proc_address(procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_api_destroy(struct st_api *stapi)
|
||||||
|
{
|
||||||
|
FREE(stapi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush the front buffer if the current context renders to the front buffer.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_manager_flush_frontbuffer(struct st_context *st)
|
||||||
|
{
|
||||||
|
struct st_framebuffer *stfb = st_framebuffer(st->ctx->DrawBuffer);
|
||||||
|
struct st_renderbuffer *strb = NULL;
|
||||||
|
|
||||||
|
if (stfb)
|
||||||
|
strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
|
||||||
|
if (!strb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* st_public.h */
|
||||||
|
if (!stfb->iface) {
|
||||||
|
struct pipe_surface *front_surf = strb->surface;
|
||||||
|
st->pipe->screen->flush_frontbuffer(st->pipe->screen,
|
||||||
|
front_surf, st->winsys_drawable_handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-validate the framebuffers.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_manager_validate_framebuffers(struct st_context *st)
|
||||||
|
{
|
||||||
|
struct st_framebuffer *stdraw = st_framebuffer(st->ctx->DrawBuffer);
|
||||||
|
struct st_framebuffer *stread = st_framebuffer(st->ctx->ReadBuffer);
|
||||||
|
|
||||||
|
/* st_public.h */
|
||||||
|
if ((stdraw && !stdraw->iface) || (stread && !stread->iface)) {
|
||||||
|
struct pipe_screen *screen = st->pipe->screen;
|
||||||
|
if (screen->update_buffer)
|
||||||
|
screen->update_buffer(screen, st->pipe->priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdraw)
|
||||||
|
st_framebuffer_validate(stdraw, st);
|
||||||
|
if (stread && stread != stdraw)
|
||||||
|
st_framebuffer_validate(stread, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a color renderbuffer on demand.
|
||||||
|
*/
|
||||||
|
boolean
|
||||||
|
st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb,
|
||||||
|
gl_buffer_index idx)
|
||||||
|
{
|
||||||
|
struct st_framebuffer *stfb = st_framebuffer(fb);
|
||||||
|
|
||||||
|
/* FBO or st_public.h */
|
||||||
|
if (!stfb || !stfb->iface)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (stfb->Base.Attachment[idx].Renderbuffer)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
switch (idx) {
|
||||||
|
case BUFFER_FRONT_LEFT:
|
||||||
|
case BUFFER_BACK_LEFT:
|
||||||
|
case BUFFER_FRONT_RIGHT:
|
||||||
|
case BUFFER_BACK_RIGHT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!st_framebuffer_add_renderbuffer(stfb, idx))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
st_framebuffer_update_attachments(stfb);
|
||||||
|
st_invalidate_state(st->ctx, _NEW_BUFFERS);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an st_api to manage the state tracker.
|
||||||
|
*/
|
||||||
|
struct st_api *
|
||||||
|
st_manager_create_api(void)
|
||||||
|
{
|
||||||
|
struct st_api *stapi;
|
||||||
|
|
||||||
|
stapi = CALLOC_STRUCT(st_api);
|
||||||
|
if (stapi) {
|
||||||
|
stapi->destroy = st_api_destroy;
|
||||||
|
stapi->get_proc_address = st_api_get_proc_address;
|
||||||
|
stapi->is_visual_supported = st_api_is_visual_supported;
|
||||||
|
|
||||||
|
stapi->create_context = st_api_create_context;
|
||||||
|
stapi->make_current = st_api_make_current;
|
||||||
|
stapi->get_current = st_api_get_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stapi;
|
||||||
|
}
|
||||||
47
src/mesa/state_tracker/st_manager.h
Normal file
47
src/mesa/state_tracker/st_manager.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Mesa 3-D graphics library
|
||||||
|
* Version: 7.9
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 LunarG Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ST_MANAGER_H
|
||||||
|
#define ST_MANAGER_H
|
||||||
|
|
||||||
|
#include "state_tracker/st_api.h"
|
||||||
|
#include "st_context.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
st_manager_flush_frontbuffer(struct st_context *st);
|
||||||
|
|
||||||
|
void
|
||||||
|
st_manager_validate_framebuffers(struct st_context *st);
|
||||||
|
|
||||||
|
boolean
|
||||||
|
st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb,
|
||||||
|
gl_buffer_index idx);
|
||||||
|
|
||||||
|
struct st_api *
|
||||||
|
st_manager_create_api(void);
|
||||||
|
|
||||||
|
#endif /* ST_MANAGER_H */
|
||||||
Loading…
Add table
Reference in a new issue