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:
Keith Whitwell 2010-03-16 09:02:38 +00:00
commit 8cdfd1219a
96 changed files with 3977 additions and 1079 deletions

View file

@ -88,9 +88,9 @@ LoadSkyBoxCubeTexture(const char *filePosX,
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE))
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;
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;
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE))
return 0;

View file

@ -31,8 +31,8 @@
*/
#ifndef OS_LLVM_H
#define OS_LLVM_H
#ifndef LP_BLD_H
#define LP_BLD_H
#include <llvm-c/Core.h>
@ -40,8 +40,8 @@
/** Set version to 0 if missing to avoid #ifdef HAVE_LLVM everywhere */
#ifndef HAVE_LLVM
#define HAVE_LLVM 0x0
#define HAVE_LLVM 0x0207
#endif
#endif /* OS_LLVM_H */
#endif /* LP_BLD_H */

View file

@ -35,7 +35,7 @@
#define LP_BLD_ALPHA_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct pipe_alpha_state;
struct lp_type;

View file

@ -361,12 +361,12 @@ lp_build_mul_u8n(LLVMBuilderRef builder,
LLVMValueRef c8;
LLVMValueRef ab;
c8 = lp_build_int_const_scalar(i16_type, 8);
c8 = lp_build_const_int_vec(i16_type, 8);
#if 0
/* 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, "");
#else
@ -374,7 +374,7 @@ lp_build_mul_u8n(LLVMBuilderRef builder,
/* ab/255 ~= (ab + (ab >> 8) + 0x80) >> 8 */
ab = LLVMBuildMul(builder, a, b, "");
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
@ -429,7 +429,7 @@ lp_build_mul(struct lp_build_context *bld,
}
if(type.fixed)
shift = lp_build_int_const_scalar(type, type.width/2);
shift = lp_build_const_int_vec(type, type.width/2);
else
shift = NULL;
@ -491,7 +491,7 @@ lp_build_mul_imm(struct lp_build_context *bld,
* for Inf and NaN.
*/
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 = LLVMBuildAdd(bld->builder, a, factor, "");
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
}
else {
factor = lp_build_const_scalar(bld->type, shift);
factor = lp_build_const_vec(bld->type, shift);
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);
}
@ -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
* powerful lp_type, capable of further distinguishing the values
* 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;
}
@ -689,7 +689,7 @@ lp_build_abs(struct lp_build_context *bld,
/* vector of floats */
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
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 = LLVMBuildAnd(bld->builder, a, mask, "");
a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
@ -751,7 +751,7 @@ lp_build_sgn(struct lp_build_context *bld,
/* vector */
int_type = lp_build_int_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 */
@ -763,14 +763,14 @@ lp_build_sgn(struct lp_build_context *bld,
}
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);
res = lp_build_select(bld, cond, bld->one, minus_one);
}
/* Handle 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;
}
@ -789,8 +789,8 @@ lp_build_set_sign(struct lp_build_context *bld,
const struct lp_type type = bld->type;
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
LLVMTypeRef vec_type = lp_build_vec_type(type);
LLVMValueRef shift = lp_build_int_const_scalar(type, type.width - 1);
LLVMValueRef mask = lp_build_int_const_scalar(type,
LLVMValueRef shift = lp_build_const_int_vec(type, type.width - 1);
LLVMValueRef mask = lp_build_const_int_vec(type,
~((unsigned long long) 1 << (type.width - 1)));
LLVMValueRef val, res;
@ -930,7 +930,10 @@ lp_build_floor(struct lp_build_context *bld,
assert(type.floating);
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)
@ -993,7 +996,7 @@ lp_build_itrunc(struct lp_build_context *bld,
if (type.length == 1) {
LLVMTypeRef int_type = LLVMIntType(type.width);
return LLVMBuildFPTrunc(bld->builder, a, int_type, "");
return LLVMBuildFPToSI(bld->builder, a, int_type, "");
}
else {
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
@ -1031,7 +1034,7 @@ lp_build_iround(struct lp_build_context *bld,
}
else {
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 half;
@ -1040,7 +1043,7 @@ lp_build_iround(struct lp_build_context *bld,
sign = LLVMBuildAnd(bld->builder, sign, mask, "");
/* 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 = LLVMBuildOr(bld->builder, sign, half, "");
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 */
LLVMTypeRef vec_type = lp_build_vec_type(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 offset;
/* sign = a < 0 ? ~0 : 0 */
sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
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");
/* 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 = a < 0 ? -0.99999(9)f : 0.0f */
@ -1265,7 +1268,7 @@ lp_build_exp(struct lp_build_context *bld,
LLVMValueRef x)
{
/* 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));
}
@ -1279,7 +1282,7 @@ lp_build_log(struct lp_build_context *bld,
LLVMValueRef x)
{
/* 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));
}
@ -1315,7 +1318,7 @@ lp_build_polynomial(struct lp_build_context *bld,
if (type.length == 1)
coeff = LLVMConstReal(float_type, coeffs[i]);
else
coeff = lp_build_const_scalar(type, coeffs[i]);
coeff = lp_build_const_vec(type, coeffs[i]);
if(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);
x = lp_build_min(bld, x, lp_build_const_scalar(type, 129.0));
x = lp_build_max(bld, x, lp_build_const_scalar(type, -126.99999));
x = lp_build_min(bld, x, lp_build_const_vec(type, 129.0));
x = lp_build_max(bld, x, lp_build_const_vec(type, -126.99999));
/* 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, "");
/* fpart = x - ipart */
@ -1386,8 +1389,8 @@ lp_build_exp2_approx(struct lp_build_context *bld,
if(p_exp2_int_part || p_exp2) {
/* expipart = (float) (1 << ipart) */
expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_int_const_scalar(type, 127), "");
expipart = LLVMBuildShl(bld->builder, expipart, lp_build_int_const_scalar(type, 23), "");
expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_const_int_vec(type, 127), "");
expipart = LLVMBuildShl(bld->builder, expipart, lp_build_const_int_vec(type, 23), "");
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 int_vec_type = lp_build_int_vec_type(type);
LLVMValueRef expmask = lp_build_int_const_scalar(type, 0x7f800000);
LLVMValueRef mantmask = lp_build_int_const_scalar(type, 0x007fffff);
LLVMValueRef expmask = lp_build_const_int_vec(type, 0x7f800000);
LLVMValueRef mantmask = lp_build_const_int_vec(type, 0x007fffff);
LLVMValueRef one = LLVMConstBitCast(bld->one, int_vec_type);
LLVMValueRef i = NULL;
@ -1479,8 +1482,8 @@ lp_build_log2_approx(struct lp_build_context *bld,
}
if(p_floor_log2 || p_log2) {
logexp = LLVMBuildLShr(bld->builder, exp, lp_build_int_const_scalar(type, 23), "");
logexp = LLVMBuildSub(bld->builder, logexp, lp_build_int_const_scalar(type, 127), "");
logexp = LLVMBuildLShr(bld->builder, exp, lp_build_const_int_vec(type, 23), "");
logexp = LLVMBuildSub(bld->builder, logexp, lp_build_const_int_vec(type, 127), "");
logexp = LLVMBuildSIToFP(bld->builder, logexp, vec_type, "");
}

View file

@ -37,7 +37,7 @@
#define LP_BLD_ARIT_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct lp_type;

View file

@ -40,7 +40,7 @@
* for a standalone example.
*/
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include "pipe/p_format.h"

View file

@ -263,7 +263,7 @@ lp_build_one(struct lp_type type)
if(type.sign)
/* TODO: Unfortunately this caused "Tried to create a shift operation
* 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
return vec;
@ -283,8 +283,8 @@ lp_build_one(struct lp_type type)
* Build constant-valued vector from a scalar value.
*/
LLVMValueRef
lp_build_const_scalar(struct lp_type type,
double val)
lp_build_const_vec(struct lp_type type,
double val)
{
LLVMTypeRef elem_type = lp_build_elem_type(type);
LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
@ -309,7 +309,7 @@ lp_build_const_scalar(struct lp_type type,
LLVMValueRef
lp_build_int_const_scalar(struct lp_type type,
lp_build_const_int_vec(struct lp_type type,
long long val)
{
LLVMTypeRef elem_type = lp_build_int_elem_type(type);

View file

@ -37,9 +37,9 @@
#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;
@ -85,13 +85,11 @@ lp_build_one(struct lp_type type);
LLVMValueRef
lp_build_const_scalar(struct lp_type type,
double val);
lp_build_const_vec(struct lp_type type, double val);
LLVMValueRef
lp_build_int_const_scalar(struct lp_type type,
long long val);
lp_build_const_int_vec(struct lp_type type, long long val);
LLVMValueRef

View file

@ -114,13 +114,13 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
scale = (double)mask/ubound;
bias = (double)((unsigned long long)1 << (mantissa - n));
res = LLVMBuildMul(builder, src, lp_build_const_scalar(src_type, scale), "");
res = LLVMBuildAdd(builder, res, lp_build_const_scalar(src_type, bias), "");
res = LLVMBuildMul(builder, src, lp_build_const_vec(src_type, scale), "");
res = LLVMBuildAdd(builder, res, lp_build_const_vec(src_type, bias), "");
res = LLVMBuildBitCast(builder, res, int_vec_type, "");
if(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? */
/* YES: this fixes progs/trivial/tri-z-eq.c.
@ -130,21 +130,21 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
#if 0
{
LLVMValueRef msb;
msb = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, dst_width - 1), "");
msb = LLVMBuildShl(builder, msb, lp_build_int_const_scalar(src_type, shift), "");
msb = LLVMBuildSub(builder, msb, lp_build_int_const_scalar(src_type, 1), "");
msb = LLVMBuildLShr(builder, res, lp_build_const_int_vec(src_type, dst_width - 1), "");
msb = LLVMBuildShl(builder, msb, lp_build_const_int_vec(src_type, shift), "");
msb = LLVMBuildSub(builder, msb, lp_build_const_int_vec(src_type, 1), "");
res = LLVMBuildOr(builder, res, msb, "");
}
#elif 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;
n *= 2;
}
#endif
}
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;
}
@ -183,10 +183,10 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
if(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,
@ -195,7 +195,7 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
res = LLVMBuildBitCast(builder, res, vec_type, "");
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;
}
@ -251,7 +251,7 @@ lp_build_conv(LLVMBuilderRef builder,
if(dst_min == 0.0)
thres = bld.zero;
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)
tmp[i] = lp_build_max(&bld, tmp[i], thres);
}
@ -260,7 +260,7 @@ lp_build_conv(LLVMBuilderRef builder,
if(dst_max == 1.0)
thres = bld.one;
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)
tmp[i] = lp_build_min(&bld, tmp[i], thres);
}
@ -288,7 +288,7 @@ lp_build_conv(LLVMBuilderRef builder,
LLVMTypeRef tmp_vec_type;
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)
tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
}
@ -315,7 +315,7 @@ lp_build_conv(LLVMBuilderRef builder,
/* FIXME: compensate different offsets too */
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)
if(src_type.sign)
tmp[i] = LLVMBuildAShr(builder, tmp[i], shift, "");
@ -388,7 +388,7 @@ lp_build_conv(LLVMBuilderRef builder,
}
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)
tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
}
@ -400,7 +400,7 @@ lp_build_conv(LLVMBuilderRef builder,
/* FIXME: compensate different offsets too */
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)
tmp[i] = LLVMBuildShl(builder, tmp[i], shift, "");
}

View file

@ -37,7 +37,7 @@
#define LP_BLD_CONV_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct lp_type;

View file

@ -30,7 +30,7 @@
#define LP_BLD_DEBUG_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include "pipe/p_compiler.h"
#include "util/u_string.h"

View file

@ -61,11 +61,104 @@
#include "util/u_format.h"
#include "lp_bld_type.h"
#include "lp_bld_arit.h"
#include "lp_bld_const.h"
#include "lp_bld_logic.h"
#include "lp_bld_flow.h"
#include "lp_bld_debug.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
lp_build_depth_test(LLVMBuilderRef builder,
@ -126,6 +226,9 @@ lp_build_depth_test(LLVMBuilderRef builder,
LLVMValueRef z_bitmask = NULL;
LLVMValueRef test;
(void) lp_build_stencil_test;
(void) lp_build_stencil_op;
if(!state->enabled)
return;
@ -185,11 +288,11 @@ lp_build_depth_test(LLVMBuilderRef builder,
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_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)
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)
src = LLVMBuildAnd(builder, src, z_bitmask, "");
if(padding_left || padding_right)
@ -198,6 +301,7 @@ lp_build_depth_test(LLVMBuilderRef builder,
lp_build_name(dst, "zsbuf.z");
/* compare src Z to dst Z, returning 'pass' mask */
test = lp_build_cmp(&bld, state->func, src, dst);
lp_build_mask_update(mask, test);

View file

@ -36,7 +36,7 @@
#define LP_BLD_DEPTH_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct pipe_depth_state;

View file

@ -35,7 +35,7 @@
#define LP_BLD_FLOW_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct lp_type;

View file

@ -34,7 +34,7 @@
* Pixel format helpers.
*/
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include "pipe/p_format.h"

View file

@ -114,10 +114,10 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
case UTIL_FORMAT_TYPE_UNSIGNED:
if(type.floating) {
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) {
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)

View file

@ -289,17 +289,17 @@ pos_update(struct lp_build_interp_soa_context *bld, int quad_index)
/* top-right or bottom-right quad in block */
/* build x += xstep */
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) {
/* bottom-left quad in block */
/* build y += ystep */
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 */
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");

View file

@ -41,7 +41,7 @@
#define LP_BLD_INTERP_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include "tgsi/tgsi_exec.h"

View file

@ -37,7 +37,7 @@
#define LP_BLD_INTR_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
/**

View file

@ -193,7 +193,7 @@ lp_build_compare(LLVMBuilderRef builder,
if(table[func].gt &&
((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, "");
b = LLVMBuildXor(builder, b, msb, "");
}

View file

@ -37,7 +37,7 @@
#define LP_BLD_LOGIC_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include "pipe/p_defines.h" /* For PIPE_FUNC_xxx */

View file

@ -164,7 +164,7 @@ lp_build_unpack2(LLVMBuilderRef builder,
if(dst_type.sign && src_type.sign) {
/* 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
/* Most significant bits always zero */
@ -361,7 +361,7 @@ lp_build_packs2(LLVMBuilderRef builder,
if(clamp) {
struct lp_build_context bld;
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);
lo = lp_build_min(&bld, lo, dst_max);
hi = lp_build_min(&bld, hi, dst_max);

View file

@ -37,7 +37,7 @@
#define LP_BLD_PACK_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct lp_type;

View file

@ -173,7 +173,7 @@ lp_build_sample_offset(struct lp_build_context *bld,
LLVMValueRef x_stride;
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) {
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, "");
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, "");
x_offset_lo = lp_build_mul(bld, x_lo, x_stride_lo);

View file

@ -36,7 +36,7 @@
#define LP_BLD_SAMPLE_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct pipe_texture;
struct pipe_sampler_state;

View file

@ -292,7 +292,7 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
int chan;
for (chan = 0; chan < 4; chan++) {
LLVMValueRef border_chan =
lp_build_const_scalar(bld->texel_type,
lp_build_const_vec(bld->texel_type,
bld->static_state->border_color[chan]);
texel[chan] = lp_build_select(&bld->texel_bld, use_border,
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 *int_coord_bld = &bld->int_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 half = lp_build_const_scalar(coord_bld->type, 0.5);
LLVMValueRef two = lp_build_const_vec(coord_bld->type, 2.0);
LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5);
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_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 {
LLVMValueRef min, max;
/* 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);
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) {
/* min = -1.0 / (2 * length) = -0.5 / length */
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));
/* max = 1.0 - 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 {
/* 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);
coord = lp_build_clamp(coord_bld, coord, min, max);
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;
/* min = -1.0 / (2 * length) = -0.5 / length */
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));
/* max = 1.0 - 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 *int_coord_bld = &bld->int_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_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);
@ -708,7 +708,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
}
else {
/* 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);
}
/* 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) {
/* min = -1.0 / (2 * length) = -0.5 / length */
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));
/* max = length - 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 {
/* 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);
}
/* coord = clamp(coord, min, max) */
@ -843,87 +843,98 @@ lp_build_lod_selector(struct lp_build_sample_context *bld,
LLVMValueRef depth)
{
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);
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);
}
if (bld->static_state->min_lod == bld->static_state->max_lod) {
/* User is forcing sampling from a particular mipmap level.
* This is hit during mipmap generation.
*/
return LLVMConstReal(LLVMFloatType(), bld->static_state->min_lod);
}
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.
* 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,
lp_build_max(float_bld, dtdx, dtdy),
lp_build_int_to_float(float_bld, height), "");
rho = lp_build_max(float_bld, rho, max);
if (dims > 2) {
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);
}
}
/* 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,
lp_build_max(float_bld, drdx, drdy),
lp_build_int_to_float(float_bld, depth), "");
lp_build_max(float_bld, dtdx, dtdy),
lp_build_int_to_float(float_bld, height), "");
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);
/* 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_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);
}
@ -1215,7 +1226,7 @@ static LLVMValueRef
lp_build_cube_ima(struct lp_build_context *coord_bld, LLVMValueRef 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 ima = lp_build_mul(coord_bld, negHalf,
lp_build_rcp(coord_bld, absCoord));
@ -1235,7 +1246,7 @@ lp_build_cube_coord(struct lp_build_context *coord_bld,
LLVMValueRef coord, LLVMValueRef ima)
{
/* 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;
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.
* 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 *colors_out)
{
struct lp_build_context *float_bld = &bld->float_bld;
const unsigned mip_filter = bld->static_state->min_mip_filter;
const unsigned min_filter = bld->static_state->min_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 img_stride0_vec = NULL, img_stride1_vec = NULL;
LLVMValueRef data_ptr0, data_ptr1;
int chan;
/*
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) {
/* always use mip level 0 */
ilevel0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
}
else {
/* compute float LOD */
lod = lp_build_lod_selector(bld, s, t, r, width, height, depth);
if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
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) {
/* 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);
if (dims >= 2) {
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) {
LLVMValueRef face, face_s, face_t;
@ -1538,62 +1636,67 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
/*
* Get/interpolate texture colors.
*/
/* XXX temporarily force this path: */
if (1 /*min_filter == mag_filter*/) {
/* same filter for minification or magnification */
LLVMValueRef colors0[4], colors1[4];
if (min_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(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];
}
}
if (min_filter == mag_filter) {
/* no need to distinquish between minification and magnification */
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);
}
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.
*/
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 *rgba)
{
LLVMValueRef mask = lp_build_int_const_scalar(dst_type, 0xff);
LLVMValueRef mask = lp_build_const_int_vec(dst_type, 0xff);
unsigned chan;
/* Decode the input vector components */
@ -1617,7 +1720,7 @@ lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder,
input = packed;
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)
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, "");
/* 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, "");
t = LLVMBuildAdd(builder, t, i32_c128, "");
/* 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, "");
t_ipart = LLVMBuildAShr(builder, t, i32_c8, "");
/* 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, "");
t_fpart = LLVMBuildAnd(builder, t, i32_c255, "");
@ -1856,7 +1959,7 @@ lp_build_sample_compare(struct lp_build_sample_context *bld,
}
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 */
for(chan = 0; chan < 3; ++chan)

View file

@ -37,7 +37,7 @@
#define LP_BLD_STRUCT_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include <llvm-c/Target.h>
#include "util/u_debug.h"

View file

@ -144,9 +144,9 @@ lp_build_broadcast_aos(struct lp_build_context *bld,
#endif
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)
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);
if(tmp)

View file

@ -37,7 +37,7 @@
#define LP_BLD_SWIZZLE_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct lp_type;

View file

@ -35,7 +35,7 @@
#ifndef LP_BLD_TGSI_H
#define LP_BLD_TGSI_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct tgsi_token;

View file

@ -475,7 +475,7 @@ emit_store(
break;
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);
break;
@ -996,7 +996,7 @@ emit_instruction(
src0 = emit_fetch( bld, inst, 0, chan_index );
src1 = emit_fetch( bld, inst, 1, 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);
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);
for( i = 0; i < size; ++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 )
bld.immediates[num_immediates][i] = bld.base.undef;
num_immediates++;

View file

@ -37,9 +37,9 @@
#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>
/**

View file

@ -142,8 +142,10 @@ cell_is_format_supported( struct pipe_screen *screen,
format == PIPE_FORMAT_A8B8G8R8_SRGB)
return FALSE;
if (tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
if (!winsys->is_displaytarget_format_supported(winsys, format))
if (tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_SCANOUT |
PIPE_TEXTURE_USAGE_SHARED)) {
if (!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
return FALSE;
}

View file

@ -105,6 +105,7 @@ cell_displaytarget_layout(struct pipe_screen *screen,
/* Round up the surface size to a multiple of the tile size?
*/
ct->dt = winsys->displaytarget_create(winsys,
ct->base->tex_usage,
ct->base.format,
ct->base.width0,
ct->base.height0,

View file

@ -118,6 +118,7 @@ struct pipe_context *brw_create_context(struct pipe_screen *screen,
brw->sws = brw_screen(screen)->sws;
brw->chipset = brw_screen(screen)->chipset;
brw_tex_init( brw );
brw_pipe_blend_init( brw );
brw_pipe_depth_stencil_init( brw );
brw_pipe_framebuffer_init( brw );

View file

@ -12,7 +12,11 @@ Done so far is:
- 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
- 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
- translate the remaining bits of texture sampling state
- translate TGSI control flow instructions, and all other remaining opcodes
- integrate with the draw module for VS code generation
@ -57,7 +59,7 @@ Requirements
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:
@ -67,6 +69,9 @@ Requirements
http://people.freedesktop.org/~jrfonseca/llvm/ and set the LLVM environment
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)
- 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
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
put in a stand-alone Gallium state -> LLVM IR translation module.
- The driver-independent parts of the LLVM / Gallium code are found in
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++
interfaces very closely, and appear to be complete enough for code
generation. See
http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html
for a stand-alone example.
See the llvm-c/Core.h file for reference.

View file

@ -204,8 +204,10 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
return FALSE;
}
if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
if(!winsys->is_displaytarget_format_supported(winsys, format))
if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_SCANOUT |
PIPE_TEXTURE_USAGE_SHARED)) {
if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
return FALSE;
}

View file

@ -34,7 +34,7 @@
#ifndef LP_SCREEN_H
#define LP_SCREEN_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include <llvm-c/ExecutionEngine.h>
#include "pipe/p_screen.h"

View file

@ -31,7 +31,7 @@
#ifndef LP_STATE_H
#define LP_STATE_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include "pipe/p_state.h"
#include "tgsi/tgsi_scan.h"

View file

@ -252,7 +252,7 @@ generate_tri_edge_mask(LLVMBuilderRef builder,
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);
@ -367,7 +367,7 @@ build_int32_vec_const(int value)
i32_type.norm = FALSE; /* values are not normalized */
i32_type.width = 32; /* 32-bit int values */
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);
}

View file

@ -41,7 +41,7 @@
#include <stdio.h>
#include <float.h>
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include <llvm-c/Analysis.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>

View file

@ -29,7 +29,7 @@
#include <stdlib.h>
#include <stdio.h>
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
#include <llvm-c/Analysis.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>

View file

@ -29,7 +29,7 @@
#define LP_TEX_SAMPLE_H
#include "os/os_llvm.h"
#include "gallivm/lp_bld.h"
struct lp_sampler_static_state;

View file

@ -103,6 +103,7 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
unsigned height = align(lpt->base.height0, TILE_SIZE);
lpt->dt = winsys->displaytarget_create(winsys,
lpt->base.tex_usage,
lpt->base.format,
width, height,
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 *
llvmpipe_get_tex_surface(struct pipe_screen *screen,
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_destroy = llvmpipe_texture_destroy;
screen->texture_get_handle = llvmpipe_texture_get_handle;
screen->get_tex_surface = llvmpipe_get_tex_surface;
screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;

View file

@ -173,8 +173,10 @@ softpipe_is_format_supported( struct pipe_screen *screen,
break;
}
if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
if(!winsys->is_displaytarget_format_supported(winsys, format))
if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_SCANOUT |
PIPE_TEXTURE_USAGE_SHARED)) {
if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
return FALSE;
}

View file

@ -91,6 +91,7 @@ softpipe_displaytarget_layout(struct pipe_screen *screen,
/* Round up the surface size to a multiple of the tile size?
*/
spt->dt = winsys->displaytarget_create(winsys,
spt->base.tex_usage,
spt->base.format,
spt->base.width0,
spt->base.height0,
@ -139,8 +140,6 @@ softpipe_texture_create(struct pipe_screen *screen,
}
static void
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.
*/
@ -461,6 +509,8 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
{
screen->texture_create = softpipe_texture_create;
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->tex_surface_destroy = softpipe_tex_surface_destroy;

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

View file

@ -44,6 +44,7 @@ extern "C" {
#endif
struct winsys_handle;
struct pipe_screen;
struct pipe_context;
@ -68,6 +69,7 @@ struct sw_winsys
boolean
(*is_displaytarget_format_supported)( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format );
/**
@ -83,11 +85,29 @@ struct sw_winsys
*/
struct sw_displaytarget *
(*displaytarget_create)( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format,
unsigned width, unsigned height,
unsigned alignment,
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
*/

View file

@ -35,7 +35,6 @@
#include "state_tracker/drm_api.h"
#include "state_tracker/dri1_api.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_context.h"
#include "pipe/p_context.h"
#include "dri_context.h"
@ -167,7 +166,7 @@ dri_make_current(__DRIcontext * cPriv,
* flush_frontbuffer directly (in front-buffer rendering), it
* 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) {
dri1_update_drawables(ctx, draw, read);

View file

@ -39,8 +39,8 @@
#include "main/renderbuffer.h"
#include "state_tracker/drm_api.h"
#include "state_tracker/dri1_api.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_cb_fbo.h"
#include "util/u_format.h"

View file

@ -36,234 +36,27 @@
#include "native.h"
#include "egl_g3d.h"
#include "egl_g3d_st.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.
*/
static const struct egl_g3d_st *
static struct st_api *
egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
const struct egl_g3d_st *stapi;
struct st_api *stapi;
EGLint idx = -1;
switch (ctx->ClientAPI) {
case EGL_OPENGL_ES_API:
switch (ctx->ClientVersion) {
case 1:
idx = EGL_G3D_ST_OPENGL_ES;
idx = ST_API_OPENGL_ES1;
break;
case 2:
idx = EGL_G3D_ST_OPENGL_ES2;
idx = ST_API_OPENGL_ES2;
break;
default:
_eglLog(_EGL_WARNING, "unknown client version %d",
@ -272,10 +65,10 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
}
break;
case EGL_OPENVG_API:
idx = EGL_G3D_ST_OPENVG;
idx = ST_API_OPENVG;
break;
case EGL_OPENGL_API:
idx = EGL_G3D_ST_OPENGL;
idx = ST_API_OPENGL;
break;
default:
_eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
@ -299,10 +92,10 @@ egl_g3d_init_st(_EGLDriver *drv)
if (gdrv->api_mask)
return;
for (i = 0; i < NUM_EGL_G3D_STS; i++) {
gdrv->stapis[i] = egl_g3d_get_st(i);
for (i = 0; i < ST_API_COUNT; i++) {
gdrv->stapis[i] = egl_g3d_create_st_api(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)
@ -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
static void
@ -443,19 +207,89 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
#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.
*/
static EGLint
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);
const struct native_config **native_configs;
int num_configs, i;
native_configs = gdpy->native->get_configs(gdpy->native,
&num_configs);
native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
if (!num_configs) {
if (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++) {
EGLint api_mask;
struct egl_g3d_config *gconf;
EGLBoolean valid;
gconf = CALLOC_STRUCT(egl_g3d_config);
if (!gconf)
continue;
_eglInitConfig(&gconf->base, dpy, id);
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);
if (gconf) {
_eglInitConfig(&gconf->base, dpy, id);
if (!egl_g3d_init_config(drv, dpy, &gconf->base, native_configs[i])) {
free(gconf);
continue;
}
#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);
id++;
_eglAddConfig(dpy, &gconf->base);
id++;
}
}
free(native_configs);
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
egl_g3d_invalid_surface(struct native_display *ndpy,
struct native_surface *nsurf,
@ -525,11 +323,15 @@ egl_g3d_invalid_surface(struct native_display *ndpy,
{
/* XXX not thread safe? */
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)
gctx->force_validate = TRUE;
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
}
static struct native_event_handler egl_g3d_native_event_handler = {
@ -545,6 +347,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
_eglReleaseDisplayResources(drv, dpy);
_eglCleanupDisplay(dpy);
if (gdpy->pipe)
gdpy->pipe->destroy(gdpy->pipe);
if (dpy->Screens) {
for (i = 0; i < dpy->NumScreens; 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);
}
if (gdpy->smapi)
egl_g3d_destroy_st_manager(gdpy->smapi);
if (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->screen->update_buffer = egl_g3d_update_buffer;
egl_g3d_init_st(&gdrv->base);
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
/* enable MESA_screen_surface before adding (and validating) configs */
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_config *gconf = egl_g3d_config(conf);
struct egl_g3d_context *gctx;
const __GLcontextModes *mode;
gctx = CALLOC_STRUCT(egl_g3d_context);
if (!gctx) {
@ -648,24 +461,14 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
return NULL;
}
mode = &gconf->native->mode;
gctx->pipe = gdpy->native->screen->context_create(
gdpy->native->screen,
(void *) &gctx->base);
if (!gctx->pipe) {
gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi,
&gconf->stvis, (gshare) ? gshare->stctxi : NULL);
if (!gctx->stctxi) {
free(gctx);
return NULL;
}
gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
(gshare) ? gshare->st_ctx : NULL);
if (!gctx->st_ctx) {
gctx->pipe->destroy(gctx->pipe);
free(gctx);
return NULL;
}
gctx->stctxi->st_manager_private = (void *) &gctx->base;
return &gctx->base;
}
@ -682,9 +485,7 @@ destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
if (!dpy->Initialized)
_eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
egl_g3d_realloc_context(dpy, &gctx->base);
/* it will destroy the associated pipe context */
gctx->stapi->st_destroy_context(gctx->st_ctx);
gctx->stctxi->destroy(gctx->stctxi);
free(gctx);
}
@ -786,14 +587,20 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
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;
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;
}
@ -849,7 +656,8 @@ destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
if (!dpy->Initialized)
_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);
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_surface *gdraw = egl_g3d_surface(draw);
struct egl_g3d_surface *gread = egl_g3d_surface(read);
struct egl_g3d_context *old_gctx;
EGLBoolean ok = EGL_TRUE;
@ -878,39 +687,29 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
if (old_gctx) {
/* 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);
/*
* 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) {
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) {
/* XXX: need to pass the winsys argument for
* flush_frontbuffer in the fourth parameter here:
*/
ok = gctx->stapi->st_make_current(gctx->st_ctx,
gctx->draw.st_fb,
gctx->read.st_fb,
NULL);
if (ok) {
egl_g3d_validate_context(dpy, &gctx->base);
if (gdraw->base.Type == EGL_WINDOW_BIT) {
gctx->base.WindowRenderBuffer =
(gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
}
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi);
if (gread != gdraw) {
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi,
gread->stfbi);
}
if (gdraw->base.Type == EGL_WINDOW_BIT) {
gctx->base.WindowRenderBuffer =
(gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
}
}
}
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;
}
@ -937,15 +736,17 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
return EGL_TRUE;
/* 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;
if (ctx && ctx->DrawSurface == surf)
gctx = egl_g3d_context(ctx);
/* flush if the surface is current */
if (gctx)
gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
if (gctx) {
gctx->stctxi->flush(gctx->stctxi,
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
}
return gsurf->native->swap_buffers(gsurf->native);
}
@ -985,7 +786,7 @@ get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf,
return NULL;
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);
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_surface *psurf;
if (!gsurf->render_surface)
if (!gsurf->render_texture)
return EGL_TRUE;
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 */
if (ctx && ctx->DrawSurface == &gsurf->base) {
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);
}
/* 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);
if (psurf) {
struct pipe_context pipe;
struct pipe_surface *psrc;
/**
* XXX This is hacky. If we might allow the EGLDisplay to create a pipe
* context of its own and use the blitter context for this.
*/
memset(&pipe, 0, sizeof(pipe));
pipe.screen = screen;
psrc = screen->get_tex_surface(screen, gsurf->render_texture,
0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
if (psrc) {
gdpy->pipe->surface_copy(gdpy->pipe, psurf, 0, 0,
psrc, 0, 0, psurf->width, psurf->height);
pipe_surface_reference(&psrc, NULL);
util_surface_copy(&pipe, FALSE, psurf, 0, 0,
gsurf->render_surface, 0, 0, psurf->width, psurf->height);
nsurf->flush_frontbuffer(nsurf);
}
pipe_surface_reference(&psurf, NULL);
nsurf->flush_frontbuffer(nsurf);
}
nsurf->destroy(nsurf);
@ -1048,8 +856,16 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
static EGLBoolean
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);
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;
}
@ -1079,10 +895,10 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
/* in case this is called before a display is initialized */
egl_g3d_init_st(&gdrv->base);
for (i = 0; i < NUM_EGL_G3D_STS; i++) {
const struct egl_g3d_st *stapi = gdrv->stapis[i];
for (i = 0; i < ST_API_COUNT; i++) {
struct st_api *stapi = gdrv->stapis[i];
if (stapi) {
proc = (_EGLProc) stapi->st_get_proc_address(procname);
proc = (_EGLProc) stapi->get_proc_address(stapi, procname);
if (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);
_EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
struct egl_g3d_context *gctx;
enum pipe_format target_format;
int target;
enum pipe_format internal_format;
enum st_texture_type target;
if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
@ -1110,10 +926,10 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
switch (gsurf->base.TextureFormat) {
case EGL_TEXTURE_RGB:
target_format = PIPE_FORMAT_R8G8B8_UNORM;
internal_format = PIPE_FORMAT_R8G8B8_UNORM;
break;
case EGL_TEXTURE_RGBA:
target_format = PIPE_FORMAT_B8G8R8A8_UNORM;
internal_format = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
default:
return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
@ -1129,21 +945,24 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
if (!es1)
return EGL_TRUE;
if (!gsurf->render_surface)
if (!gsurf->render_texture)
return EGL_FALSE;
/* flush properly if the surface is bound */
if (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);
}
gctx = egl_g3d_context(es1);
gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
target, gsurf->base.MipmapLevel, target_format);
gsurf->base.BoundToTexture = EGL_TRUE;
if (gctx->stctxi->teximage) {
if (!gctx->stctxi->teximage(gctx->stctxi, target,
gsurf->base.MipmapLevel, internal_format,
gsurf->render_texture, gsurf->base.MipmapTexture))
return EGL_FALSE;
gsurf->base.BoundToTexture = EGL_TRUE;
}
return EGL_TRUE;
}
@ -1160,14 +979,15 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
if (buffer != EGL_BACK_BUFFER)
return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
if (gsurf->render_surface) {
if (gsurf->render_texture) {
_EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
/* what if the context the surface binds to is no longer current? */
if (gctx)
gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
ST_TEXTURE_2D, gsurf->base.MipmapLevel);
if (gctx) {
gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D,
gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE);
}
}
gsurf->base.BoundToTexture = EGL_FALSE;
@ -1279,6 +1099,12 @@ static void
egl_g3d_unload(_EGLDriver *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);
free(gdrv);

View file

@ -39,11 +39,11 @@
#include "eglmode.h"
#include "native.h"
#include "egl_st.h"
#include "egl_g3d_st.h"
struct egl_g3d_driver {
_EGLDriver base;
const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS];
struct st_api *stapis[ST_API_COUNT];
EGLint api_mask;
EGLint probe_key;
@ -51,35 +51,34 @@ struct egl_g3d_driver {
struct egl_g3d_display {
struct native_display *native;
};
struct egl_g3d_buffer {
struct st_framebuffer *st_fb;
uint attachment_mask;
struct st_manager *smapi;
struct pipe_context *pipe;
};
struct egl_g3d_context {
_EGLContext base;
const struct egl_g3d_st *stapi;
struct pipe_context *pipe;
struct st_api *stapi;
struct st_context *st_ctx;
EGLBoolean force_validate;
struct egl_g3d_buffer draw, read;
struct st_context_iface *stctxi;
};
struct egl_g3d_surface {
_EGLSurface base;
struct st_visual stvis;
struct st_framebuffer_iface *stfbi;
struct native_surface *native;
enum native_attachment render_att;
struct pipe_surface *render_surface;
struct pipe_texture *render_texture;
unsigned int sequence_number;
};
struct egl_g3d_config {
_EGLConfig base;
const struct native_config *native;
struct st_visual stvis;
};
struct egl_g3d_image {

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

View file

@ -1,8 +1,8 @@
/*
* 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
* 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
* 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 _EGL_ST_H_
#define _EGL_ST_H_
#include "GL/gl.h" /* for GL types */
#include "GL/internal/glcore.h" /* for __GLcontextModes */
#ifndef _EGL_G3D_ST_H_
#define _EGL_G3D_ST_H_
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#include "pipe/p_context.h"
#include "state_tracker/st_api.h"
#include "egltypedefs.h"
/* avoid calling st functions directly */
#if 1
struct st_api *
egl_g3d_create_st_api(enum st_api_type api);
#define ST_SURFACE_FRONT_LEFT 0
#define ST_SURFACE_BACK_LEFT 1
#define ST_SURFACE_FRONT_RIGHT 2
#define ST_SURFACE_BACK_RIGHT 3
struct st_manager *
egl_g3d_create_st_manager(_EGLDisplay *dpy);
#define ST_TEXTURE_2D 0x2
void
egl_g3d_destroy_st_manager(struct st_manager *smapi);
struct st_context;
struct st_framebuffer;
typedef void (*st_proc)();
struct st_framebuffer_iface *
egl_g3d_create_st_framebuffer(_EGLSurface *surf);
#else
#include "state_tracker/st_public.h"
#endif
void
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
/* remember to update egl_g3d_get_st() when update the enums */
enum egl_g3d_st_api {
EGL_G3D_ST_OPENGL_ES = 0,
EGL_G3D_ST_OPENVG,
EGL_G3D_ST_OPENGL_ES2,
EGL_G3D_ST_OPENGL,
/**
* Return the EGL_<api>_BIT of the st api.
*/
static INLINE int
egl_g3d_st_api_bit(enum st_api_type api)
{
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 {
#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__);
#include "st_public_tmp.h"
/* fields must be added here */
EGLint api_bit;
};
return bit;
}
const struct egl_g3d_st *
egl_g3d_get_st(enum egl_g3d_st_api api);
#endif /* _EGL_ST_H_ */
#endif /* _EGL_G3D_ST_H_ */

View file

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

View file

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

View file

@ -38,6 +38,7 @@ SYS_LIBS = -lm -pthread
INCLUDE_DIRS = \
-I$(TOP)/src/mesa \
-I$(TOP)/src/gallium/include
.c.o:

View file

@ -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 struct st_module st_module_OpenGL_ES1 = {
.api = ST_API_OPENGL_ES1,
.create_api = st_manager_create_api
};

View file

@ -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 struct st_module st_module_OpenGL_ES2 = {
.api = ST_API_OPENGL_ES2,
.create_api = st_manager_create_api
};

View file

@ -12,6 +12,7 @@ C_SOURCES = \
glx_api.c \
glx_getproc.c \
glx_usefont.c \
xm_api.c
xm_api.c \
xm_st.c
include ../../../Makefile.template

View file

@ -20,6 +20,7 @@ if env['platform'] == 'linux' \
'glx_getproc.c',
'glx_usefont.c',
'xm_api.c',
'xm_st.c',
]
)
Export('st_xlib')

View file

@ -35,12 +35,9 @@
#include "xm_api.h"
#include "main/context.h"
#include "main/config.h"
#include "main/macros.h"
#include "main/imports.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. */
@ -1304,7 +1301,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
if (MakeCurrent_PrevContext == src) {
_mesa_Flush();
}
st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask );
XMesaCopyContext(xm_src, xm_dst, mask);
}

View file

@ -54,11 +54,9 @@
#endif
#include "xm_api.h"
#include "main/context.h"
#include "main/framebuffer.h"
#include "xm_st.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_context.h"
#include "main/context.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
@ -72,19 +70,56 @@
* global.
*/
static struct xm_driver driver;
static struct st_api *stapi;
void xmesa_set_driver( const struct xm_driver *templ )
{
driver = *templ;
stapi = driver.create_st_api();
}
/**
* Global X driver lock
*/
pipe_mutex _xmesa_lock;
static XMesaDisplay
xmesa_init_display( Display *display )
{
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 *****/
@ -194,12 +229,13 @@ void
xmesa_get_window_size(Display *dpy, XMesaBuffer b,
GLuint *width, GLuint *height)
{
XMesaDisplay xmdpy = xmesa_init_display(dpy);
Status stat;
pipe_mutex_lock(_xmesa_lock);
pipe_mutex_lock(xmdpy->mutex);
XSync(b->xm_visual->display, 0); /* added for Chromium */
stat = get_drawable_size(dpy, b->ws.drawable, width, height);
pipe_mutex_unlock(_xmesa_lock);
pipe_mutex_unlock(xmdpy->mutex);
if (!stat) {
/* probably querying a window that's recently been destroyed */
@ -273,49 +309,43 @@ choose_pixel_format(XMesaVisual v)
return 0;
}
/**
* Query the default gallium screen for a Z/Stencil format that
* at least matches the given depthBits and stencilBits.
* Choose a depth/stencil format that is "better" than the given depth and
* stencil sizes.
*/
static void
xmesa_choose_z_stencil_format(int depthBits, int stencilBits,
enum pipe_format *depthFormat,
enum pipe_format *stencilFormat)
static enum pipe_format
choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil)
{
const enum pipe_texture_target target = PIPE_TEXTURE_2D;
const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE |
PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO);
static enum pipe_format formats[] = {
PIPE_FORMAT_S8Z24_UNORM,
PIPE_FORMAT_Z24S8_UNORM,
PIPE_FORMAT_Z16_UNORM,
PIPE_FORMAT_Z32_UNORM
};
int i;
enum pipe_format formats[8], fmt;
int count, 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 */
for (i = 0; i < Elements(formats); i++) {
if (screen->is_format_supported(screen, formats[i],
fmt = PIPE_FORMAT_NONE;
for (i = 0; i < count; i++) {
if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
target, tex_usage, geom_flags)) {
*depthFormat = formats[i];
fmt = formats[i];
break;
}
}
if (stencilBits) {
*stencilFormat = *depthFormat;
}
/* XXX we should check that he chosen format has at least as many bits
* as what was requested.
*/
return fmt;
}
@ -324,7 +354,7 @@ xmesa_choose_z_stencil_format(int depthBits, int stencilBits,
/***** Linked list of XMesaBuffers *****/
/**********************************************************************/
XMesaBuffer XMesaBufferList = NULL;
static XMesaBuffer XMesaBufferList = NULL;
/**
@ -342,13 +372,15 @@ static XMesaBuffer
create_xmesa_buffer(Drawable d, BufferType type,
XMesaVisual vis, Colormap cmap)
{
XMesaDisplay xmdpy = xmesa_init_display(vis->display);
XMesaBuffer b;
GLframebuffer *fb;
enum pipe_format colorFormat, depthFormat, stencilFormat;
uint width, height;
ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
if (!xmdpy)
return NULL;
b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
if (!b)
return NULL;
@ -361,24 +393,12 @@ create_xmesa_buffer(Drawable d, BufferType type,
b->type = type;
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);
/*
* Create framebuffer, but we'll plug in our own renderbuffers below.
*/
b->stfb = st_create_framebuffer(&vis->mesa_visual,
colorFormat, depthFormat, stencilFormat,
width, height,
(void *) b);
fb = &b->stfb->Base;
b->stfb = xmesa_create_st_framebuffer(xmdpy, b);
/* GLX_EXT_texture_from_pixmap */
b->TextureTarget = 0;
@ -422,24 +442,21 @@ xmesa_free_buffer(XMesaBuffer buffer)
for (b = XMesaBufferList; b; b = b->Next) {
if (b == buffer) {
struct gl_framebuffer *fb = &buffer->stfb->Base;
/* unlink buffer from list */
if (prev)
prev->Next = buffer->Next;
else
XMesaBufferList = buffer->Next;
/* mark as delete pending */
fb->DeletePending = GL_TRUE;
/* Since the X window for the XMesaBuffer is going away, we don't
* want to dereference this pointer in the future.
*/
b->ws.drawable = 0;
/* Unreference. If count = zero we'll really delete the buffer */
_mesa_reference_framebuffer(&fb, NULL);
/* XXX we should move the buffer to a delete-pending list and destroy
* the buffer until it is no longer current.
*/
xmesa_destroy_st_framebuffer(buffer->stfb);
free(buffer);
@ -596,10 +613,12 @@ XMesaVisual XMesaCreateVisual( Display *display,
GLint level,
GLint visualCaveat )
{
XMesaDisplay xmdpy = xmesa_init_display(display);
XMesaVisual v;
GLint red_bits, green_bits, blue_bits, alpha_bits;
xmesa_init( display );
if (!xmdpy)
return NULL;
/* For debugging only */
if (_mesa_getenv("MESA_XSYNC")) {
@ -681,6 +700,26 @@ XMesaVisual XMesaCreateVisual( Display *display,
accum_blue_size, accum_alpha_size,
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 */
v->mesa_visual.level = level;
return v;
@ -696,17 +735,12 @@ void XMesaDestroyVisual( XMesaVisual v )
/**
* Do one-time initializations.
* Do per-display initializations.
*/
void
xmesa_init( Display *display )
{
static GLboolean firstTime = GL_TRUE;
if (firstTime) {
pipe_mutex_init(_xmesa_lock);
screen = driver.create_pipe_screen( display );
firstTime = GL_FALSE;
}
xmesa_init_display(display);
}
@ -720,51 +754,33 @@ xmesa_init( Display *display )
PUBLIC
XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
{
struct pipe_context *pipe = NULL;
XMesaDisplay xmdpy = xmesa_init_display(v->display);
XMesaContext c;
GLcontext *mesaCtx;
uint pf;
xmesa_init( v->display );
if (!xmdpy)
return NULL;
/* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
if (!c)
return NULL;
pf = choose_pixel_format(v);
assert(pf);
c->xm_visual = v;
c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
c->xm_read_buffer = NULL;
if (screen == NULL)
goto fail;
/* 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);
c->st = stapi->create_context(stapi, xmdpy->smapi,
&v->stvis, (share_list) ? share_list->st : NULL);
if (c->st == NULL)
goto fail;
mesaCtx = c->st->ctx;
c->st->ctx->DriverCtx = c;
c->st->st_manager_private = (void *) c;
return c;
fail:
if (c->st)
st_destroy_context(c->st);
else if (pipe)
pipe->destroy(pipe);
c->st->destroy(c->st);
free(c);
return NULL;
@ -775,7 +791,7 @@ fail:
PUBLIC
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
* outlive it, causing segfaults
@ -881,7 +897,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
{
GET_CURRENT_CONTEXT(ctx);
XMesaBuffer b;
GLuint width, height;
assert(v);
@ -889,19 +904,18 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
if (!b)
return NULL;
/* get pixmap size, update framebuffer/renderbuffer dims */
xmesa_get_window_size(v->display, b, &width, &height);
_mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
/* get pixmap size */
xmesa_get_window_size(v->display, b, &b->width, &b->height);
if (target == 0) {
/* examine dims */
if (ctx->Extensions.ARB_texture_non_power_of_two) {
target = GLX_TEXTURE_2D_EXT;
}
else if ( _mesa_bitcount(width) == 1
&& _mesa_bitcount(height) == 1) {
else if ( _mesa_bitcount(b->width) == 1
&& _mesa_bitcount(b->height) == 1) {
/* power of two size */
if (height == 1) {
if (b->height == 1) {
target = GLX_TEXTURE_1D_EXT;
}
else {
@ -974,25 +988,22 @@ XMesaDestroyBuffer(XMesaBuffer b)
/**
* Query the current window size and update the corresponding GLframebuffer
* 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.
* Query the current drawable size and notify the binding context.
*/
void
xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
xmesa_check_buffer_size(XMesaBuffer b)
{
GLuint width, height;
xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
st_resize_framebuffer(drawBuffer->stfb, width, height);
XMesaContext xmctx = XMesaGetCurrentContext();
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.
*/
@ -1017,22 +1028,21 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
c->xm_read_buffer == readBuffer)
return GL_TRUE;
xmesa_check_buffer_size(drawBuffer);
if (readBuffer != drawBuffer)
xmesa_check_buffer_size(readBuffer);
c->xm_buffer = drawBuffer;
c->xm_read_buffer = readBuffer;
st_make_current(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);
stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb);
/* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
drawBuffer->wasCurrent = GL_TRUE;
}
else {
/* Detach */
st_make_current( NULL, NULL, NULL, NULL );
stapi->make_current(stapi, NULL, NULL, NULL);
}
return GL_TRUE;
@ -1051,14 +1061,8 @@ GLboolean XMesaUnbindContext( XMesaContext c )
XMesaContext XMesaGetCurrentContext( void )
{
GET_CURRENT_CONTEXT(ctx);
if (ctx) {
XMesaContext xmesa = xmesa_context(ctx);
return xmesa;
}
else {
return 0;
}
struct st_context_iface *st = stapi->get_current(stapi);
return (XMesaContext) (st) ? st->st_manager_private : NULL;
}
@ -1070,17 +1074,17 @@ XMesaContext XMesaGetCurrentContext( void )
PUBLIC
void XMesaSwapBuffers( XMesaBuffer b )
{
struct pipe_surface *frontLeftSurf;
XMesaContext xmctx = XMesaGetCurrentContext();
st_swapbuffers(b->stfb, &frontLeftSurf, NULL);
if (frontLeftSurf) {
screen->flush_frontbuffer( screen,
frontLeftSurf,
&b->ws );
if (xmctx && xmctx->xm_buffer == b) {
xmctx->st->flush( xmctx->st,
PIPE_FLUSH_RENDER_CACHE |
PIPE_FLUSH_SWAPBUFFERS |
PIPE_FLUSH_FRAME,
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 )
{
struct pipe_surface *surf_front;
struct pipe_surface *surf_back;
struct pipe_context *pipe = NULL; /* XXX fix */
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);
xmesa_copy_st_framebuffer(b->stfb,
ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT,
x, y, width, height);
}
@ -1112,7 +1104,14 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
void XMesaFlush( XMesaContext c )
{
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 );
}
}
@ -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);
}

View file

@ -58,8 +58,7 @@ and create a window, you must do the following to use the X/Mesa interface:
#include "main/mtypes.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_api.h"
#include "os/os_thread.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/Xutil.h>
typedef struct xmesa_display *XMesaDisplay;
typedef struct xmesa_buffer *XMesaBuffer;
typedef struct xmesa_context *XMesaContext;
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.
@ -258,16 +268,13 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
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.
* Basically corresponds to an XVisualInfo.
@ -280,6 +287,8 @@ struct xmesa_visual {
GLint BitsPerPixel; /* True bits per pixel for XImages */
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.
*/
struct xmesa_context {
struct st_context *st;
struct st_context_iface *st;
XMesaVisual xm_visual; /** pixel format info */
XMesaBuffer xm_buffer; /** current drawbuffer */
XMesaBuffer xm_read_buffer; /** current readbuffer */
@ -311,7 +320,7 @@ typedef enum {
* Basically corresponds to a GLXDrawable.
*/
struct xmesa_buffer {
struct st_framebuffer *stfb;
struct st_framebuffer_iface *stfb;
struct xlib_drawable ws;
GLboolean wasCurrent; /* was ever the current buffer? */
@ -335,33 +344,15 @@ struct xmesa_buffer {
GLint TextureMipmap; /** 0 or 1 */
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
xmesa_init(Display *dpy);
extern void
xmesa_delete_framebuffer(struct gl_framebuffer *fb);
extern XMesaBuffer
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);
extern void
xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer);
xmesa_check_buffer_size(XMesaBuffer b);
extern void
xmesa_destroy_buffers_on_display(Display *dpy);
@ -378,13 +369,13 @@ xmesa_destroy_buffers_on_display(Display *dpy);
static INLINE GLuint
xmesa_buffer_width(XMesaBuffer b)
{
return b->stfb->Base.Width;
return b->width;
}
static INLINE GLuint
xmesa_buffer_height(XMesaBuffer b)
{
return b->stfb->Base.Height;
return b->height;
}

View file

@ -26,19 +26,23 @@
*
**************************************************************************/
#ifndef XM_WINSYS_H
#define XM_WINSYS_H
#ifndef XM_PUBLIC_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.
*/
struct xm_driver {
struct pipe_screen *(*create_pipe_screen)( Display *display );
struct st_api *(*create_st_api)( void );
};
extern void
xmesa_set_driver( const struct xm_driver *driver );
#endif
#endif /* XM_PUBLIC_H */

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

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

View file

@ -25,6 +25,7 @@ VG_SOURCES = \
api_transform.c \
vgu.c \
vg_context.c \
vg_manager.c \
vg_state.c \
vg_tracker.c \
vg_translate.c \

View file

@ -26,6 +26,7 @@
#include "VG/openvg.h"
#include "vg_manager.h"
#include "vg_context.h"
#include "pipe/p_context.h"
@ -55,6 +56,8 @@ void vgFlush(void)
pipe = ctx->pipe;
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
vg_manager_flush_frontbuffer(ctx);
}
void vgFinish(void)

View file

@ -117,10 +117,6 @@ clear_with_quad(struct vg_context *st, float x0, float y0,
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_rasterizer(st->cso_context);
cso_save_fragment_shader(st->cso_context);

View file

@ -32,6 +32,7 @@
#include "shader.h"
#include "asm_util.h"
#include "st_inlines.h"
#include "vg_manager.h"
#include "pipe/p_context.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)
{
vg_manager_validate_framebuffer(ctx);
if ((ctx->state.dirty & BLEND_DIRTY)) {
struct pipe_blend_state *blend = &ctx->state.g3d.blend;
memset(blend, 0, sizeof(struct pipe_blend_state));

View file

@ -33,6 +33,7 @@
#include "pipe/p_state.h"
#include "util/u_pointer.h"
#include "util/u_math.h"
#include "state_tracker/st_api.h"
#include "cso_cache/cso_hash.h"
#include "cso_cache/cso_context.h"
@ -58,6 +59,9 @@ struct st_framebuffer {
struct pipe_texture *blend_texture;
struct st_framebuffer_iface *iface;
enum st_attachment_type strb_att;
void *privateData;
};
@ -84,6 +88,8 @@ enum dirty_state {
struct vg_context
{
struct st_context_iface iface;
struct pipe_context *pipe;
struct {
@ -101,6 +107,7 @@ struct vg_context
VGErrorCode _error;
struct st_framebuffer *draw_buffer;
int32_t draw_buffer_invalid;
struct cso_hash *owned_objects[VG_OBJECT_LAST];

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

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

View file

@ -39,9 +39,15 @@
#include "target-helpers/wrap_screen.h"
#include "xm_public.h"
#include "state_tracker/st_manager.h"
/* advertise OpenGL support */
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
* 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 );
#endif
#if defined(GALLIUM_SOFTPIPE)
if (screen == NULL)
screen = softpipe_create_screen( winsys );
#endif
if (screen == NULL)
goto fail;
@ -98,9 +106,10 @@ fail:
return NULL;
}
struct xm_driver xlib_driver =
static struct xm_driver xlib_driver =
{
.create_pipe_screen = swrast_xlib_create_screen,
.create_st_api = st_manager_create_api,
};

View file

@ -2,7 +2,7 @@
TOP = ../../../..
include $(TOP)/configs/current
SUBDIRS = $(GALLIUM_WINSYS_DRM_DIRS)
SUBDIRS = sw $(GALLIUM_WINSYS_DRM_DIRS)
default install clean:
@for dir in $(SUBDIRS) ; do \

View file

@ -7,6 +7,7 @@ PIPE_DRIVERS = \
$(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
$(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.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/identity/libidentity.a \
$(TOP)/src/gallium/drivers/i965/libi965.a

View file

@ -10,6 +10,8 @@
#include "trace/tr_drm.h"
#include "../../sw/sw_drm_api.h"
/*
* Helper functions
*/
@ -108,5 +110,13 @@ struct drm_api i965_libdrm_api =
struct drm_api *
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);
}

View 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

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

View 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

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

View 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

View file

@ -71,6 +71,7 @@ gdi_sw_displaytarget( struct sw_displaytarget *buf )
static boolean
gdi_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format )
{
switch(format) {
@ -119,6 +120,7 @@ gdi_sw_displaytarget_destroy(struct sw_winsys *winsys,
static struct sw_displaytarget *
gdi_sw_displaytarget_create(struct sw_winsys *winsys,
unsigned tex_usage,
enum pipe_format format,
unsigned width, unsigned height,
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
gdi_sw_display( struct sw_winsys *winsys,
struct sw_displaytarget *dt,
@ -212,6 +235,8 @@ gdi_create_sw_winsys(void)
winsys->destroy = gdi_sw_destroy;
winsys->is_displaytarget_format_supported = gdi_sw_is_displaytarget_format_supported;
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_unmap = gdi_sw_displaytarget_unmap;
winsys->displaytarget_display = gdi_sw_displaytarget_display;

View file

@ -44,6 +44,7 @@
static boolean
null_sw_is_displaytarget_format_supported(struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format )
{
return FALSE;
@ -78,6 +79,7 @@ null_sw_displaytarget_destroy(struct sw_winsys *winsys,
static struct sw_displaytarget *
null_sw_displaytarget_create(struct sw_winsys *winsys,
unsigned tex_usage,
enum pipe_format format,
unsigned width, unsigned height,
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
null_sw_displaytarget_display(struct sw_winsys *winsys,
struct sw_displaytarget *dt,
@ -115,6 +137,8 @@ null_sw_create(void)
winsys->destroy = null_sw_destroy;
winsys->is_displaytarget_format_supported = null_sw_is_displaytarget_format_supported;
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_unmap = null_sw_displaytarget_unmap;
winsys->displaytarget_display = null_sw_displaytarget_display;

View file

@ -208,6 +208,7 @@ alloc_ximage(struct xm_displaytarget *xm_dt,
static boolean
xm_is_displaytarget_format_supported( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format )
{
/* TODO: check visuals or other sensible thing here */
@ -358,6 +359,7 @@ xm_displaytarget_display(struct sw_winsys *ws,
static struct sw_displaytarget *
xm_displaytarget_create(struct sw_winsys *winsys,
unsigned tex_usage,
enum pipe_format format,
unsigned width, unsigned height,
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
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.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_unmap = xm_displaytarget_unmap;
ws->base.displaytarget_destroy = xm_displaytarget_destroy;

View file

@ -182,6 +182,7 @@ if env['platform'] != 'winddk':
'state_tracker/st_format.c',
'state_tracker/st_framebuffer.c',
'state_tracker/st_gen_mipmap.c',
'state_tracker/st_manager.c',
'state_tracker/st_mesa_to_tgsi.c',
'state_tracker/st_program.c',
'state_tracker/st_texture.c',

View file

@ -214,6 +214,7 @@ STATETRACKER_SOURCES = \
state_tracker/st_format.c \
state_tracker/st_framebuffer.c \
state_tracker/st_gen_mipmap.c \
state_tracker/st_manager.c \
state_tracker/st_mesa_to_tgsi.c \
state_tracker/st_program.c \
state_tracker/st_texture.c

View file

@ -34,6 +34,7 @@
#include "st_atom.h"
#include "st_cb_bitmap.h"
#include "st_program.h"
#include "st_manager.h"
#include "pipe/p_context.h"
@ -136,9 +137,7 @@ void st_validate_state( struct st_context *st )
check_program_state( st );
if (st->pipe->screen->update_buffer)
st->pipe->screen->update_buffer(st->pipe->screen,
st->pipe->priv);
st_manager_validate_framebuffers(st);
if (state->st == 0)
return;

View file

@ -48,6 +48,7 @@
#include "st_format.h"
#include "st_public.h"
#include "st_texture.h"
#include "st_manager.h"
#include "util/u_format.h"
#include "util/u_rect.h"
@ -618,8 +619,18 @@ check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
static void
st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
{
GLframebuffer *fb = ctx->DrawBuffer;
GLuint i;
(void) count;
(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);
}
@ -630,8 +641,13 @@ st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
static void
st_ReadBuffer(GLcontext *ctx, GLenum buffer)
{
GLframebuffer *fb = ctx->ReadBuffer;
(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);
}

View file

@ -40,6 +40,7 @@
#include "st_cb_clear.h"
#include "st_cb_fbo.h"
#include "st_public.h"
#include "st_manager.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.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);
if (strb) {
struct pipe_surface *front_surf = strb->surface;
/* Hook for copying "fake" frontbuffer if necessary:
*/
st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf,
st->winsys_drawable_handle );
st_manager_flush_frontbuffer(st);
/*
st->frontbuffer_status = FRONT_STATUS_UNDEFINED;

View file

@ -45,6 +45,7 @@
#include "st_debug.h"
#include "st_context.h"
#include "st_atom.h"
#include "st_cb_readpixels.h"
#include "st_cb_fbo.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 */
assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
st_validate_state(ctx->st);
/* Do all needed clipping here, so that we can forget about it later */
if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
/* The ReadPixels transfer is totally outside the window bounds */

View file

@ -30,9 +30,9 @@
#include "vbo/vbo.h"
#include "shader/shader_api.h"
#include "glapi/glapi.h"
#include "st_context.h"
#include "st_public.h"
#include "st_debug.h"
#include "st_context.h"
#include "st_cb_accum.h"
#include "st_cb_bitmap.h"
#include "st_cb_blit.h"

View file

@ -31,6 +31,7 @@
#include "main/mtypes.h"
#include "shader/prog_cache.h"
#include "pipe/p_state.h"
#include "state_tracker/st_api.h"
struct st_context;
@ -73,6 +74,8 @@ struct st_tracked_state {
struct st_context
{
struct st_context_iface iface;
GLcontext *ctx;
struct pipe_context *pipe;
@ -207,6 +210,11 @@ struct st_framebuffer
GLframebuffer Base;
void *Private;
GLuint InitWidth, InitHeight;
struct st_framebuffer_iface *iface;
enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
unsigned num_statts;
int32_t revalidate;
};

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

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