Conflicts: src/gallium/auxiliary/cso_cache/cso_context.c src/gallium/auxiliary/util/u_blit.c src/gallium/drivers/llvmpipe/lp_texture.c src/gallium/drivers/softpipe/sp_texture.c src/mesa/state_tracker/st_cb_fbo.c src/mesa/state_tracker/st_framebuffer.c src/mesa/state_tracker/st_texture.cgallium-resources
@@ -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; |
@@ -71,16 +71,12 @@ struct cso_context { | |||
unsigned nr_vertex_samplers_saved; | |||
void *vertex_samplers_saved[PIPE_MAX_VERTEX_SAMPLERS]; | |||
struct pipe_resource *textures[PIPE_MAX_SAMPLERS]; | |||
uint nr_fragment_sampler_views; | |||
struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; | |||
uint nr_textures; | |||
uint nr_vertex_sampler_views; | |||
struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; | |||
uint nr_textures_saved; | |||
struct pipe_resource *textures_saved[PIPE_MAX_SAMPLERS]; | |||
uint nr_fragment_sampler_views_saved; | |||
struct pipe_sampler_view *fragment_sampler_views_saved[PIPE_MAX_SAMPLERS]; | |||
@@ -299,8 +295,6 @@ void cso_release_all( struct cso_context *ctx ) | |||
} | |||
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { | |||
pipe_resource_reference(&ctx->textures[i], NULL); | |||
pipe_resource_reference(&ctx->textures_saved[i], NULL); | |||
pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); | |||
pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], NULL); | |||
} | |||
@@ -630,7 +624,7 @@ enum pipe_error cso_set_sampler_textures( struct cso_context *ctx, | |||
{ | |||
uint i; | |||
ctx->nr_textures = count; | |||
ctx->nr_fragment_sampler_views = count; | |||
for (i = 0; i < count; i++) { | |||
struct pipe_sampler_view templ, *view; | |||
@@ -638,15 +632,14 @@ enum pipe_error cso_set_sampler_textures( struct cso_context *ctx, | |||
u_sampler_view_default_template(&templ, | |||
textures[i], | |||
textures[i]->format); | |||
view = ctx->pipe->create_sampler_view(ctx->pipe, | |||
textures[i], | |||
&templ); | |||
pipe_resource_reference(&ctx->textures[i], textures[i]); | |||
pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], view); | |||
} | |||
for ( ; i < PIPE_MAX_SAMPLERS; i++) { | |||
pipe_resource_reference(&ctx->textures[i], NULL); | |||
pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); | |||
} | |||
@@ -661,12 +654,10 @@ void cso_save_sampler_textures( struct cso_context *ctx ) | |||
{ | |||
uint i; | |||
ctx->nr_textures_saved = ctx->nr_textures; | |||
for (i = 0; i < ctx->nr_textures; i++) { | |||
assert(!ctx->textures_saved[i]); | |||
ctx->nr_fragment_sampler_views_saved = ctx->nr_fragment_sampler_views; | |||
for (i = 0; i < ctx->nr_fragment_sampler_views; i++) { | |||
assert(!ctx->fragment_sampler_views_saved[i]); | |||
pipe_resource_reference(&ctx->textures_saved[i], ctx->textures[i]); | |||
pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], | |||
ctx->fragment_sampler_views[i]); | |||
} | |||
@@ -676,27 +667,22 @@ void cso_restore_sampler_textures( struct cso_context *ctx ) | |||
{ | |||
uint i; | |||
ctx->nr_textures = ctx->nr_textures_saved; | |||
for (i = 0; i < ctx->nr_textures; i++) { | |||
pipe_resource_reference(&ctx->textures[i], NULL); | |||
ctx->textures[i] = ctx->textures_saved[i]; | |||
ctx->textures_saved[i] = NULL; | |||
ctx->nr_fragment_sampler_views = ctx->nr_fragment_sampler_views_saved; | |||
for (i = 0; i < ctx->nr_fragment_sampler_views; i++) { | |||
pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); | |||
ctx->fragment_sampler_views[i] = ctx->fragment_sampler_views_saved[i]; | |||
ctx->fragment_sampler_views_saved[i] = NULL; | |||
} | |||
for ( ; i < PIPE_MAX_SAMPLERS; i++) { | |||
pipe_resource_reference(&ctx->textures[i], NULL); | |||
pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); | |||
} | |||
ctx->pipe->set_fragment_sampler_views(ctx->pipe, | |||
ctx->nr_textures, | |||
ctx->nr_fragment_sampler_views, | |||
ctx->fragment_sampler_views); | |||
ctx->nr_textures_saved = 0; | |||
ctx->nr_fragment_sampler_views_saved = 0; | |||
} | |||
@@ -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 */ |
@@ -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; |
@@ -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, ""); | |||
} | |||
@@ -37,7 +37,7 @@ | |||
#define LP_BLD_ARIT_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
struct lp_type; |
@@ -40,7 +40,7 @@ | |||
* for a standalone example. | |||
*/ | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
#include "pipe/p_format.h" | |||
@@ -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); |
@@ -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 |
@@ -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, ""); | |||
} |
@@ -37,7 +37,7 @@ | |||
#define LP_BLD_CONV_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
struct lp_type; |
@@ -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" |
@@ -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); | |||
@@ -36,7 +36,7 @@ | |||
#define LP_BLD_DEPTH_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
struct pipe_depth_state; |
@@ -35,7 +35,7 @@ | |||
#define LP_BLD_FLOW_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
struct lp_type; |
@@ -34,7 +34,7 @@ | |||
* Pixel format helpers. | |||
*/ | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
#include "pipe/p_format.h" | |||
@@ -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) |
@@ -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"); |
@@ -41,7 +41,7 @@ | |||
#define LP_BLD_INTERP_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
#include "tgsi/tgsi_exec.h" | |||
@@ -37,7 +37,7 @@ | |||
#define LP_BLD_INTR_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
/** |
@@ -193,7 +193,7 @@ lp_build_compare(LLVMBuilderRef builder, | |||
if(table[func].gt && | |||
((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, ""); | |||
} |
@@ -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 */ | |||
@@ -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); |
@@ -37,7 +37,7 @@ | |||
#define LP_BLD_PACK_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
struct lp_type; |
@@ -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); |
@@ -36,7 +36,7 @@ | |||
#define LP_BLD_SAMPLE_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
struct pipe_resource; | |||
struct pipe_sampler_state; |
@@ -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); | |||
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, dtdx, dtdy), | |||
lp_build_int_to_float(float_bld, height), ""); | |||
rho = lp_build_max(float_bld, rho, max); | |||
if (dims > 2) { | |||
/* 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); | |||
/* compute lod = log2(rho) */ | |||
lod = lp_build_log2(float_bld, rho); | |||
/* add lod bias */ | |||
lod = LLVMBuildAdd(bld->builder, lod, lod_bias, "LOD bias"); | |||
/* 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); | |||
/* clamp lod */ | |||
lod = lp_build_clamp(float_bld, lod, min_lod, max_lod); | |||
return 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); | |||
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 | |||
* depending on the lod being >0 or <= 0, respectively. | |||
*/ | |||
struct lp_build_flow_context *flow_ctx; | |||
struct lp_build_if_state if_ctx; | |||
LLVMValueRef minify; | |||
lp_build_sample_image_linear(bld, | |||
width0_vec, height0_vec, depth0_vec, | |||
row_stride0_vec, img_stride0_vec, | |||
data_ptr0, s, t, r, colors0); | |||
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]); | |||
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); | |||
} | |||
} | |||
/* minify = lod > 0.0 */ | |||
minify = LLVMBuildFCmp(bld->builder, LLVMRealUGE, | |||
lod, float_bld->zero, ""); | |||
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]); | |||
} | |||
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); | |||
} | |||
else { | |||
/* use first/only level's colors */ | |||
for (chan = 0; chan < 4; chan++) { | |||
colors_out[chan] = colors0[chan]; | |||
} | |||
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); | |||
} | |||
} | |||
else { | |||
/* emit conditional to choose min image filter or mag image filter | |||
* depending on the lod being >0 or <= 0, respectively. | |||
*/ | |||
abort(); | |||
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) |
@@ -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" |
@@ -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) |
@@ -37,7 +37,7 @@ | |||
#define LP_BLD_SWIZZLE_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
struct lp_type; |
@@ -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; |
@@ -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++; |
@@ -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> | |||
/** |
@@ -45,6 +45,7 @@ | |||
#include "util/u_format.h" | |||
#include "util/u_math.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_sampler.h" | |||
#include "util/u_simple_shaders.h" | |||
#include "util/u_surface.h" | |||
#include "util/u_rect.h" | |||
@@ -280,6 +281,7 @@ regions_overlap(int srcX0, int srcY0, | |||
void | |||
util_blit_pixels_writemask(struct blit_state *ctx, | |||
struct pipe_surface *src, | |||
struct pipe_sampler_view *src_sampler_view, | |||
int srcX0, int srcY0, | |||
int srcX1, int srcY1, | |||
struct pipe_surface *dst, | |||
@@ -290,7 +292,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, | |||
{ | |||
struct pipe_context *pipe = ctx->pipe; | |||
struct pipe_screen *screen = pipe->screen; | |||
struct pipe_resource *tex = NULL; | |||
struct pipe_sampler_view *sampler_view = NULL; | |||
struct pipe_framebuffer_state fb; | |||
const int srcW = abs(srcX1 - srcX0); | |||
const int srcH = abs(srcY1 - srcY0); | |||
@@ -345,6 +347,8 @@ util_blit_pixels_writemask(struct blit_state *ctx, | |||
src->texture->last_level != 0) | |||
{ | |||
struct pipe_resource texTemp; | |||
struct pipe_resource *tex; | |||
struct pipe_sampler_view sv_templ; | |||
struct pipe_surface *texSurf; | |||
const int srcLeft = MIN2(srcX0, srcX1); | |||
const int srcTop = MIN2(srcY0, srcY1); | |||
@@ -376,6 +380,14 @@ util_blit_pixels_writemask(struct blit_state *ctx, | |||
if (!tex) | |||
return; | |||
u_sampler_view_default_template(&sv_templ, tex, tex->format); | |||
sampler_view = ctx->pipe->create_sampler_view(ctx->pipe, tex, &sv_templ); | |||
if (!sampler_view) { | |||
pipe_texture_reference(&tex, NULL); | |||
return; | |||
} | |||
texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, | |||
PIPE_BUFFER_USAGE_GPU_WRITE); | |||
@@ -399,22 +411,25 @@ util_blit_pixels_writemask(struct blit_state *ctx, | |||
s1 = 1.0f; | |||
t0 = 0.0f; | |||
t1 = 1.0f; | |||
pipe_texture_reference(&tex, NULL); | |||
} | |||
else { | |||
pipe_resource_reference(&tex, src->texture); | |||
s0 = srcX0 / (float)tex->width0; | |||
s1 = srcX1 / (float)tex->width0; | |||
t0 = srcY0 / (float)tex->height0; | |||
t1 = srcY1 / (float)tex->height0; | |||
pipe_sampler_view_reference(&sampler_view, src_sampler_view); | |||
s0 = srcX0 / (float)src->texture->width0; | |||
s1 = srcX1 / (float)src->texture->width0; | |||
t0 = srcY0 / (float)src->texture->height0; | |||
t1 = srcY1 / (float)src->texture->height0; | |||
} | |||
/* save state (restored below) */ | |||
cso_save_blend(ctx->cso); | |||
cso_save_depth_stencil_alpha(ctx->cso); | |||
cso_save_rasterizer(ctx->cso); | |||
cso_save_samplers(ctx->cso); | |||
cso_save_sampler_textures(ctx->cso); | |||
cso_save_fragment_sampler_views(ctx->cso); | |||
cso_save_viewport(ctx->cso); | |||
cso_save_framebuffer(ctx->cso); | |||
cso_save_fragment_shader(ctx->cso); | |||
@@ -447,7 +462,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, | |||
cso_set_viewport(ctx->cso, &ctx->viewport); | |||
/* texture */ | |||
cso_set_sampler_textures(ctx->cso, 1, &tex); | |||
cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view); | |||
if (ctx->fs[writemask] == NULL) | |||
ctx->fs[writemask] = | |||
@@ -486,7 +501,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, | |||
cso_restore_depth_stencil_alpha(ctx->cso); | |||
cso_restore_rasterizer(ctx->cso); | |||
cso_restore_samplers(ctx->cso); | |||
cso_restore_sampler_textures(ctx->cso); | |||
cso_restore_fragment_sampler_views(ctx->cso); | |||
cso_restore_viewport(ctx->cso); | |||
cso_restore_framebuffer(ctx->cso); | |||
cso_restore_fragment_shader(ctx->cso); | |||
@@ -494,13 +509,14 @@ util_blit_pixels_writemask(struct blit_state *ctx, | |||
cso_restore_clip(ctx->cso); | |||
cso_restore_vertex_elements(ctx->cso); | |||
pipe_resource_reference(&tex, NULL); | |||
pipe_sampler_view_reference(&sampler_view, NULL); | |||
} | |||
void | |||
util_blit_pixels(struct blit_state *ctx, | |||
struct pipe_surface *src, | |||
struct pipe_sampler_view *src_sampler_view, | |||
int srcX0, int srcY0, | |||
int srcX1, int srcY1, | |||
struct pipe_surface *dst, | |||
@@ -508,7 +524,7 @@ util_blit_pixels(struct blit_state *ctx, | |||
int dstX1, int dstY1, | |||
float z, uint filter ) | |||
{ | |||
util_blit_pixels_writemask( ctx, src, | |||
util_blit_pixels_writemask( ctx, src, src_sampler_view, | |||
srcX0, srcY0, | |||
srcX1, srcY1, | |||
dst, |
@@ -53,6 +53,7 @@ util_destroy_blit(struct blit_state *ctx); | |||
extern void | |||
util_blit_pixels(struct blit_state *ctx, | |||
struct pipe_surface *src, | |||
struct pipe_sampler_view *src_sampler_view, | |||
int srcX0, int srcY0, | |||
int srcX1, int srcY1, | |||
struct pipe_surface *dst, | |||
@@ -63,6 +64,7 @@ util_blit_pixels(struct blit_state *ctx, | |||
void | |||
util_blit_pixels_writemask(struct blit_state *ctx, | |||
struct pipe_surface *src, | |||
struct pipe_sampler_view *src_sampler_view, | |||
int srcX0, int srcY0, | |||
int srcX1, int srcY1, | |||
struct pipe_surface *dst, |
@@ -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; | |||
} | |||
@@ -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, |
@@ -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 ); |
@@ -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. |
@@ -203,8 +203,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; | |||
} | |||
@@ -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" |
@@ -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" |
@@ -251,7 +251,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); | |||
@@ -366,7 +366,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); | |||
} | |||
@@ -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> |
@@ -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> |
@@ -29,7 +29,7 @@ | |||
#define LP_TEX_SAMPLE_H | |||
#include "os/os_llvm.h" | |||
#include "gallivm/lp_bld.h" | |||
struct lp_sampler_static_state; |
@@ -105,6 +105,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, | |||
@@ -253,6 +254,51 @@ llvmpipe_resource_unmap(struct pipe_resource *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_resource_get_handle(struct pipe_screen *screen, | |||
struct pipe_resource *pt, | |||
struct winsys_handle *whandle) | |||
{ | |||
struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; | |||
struct llvmpipe_resource *lpt = llvmpipe_resource(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_resource *pt, | |||
@@ -464,6 +510,7 @@ llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) | |||
{ | |||
screen->resource_create = llvmpipe_resource_create; | |||
screen->resource_destroy = llvmpipe_resource_destroy; | |||
screen->resource_get_handle = llvmpipe_resource_get_handle; | |||
screen->user_buffer_create = llvmpipe_user_buffer_create; | |||
screen->get_tex_surface = llvmpipe_get_tex_surface; |
@@ -145,18 +145,14 @@ nvfx_set_fragment_sampler_views(struct pipe_context *pipe, | |||
unsigned unit; | |||
for (unit = 0; unit < nr; unit++) { | |||
pipe_sampler_view_reference(&nv30->fragment_sampler_views[unit], | |||
pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], | |||
views[unit]); | |||
pipe_texture_reference((struct pipe_texture **) | |||
&nvfx->tex_miptree[unit], miptree[unit]); | |||
nvfx->dirty_samplers |= (1 << unit); | |||
} | |||
for (unit = nr; unit < nvfx->nr_textures; unit++) { | |||
pipe_sampler_view_reference(&nv30->fragment_sampler_views[unit], | |||
pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], | |||
NULL); | |||
pipe_texture_reference((struct pipe_texture **) | |||
&nvfx->tex_miptree[unit], NULL); | |||
nvfx->dirty_samplers |= (1 << unit); | |||
} | |||
@@ -166,7 +162,7 @@ nvfx_set_fragment_sampler_views(struct pipe_context *pipe, | |||
static struct pipe_sampler_view * | |||
nv30_create_sampler_view(struct pipe_context *pipe, | |||
nvfx_create_sampler_view(struct pipe_context *pipe, | |||
struct pipe_texture *texture, | |||
const struct pipe_sampler_view *templ) | |||
{ | |||
@@ -185,7 +181,7 @@ nv30_create_sampler_view(struct pipe_context *pipe, | |||
static void | |||
nv30_sampler_view_destroy(struct pipe_context *pipe, | |||
nvfx_sampler_view_destroy(struct pipe_context *pipe, | |||
struct pipe_sampler_view *view) | |||
{ | |||
pipe_texture_reference(&view->texture, NULL); | |||
@@ -614,7 +610,9 @@ nvfx_init_state_functions(struct nvfx_context *nvfx) | |||
nvfx->pipe.create_sampler_state = nvfx_sampler_state_create; | |||
nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind; | |||
nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete; | |||
nvfx->pipe.set_fragment_sampler_textures = nvfx_set_sampler_texture; | |||
nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views; | |||
nvfx->pipe.create_sampler_view = nvfx_create_sampler_view; | |||
nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy; | |||
nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create; | |||
nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind; |
@@ -114,8 +114,8 @@ static void r300_hw_copy(struct pipe_context* pipe, | |||
r300->blitter, state->sampler_count, (void**)state->sampler_states); | |||
util_blitter_save_fragment_sampler_views( | |||
r300->blitter, r300->fragment_sampler_view_count, | |||
r300->fragment_sampler_views); | |||
r300->blitter, state->texture_count, | |||
state->fragment_sampler_views); | |||
/* Do a copy */ | |||
util_blitter_copy(r300->blitter, |
@@ -139,7 +139,7 @@ struct r300_texture_fb_state { | |||
struct r300_textures_state { | |||
/* Textures. */ | |||
struct r300_texture *textures[8]; | |||
struct pipe_sampler_view *fragment_sampler_views[8]; | |||
int texture_count; | |||
/* Sampler states. */ | |||
struct r300_sampler_state *sampler_states[8]; | |||
@@ -343,9 +343,8 @@ struct r300_context { | |||
struct r300_atom rs_block_state; | |||
/* Scissor state. */ | |||
struct r300_atom scissor_state; | |||
/* Sampler view states. */ | |||
struct pipe_sampler_view* fragment_sampler_views[8]; | |||
int fragment_sampler_view_count; | |||
/* Textures state. */ | |||
struct r300_atom textures_state; | |||
/* Vertex stream formatting state. */ | |||
struct r300_atom vertex_stream_state; | |||
/* VAP (vertex shader) output mapping state. */ |
@@ -165,7 +165,7 @@ static const float * get_shader_constant( | |||
/* Factor for converting rectangle coords to | |||
* normalized coords. Should only show up on non-r500. */ | |||
case RC_STATE_R300_TEXRECT_FACTOR: | |||
tex = r300->fragment_sampler_views[constant->u.State[1]]->texture; | |||
tex = texstate->fragment_sampler_views[constant->u.State[1]]->texture; | |||
vec[0] = 1.0 / tex->width0; | |||
vec[1] = 1.0 / tex->height0; | |||
break; | |||
@@ -749,8 +749,9 @@ void r300_emit_textures_state(struct r300_context *r300, | |||
OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]); | |||
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); | |||
OUT_CS_TEX_RELOC(allstate->textures[i], texstate->tile_config, | |||
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); | |||
OUT_CS_TEX_RELOC((struct r300_texture *)allstate->fragment_sampler_views[i]->texture, | |||
texstate->tile_config, | |||
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); | |||
} | |||
} | |||
END_CS; | |||
@@ -1042,10 +1043,10 @@ validate: | |||
} | |||
} | |||
/* ...textures... */ | |||
for (i = 0; i < r300->fragment_sampler_view_count; i++) { | |||
if (!r300->fragment_sampler_views[i]) | |||
for (i = 0; i < texstate->count; i++) { | |||
tex = (struct r300_texture*)texstate->fragment_sampler_views[i]->texture; | |||
if (!tex || !texstate->sampler_states[i]) | |||
continue; | |||
tex = (struct r300_texture *)r300->fragment_sampler_views[i]->texture; | |||
if (!r300_add_texture(r300->rws, tex, | |||
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { | |||
r300->context.flush(&r300->context, 0, NULL); |
@@ -938,6 +938,8 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, | |||
struct pipe_sampler_view** views) | |||
{ | |||
struct r300_context* r300 = r300_context(pipe); | |||
struct r300_textures_state* state = | |||
(struct r300_textures_state*)r300->textures_state.state; | |||
unsigned i; | |||
boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; | |||
boolean dirty_tex = FALSE; | |||
@@ -948,16 +950,16 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, | |||
} | |||
for (i = 0; i < count; i++) { | |||
if (r300->fragment_sampler_views[i] != views[i]) { | |||
if (state->fragment_sampler_views[i] != views[i]) { | |||
struct r300_texture *texture; | |||
pipe_sampler_view_reference(&r300->fragment_sampler_views[i], | |||
views[i]); | |||
pipe_sampler_view_reference(&state->fragment_sampler_views[i], | |||
views[i]); | |||
dirty_tex = TRUE; | |||
texture = (struct r300_texture *)views[i]->texture; | |||
/* R300-specific - set the texrect factor in a fragment shader */ | |||
/* R300-specific - set the texrect factor in the fragment shader */ | |||
if (!is_r500 && texture->is_npot) { | |||
/* XXX It would be nice to re-emit just 1 constant, | |||
* XXX not all of them */ | |||
@@ -967,13 +969,13 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, | |||
} | |||
for (i = count; i < 8; i++) { | |||
if (r300->fragment_sampler_views[i]) { | |||
pipe_sampler_view_reference(&r300->fragment_sampler_views[i], | |||
NULL); | |||
if (state->fragment_sampler_views[i]) { | |||
pipe_sampler_view_reference(&state->fragment_sampler_views[i], | |||
NULL); | |||
} | |||
} | |||
r300->fragment_sampler_view_count = count; | |||
state->texture_count = count; | |||
r300->textures_state.dirty = TRUE; | |||
@@ -987,7 +989,6 @@ r300_create_sampler_view(struct pipe_context *pipe, | |||
struct pipe_texture *texture, | |||
const struct pipe_sampler_view *templ) | |||
{ | |||
struct r300_context *r300 = r300_context(pipe); | |||
struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); | |||
if (view) { |
@@ -340,10 +340,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) | |||
size = 2; | |||
for (i = 0; i < count; i++) { | |||
if (state->textures[i] && state->sampler_states[i]) { | |||
if (state->fragment_sampler_views[i] && state->sampler_states[i]) { | |||
state->tx_enable |= 1 << i; | |||
tex = state->textures[i]; | |||
tex = (struct r300_texture *)state->fragment_sampler_views[i]->texture; | |||
sampler = state->sampler_states[i]; | |||
texstate = &state->regs[i]; |
@@ -172,8 +172,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; | |||
} | |||
@@ -92,6 +92,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, | |||
@@ -142,8 +143,6 @@ softpipe_resource_create(struct pipe_screen *screen, | |||
} | |||
static void | |||
softpipe_resource_destroy(struct pipe_screen *pscreen, | |||
struct pipe_resource *pt) | |||
@@ -165,6 +164,55 @@ softpipe_resource_destroy(struct pipe_screen *pscreen, | |||
} | |||
static struct pipe_resource * | |||
softpipe_resource_from_handle(struct pipe_screen *screen, | |||
const struct pipe_resource *template, | |||
struct winsys_handle *whandle) | |||
{ | |||
struct sw_winsys *winsys = softpipe_screen(screen)->winsys; | |||
struct softpipe_resource *spt = CALLOC_STRUCT(softpipe_resource); | |||
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_resource_get_handle(struct pipe_screen *screen, | |||
struct pipe_resource *pt, | |||
struct winsys_handle *whandle) | |||
{ | |||
struct sw_winsys *winsys = softpipe_screen(screen)->winsys; | |||
struct softpipe_resource *spt = softpipe_resource(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. | |||
*/ | |||
@@ -428,6 +476,8 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen) | |||
{ | |||
screen->resource_create = softpipe_resource_create; | |||
screen->resource_destroy = softpipe_resource_destroy; | |||
screen->resource_from_handle = softpipe_resource_from_handle; | |||
screen->resource_get_handle = softpipe_resource_get_handle; | |||
screen->user_buffer_create = softpipe_user_buffer_create; | |||
screen->get_tex_surface = softpipe_get_tex_surface; |
@@ -0,0 +1,407 @@ | |||
/********************************************************** | |||
* Copyright 2010 VMware, Inc. All rights reserved. | |||
* | |||
* Permission is hereby granted, free of charge, to any person | |||
* obtaining a copy of this software and associated documentation | |||
* files (the "Software"), to deal in the Software without | |||
* restriction, including without limitation the rights to use, copy, | |||
* modify, merge, publish, distribute, sublicense, and/or sell copies | |||
* of the Software, and to permit persons to whom the Software is | |||
* furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be | |||
* included in all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
* SOFTWARE. | |||
* | |||
**********************************************************/ | |||
#ifndef _ST_API_H_ | |||
#define _ST_API_H_ | |||
#include "pipe/p_compiler.h" | |||
#include "pipe/p_format.h" | |||
/** | |||
* \file API for communication between state trackers and state tracker | |||
* managers. | |||
* | |||
* While both are state tackers, we use the term state tracker for rendering | |||
* APIs such as OpenGL or OpenVG, and state tracker manager for window system | |||
* APIs such as EGL or GLX in this file. | |||
* | |||
* This file defines an API to be implemented by both state trackers and state | |||
* tracker managers. | |||
*/ | |||
/** | |||
* The entry points of the state trackers. | |||
*/ | |||
#define ST_MODULE_OPENGL_SYMBOL "st_module_OpenGL" | |||
#define ST_MODULE_OPENGL_ES1_SYMBOL "st_module_OpenGL_ES1" | |||
#define ST_MODULE_OPENGL_ES2_SYMBOL "st_module_OpenGL_ES2" | |||
#define ST_MODULE_OPENVG_SYMBOL "st_module_OpenVG" | |||
/** | |||
* The supported rendering API of a state tracker. | |||
*/ | |||
enum st_api_type { | |||
ST_API_OPENGL, | |||
ST_API_OPENGL_ES1, | |||
ST_API_OPENGL_ES2, | |||
ST_API_OPENVG, | |||
ST_API_COUNT | |||
}; | |||
/** | |||
* Used in st_context_iface->teximage. | |||
*/ | |||
enum st_texture_type { | |||
ST_TEXTURE_1D, | |||
ST_TEXTURE_2D, | |||
ST_TEXTURE_3D, | |||
ST_TEXTURE_RECT, | |||
}; | |||
/** | |||
* Available attachments of framebuffer. | |||
*/ | |||
enum st_attachment_type { | |||
ST_ATTACHMENT_FRONT_LEFT, | |||
ST_ATTACHMENT_BACK_LEFT, | |||
ST_ATTACHMENT_FRONT_RIGHT, | |||
ST_ATTACHMENT_BACK_RIGHT, | |||
ST_ATTACHMENT_DEPTH_STENCIL, | |||
ST_ATTACHMENT_ACCUM, | |||
ST_ATTACHMENT_SAMPLE, | |||
ST_ATTACHMENT_COUNT, | |||
ST_ATTACHMENT_INVALID = -1 | |||
}; | |||
/* for buffer_mask in st_visual */ | |||
#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT) | |||
#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT) | |||
#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT) | |||
#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT) | |||
#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL) | |||
#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM) | |||
#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE) | |||
/** | |||
* Enumerations of state tracker context resources. | |||
*/ | |||
enum st_context_resource_type { | |||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D, | |||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D, | |||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X, | |||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X, | |||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y, | |||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y, | |||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z, | |||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z, | |||
ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER, | |||
ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE, | |||
}; | |||
/** | |||
* The return type of st_api->get_proc_address. | |||
*/ | |||
typedef void (*st_proc_t)(void); | |||
struct pipe_context; | |||
struct pipe_texture; | |||
struct pipe_fence_handle; | |||
/** | |||
* Used in st_context_iface->get_resource_for_egl_image. | |||
*/ | |||
struct st_context_resource | |||
{ | |||
/* these fields are filled by the caller */ | |||
enum st_context_resource_type type; | |||
void *resource; | |||
/* this is owned by the caller */ | |||
struct pipe_texture *texture; | |||
}; | |||
/** | |||
* Used in st_manager_iface->get_egl_image. | |||
*/ | |||
struct st_egl_image | |||
{ | |||
/* these fields are filled by the caller */ | |||
struct st_context_iface *stctxi; | |||
void *egl_image; | |||
/* this is owned by the caller */ | |||
struct pipe_texture *texture; | |||
unsigned face; | |||
unsigned level; | |||
unsigned zslice; | |||
}; | |||
/** | |||
* Represent the visual of a framebuffer. | |||
*/ | |||
struct st_visual | |||
{ | |||
/** | |||
* Available buffers. Tested with ST_FRAMEBUFFER_*_MASK. | |||
*/ | |||
unsigned buffer_mask; | |||
/** | |||
* Buffer formats. The formats are always set even when the buffer is | |||
* not available. | |||
*/ | |||
enum pipe_format color_format; | |||
enum pipe_format depth_stencil_format; | |||
enum pipe_format accum_format; | |||
int samples; | |||
/** | |||
* Desired render buffer. | |||
*/ | |||
enum st_attachment_type render_buffer; | |||
}; | |||
/** | |||
* Represent a windowing system drawable. | |||
* | |||
* The framebuffer is implemented by the state tracker manager and | |||
* used by the state trackers. | |||
* | |||
* Instead of the winsys pokeing into the API context to figure | |||
* out what buffers that might be needed in the future by the API | |||
* context, it calls into the framebuffer to get the textures. | |||
* | |||
* This structure along with the notify_invalid_framebuffer | |||
* allows framebuffers to be shared between different threads | |||
* but at the same make the API context free from thread | |||
* syncronisation primitves, with the exception of a small | |||
* atomic flag used for notification of framebuffer dirty status. | |||
* | |||
* The thread syncronisation is put inside the framebuffer | |||
* and only called once the framebuffer has become dirty. | |||
*/ | |||
struct st_framebuffer_iface | |||
{ | |||
/** | |||
* Available for the state tracker manager to use. | |||
*/ | |||
void *st_manager_private; | |||
/** | |||
* The visual of a framebuffer. | |||
*/ | |||
const struct st_visual *visual; | |||
/** | |||
* Flush the front buffer. | |||
* | |||
* On some window systems, changes to the front buffers are not immediately | |||
* visible. They need to be flushed. | |||
* | |||
* @att is one of the front buffer attachments. | |||
*/ | |||
boolean (*flush_front)(struct st_framebuffer_iface *stfbi, | |||
enum st_attachment_type statt); | |||
/** | |||
* The state tracker asks for the textures it needs. | |||
* | |||
* It should try to only ask for attachments that it currently renders | |||
* to, thus allowing the winsys to delay the allocation of textures not | |||
* needed. For example front buffer attachments are not needed if you | |||
* only do back buffer rendering. | |||
* | |||
* The implementor of this function needs to also ensure | |||
* thread safty as this call might be done from multiple threads. | |||
* | |||
* The returned textures are owned by the caller. They should be | |||
* unreferenced when no longer used. If this function is called multiple | |||
* times with different sets of attachments, those buffers not included in | |||
* the last call might be destroyed. This behavior might change in the | |||
* future. | |||
*/ | |||
boolean (*validate)(struct st_framebuffer_iface *stfbi, | |||
const enum st_attachment_type *statts, | |||
unsigned count, | |||
struct pipe_texture **out); | |||
}; | |||
/** | |||
* Represent a rendering context. | |||
* | |||
* This entity is created from st_api and used by the state tracker manager. | |||
*/ | |||
struct st_context_iface | |||
{ | |||
/** | |||
* Available for the state tracker and the manager to use. | |||
*/ | |||
void *st_context_private; | |||
void *st_manager_private; | |||
/** | |||
* Destroy the context. | |||
*/ | |||
void (*destroy)(struct st_context_iface *stctxi); | |||
/** | |||
* Invalidate the current textures that was taken from a framebuffer. | |||
* | |||
* The state tracker manager calls this function to let the rendering | |||
* context know that it should update the textures it got from | |||
* st_framebuffer_iface::validate. It should do so at the latest time possible. | |||
* Possible right before sending triangles to the pipe context. | |||
* | |||
* For certain platforms this function might be called from a thread other | |||
* than the thread that the context is currently bound in, and must | |||
* therefore be thread safe. But it is the state tracker manager's | |||
* responsibility to make sure that the framebuffer is bound to the context | |||
* and the API context is current for the duration of this call. | |||
* | |||
* Thus reducing the sync primitive needed to a single atomic flag. | |||
*/ | |||
void (*notify_invalid_framebuffer)(struct st_context_iface *stctxi, | |||
struct st_framebuffer_iface *stfbi); | |||
/** | |||
* Flush all drawing from context to the pipe also flushes the pipe. | |||
*/ | |||
void (*flush)(struct st_context_iface *stctxi, unsigned flags, | |||
struct pipe_fence_handle **fence); | |||
/** | |||
* Replace the texture image of a texture object at the specified level. | |||
* | |||
* This function is optional. | |||
*/ | |||
boolean (*teximage)(struct st_context_iface *stctxi, enum st_texture_type target, | |||
int level, enum pipe_format internal_format, | |||
struct pipe_texture *tex, boolean mipmap); | |||
/** | |||
* Used to implement glXCopyContext. | |||
*/ | |||
void (*copy)(struct st_context_iface *stctxi, | |||
struct st_context_iface *stsrci, unsigned mask); | |||
/** | |||
* Look up and return the info of a resource for EGLImage. | |||
* | |||
* This function is optional. | |||
*/ | |||
boolean (*get_resource_for_egl_image)(struct st_context_iface *stctxi, | |||
struct st_context_resource *stres); | |||
}; | |||
/** | |||
* Represent a state tracker manager. | |||
* | |||
* This interface is implemented by the state tracker manager. It corresponds | |||
* to a "display" in the window system. | |||
*/ | |||
struct st_manager | |||
{ | |||
struct pipe_screen *screen; | |||
/** | |||
* Look up and return the info of an EGLImage. | |||
* | |||
* This function is optional. | |||
*/ | |||
boolean (*get_egl_image)(struct st_manager *smapi, | |||
struct st_egl_image *stimg); | |||
}; | |||
/** | |||
* Represent a rendering API such as OpenGL or OpenVG. | |||
* | |||
* Implemented by the state tracker and used by the state tracker manager. | |||
*/ | |||
struct st_api | |||
{ | |||
/** | |||
* Destroy the API. | |||
*/ | |||
void (*destroy)(struct st_api *stapi); | |||
/** | |||
* Return an API entry point. | |||
* | |||
* For GL this is the same as _glapi_get_proc_address. | |||
*/ | |||
st_proc_t (*get_proc_address)(struct st_api *stapi, const char *procname); | |||
/** | |||
* Return true if the visual is supported by the state tracker. | |||
*/ | |||
boolean (*is_visual_supported)(struct st_api *stapi, | |||
const struct st_visual *visual); | |||
/** | |||
* Create a rendering context. | |||
*/ | |||
struct st_context_iface *(*create_context)(struct st_api *stapi, | |||
struct st_manager *smapi, | |||
const struct st_visual *visual, | |||
struct st_context_iface *stsharei); | |||
/** | |||
* Bind the context to the calling thread with draw and read as drawables. | |||
* | |||
* The framebuffers might have different visuals than the context does. | |||
*/ | |||
boolean (*make_current)(struct st_api *stapi, | |||
struct st_context_iface *stctxi, | |||
struct st_framebuffer_iface *stdrawi, | |||
struct st_framebuffer_iface *streadi); | |||
/** | |||
* Get the currently bound context in the calling thread. | |||
*/ | |||
struct st_context_iface *(*get_current)(struct st_api *stapi); | |||
}; | |||
/** | |||
* Represent a state tracker. | |||
* | |||
* This is the entry point of a state tracker. | |||
*/ | |||
struct st_module | |||
{ | |||
enum st_api_type api; | |||
struct st_api *(*create_api)(void); | |||
}; | |||
/** | |||
* Return true if the visual has the specified buffers. | |||
*/ | |||
static INLINE boolean | |||
st_visual_have_buffers(const struct st_visual *visual, unsigned mask) | |||
{ | |||
return ((visual->buffer_mask & mask) == mask); | |||
} | |||
/* these symbols may need to be dynamically lookup up */ | |||
extern PUBLIC const struct st_module st_module_OpenGL; | |||
extern PUBLIC const struct st_module st_module_OpenGL_ES1; | |||
extern PUBLIC const struct st_module st_module_OpenGL_ES2; | |||
extern PUBLIC const struct st_module st_module_OpenVG; | |||
#endif /* _ST_API_H_ */ |
@@ -44,6 +44,7 @@ extern "C" { | |||
#endif | |||
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 | |||
*/ |
@@ -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); |
@@ -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" |
@@ -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); | |||
/* set force_validate to skip an unnecessary check */ | |||
struct egl_g3d_context *gctx; | |||
/* | |||
* 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); |
@@ -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 { |
@@ -0,0 +1,227 @@ | |||
/* | |||
* Mesa 3-D graphics library | |||
* Version: 7.9 | |||
* | |||
* Copyright (C) 2010 LunarG Inc. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included | |||
* in all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Chia-I Wu <olv@lunarg.com> | |||
*/ | |||
#include "util/u_memory.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_dl.h" | |||
#include "eglimage.h" | |||
#include "eglmutex.h" | |||
#include "egl_g3d.h" | |||
#include "egl_g3d_st.h" | |||
struct egl_g3d_st_manager { | |||
struct st_manager base; | |||
_EGLDisplay *display; | |||
}; | |||
static INLINE struct egl_g3d_st_manager * | |||
egl_g3d_st_manager(struct st_manager *smapi) | |||
{ | |||
return (struct egl_g3d_st_manager *) smapi; | |||
} | |||
struct st_api * | |||
egl_g3d_create_st_api(enum st_api_type api) | |||
{ | |||
const char *stmod_name; | |||
struct util_dl_library *lib; | |||
const struct st_module *mod; | |||
switch (api) { | |||
case ST_API_OPENGL: | |||
stmod_name = ST_MODULE_OPENGL_SYMBOL; | |||
break; | |||
case ST_API_OPENGL_ES1: | |||
stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL; | |||
break; | |||
case ST_API_OPENGL_ES2: | |||
stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL; | |||
break; | |||
case ST_API_OPENVG: | |||
stmod_name = ST_MODULE_OPENVG_SYMBOL; | |||
break; | |||
default: | |||
stmod_name = NULL; | |||
break; | |||
} | |||
if (!stmod_name) | |||
return NULL; | |||
mod = NULL; | |||
lib = util_dl_open(NULL); | |||
if (lib) { | |||
mod = (const struct st_module *) | |||
util_dl_get_proc_address(lib, stmod_name); | |||
util_dl_close(lib); | |||
} | |||
if (!mod || mod->api != api) | |||
return NULL; | |||
return mod->create_api(); | |||
} | |||
struct st_manager * | |||
egl_g3d_create_st_manager(_EGLDisplay *dpy) | |||
{ | |||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy); | |||
struct egl_g3d_st_manager *gsmapi; | |||
gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); | |||
if (gsmapi) { | |||
gsmapi->display = dpy; | |||
gsmapi->base.screen = gdpy->native->screen; | |||
} | |||
return &gsmapi->base;; | |||
} | |||
void | |||
egl_g3d_destroy_st_manager(struct st_manager *smapi) | |||
{ | |||
struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); | |||
free(gsmapi); | |||
} | |||
static boolean | |||
egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, | |||
enum st_attachment_type statt) | |||
{ | |||
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; | |||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); | |||
return gsurf->native->flush_frontbuffer(gsurf->native); | |||
} | |||
static boolean | |||
egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, | |||
const enum st_attachment_type *statts, | |||
unsigned count, | |||
struct pipe_texture **out) | |||
{ | |||
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; | |||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); | |||
struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; | |||
uint attachment_mask = 0; | |||
unsigned i; | |||
for (i = 0; i < count; i++) { | |||
int natt; | |||
switch (statts[i]) { | |||
case ST_ATTACHMENT_FRONT_LEFT: | |||
natt = NATIVE_ATTACHMENT_FRONT_LEFT; | |||
break; | |||
case ST_ATTACHMENT_BACK_LEFT: | |||
natt = NATIVE_ATTACHMENT_BACK_LEFT; | |||
break; | |||
case ST_ATTACHMENT_FRONT_RIGHT: | |||
natt = NATIVE_ATTACHMENT_FRONT_RIGHT; | |||
break; | |||
case ST_ATTACHMENT_BACK_RIGHT: | |||
natt = NATIVE_ATTACHMENT_BACK_RIGHT; | |||
default: | |||
natt = -1; | |||
break; | |||
} | |||
if (natt >= 0) | |||
attachment_mask |= 1 << natt; | |||
} | |||
if (!gsurf->native->validate(gsurf->native, attachment_mask, | |||
&gsurf->sequence_number, textures, &gsurf->base.Width, | |||
&gsurf->base.Height)) | |||
return FALSE; | |||
for (i = 0; i < count; i++) { | |||
struct pipe_texture *tex; | |||
int natt; | |||
switch (statts[i]) { | |||
case ST_ATTACHMENT_FRONT_LEFT: | |||
natt = NATIVE_ATTACHMENT_FRONT_LEFT; | |||
break; | |||
case ST_ATTACHMENT_BACK_LEFT: | |||
natt = NATIVE_ATTACHMENT_BACK_LEFT; | |||
break; | |||
case ST_ATTACHMENT_FRONT_RIGHT: | |||
natt = NATIVE_ATTACHMENT_FRONT_RIGHT; | |||
break; | |||
case ST_ATTACHMENT_BACK_RIGHT: | |||
natt = NATIVE_ATTACHMENT_BACK_RIGHT; | |||
break; | |||
default: | |||
natt = -1; | |||
break; | |||
} | |||
if (natt >= 0) { | |||
tex = textures[natt]; | |||
if (statts[i] == stfbi->visual->render_buffer) | |||
pipe_texture_reference(&gsurf->render_texture, tex); | |||
if (attachment_mask & (1 << natt)) { | |||
/* transfer the ownership to the caller */ | |||
out[i] = tex; | |||
attachment_mask &= ~(1 << natt); | |||
} | |||
else { | |||
/* the attachment is listed more than once */ | |||
pipe_texture_reference(&out[i], tex); | |||
} | |||
} | |||
} | |||
return TRUE; | |||
} | |||
struct st_framebuffer_iface * | |||
egl_g3d_create_st_framebuffer(_EGLSurface *surf) | |||
{ | |||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); | |||
struct st_framebuffer_iface *stfbi; | |||
stfbi = CALLOC_STRUCT(st_framebuffer_iface); | |||
if (!stfbi) | |||
return NULL; | |||
stfbi->visual = &gsurf->stvis; | |||
stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; | |||
stfbi->validate = egl_g3d_st_framebuffer_validate; | |||
stfbi->st_manager_private = (void *) &gsurf->base; | |||
return stfbi; | |||
} | |||
void | |||
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) | |||
{ | |||
free(stfbi); | |||
} |
@@ -1,8 +1,8 @@ | |||
/* | |||
* Mesa 3-D graphics library | |||
* 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, | |||
NUM_EGL_G3D_STS | |||
}; | |||
/** | |||
* Return the EGL_<api>_BIT of the st api. | |||
*/ | |||
static INLINE int | |||
egl_g3d_st_api_bit(enum st_api_type api) | |||
{ | |||
int bit; | |||
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; | |||
}; | |||
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; | |||
} | |||
const struct egl_g3d_st * | |||
egl_g3d_get_st(enum egl_g3d_st_api api); | |||
return bit; | |||
} | |||
#endif /* _EGL_ST_H_ */ | |||
#endif /* _EGL_G3D_ST_H_ */ |
@@ -1,131 +0,0 @@ | |||
/* | |||
* Mesa 3-D graphics library | |||
* Version: 7.8 | |||
* | |||
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included | |||
* in all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
*/ | |||
#include <dlfcn.h> | |||
#include "pipe/p_compiler.h" | |||
#include "util/u_memory.h" | |||
#include "egllog.h" | |||
#include "EGL/egl.h" /* for EGL_api_BIT */ | |||
#include "egl_st.h" | |||
#ifndef HAVE_DLADDR | |||
#define HAVE_DLADDR 1 | |||
#endif | |||
#if HAVE_DLADDR | |||
static const char * | |||
egl_g3d_st_names[] = { | |||
#define ST_PUBLIC(name, ...) #name, | |||
#include "st_public_tmp.h" | |||
NULL | |||
}; | |||
static boolean | |||
egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) | |||
{ | |||
st_proc *procs = (st_proc *) stapi; | |||
void *handle; | |||
Dl_info info; | |||
const char **name; | |||
if (!dladdr(sym, &info)) | |||
return FALSE; | |||
handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); | |||
if (!handle) | |||
return FALSE; | |||
for (name = egl_g3d_st_names; *name; name++) { | |||
st_proc proc = (st_proc) dlsym(handle, *name); | |||
if (!proc) { | |||
_eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname); | |||
memset(stapi, 0, sizeof(*stapi)); | |||
dlclose(handle); | |||
return FALSE; | |||
} | |||
*procs++ = proc; | |||
} | |||
dlclose(handle); | |||
return TRUE; | |||
} | |||
#else /* HAVE_DLADDR */ | |||
static boolean | |||
egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) | |||
{ | |||
#define ST_PUBLIC(name, ...) stapi->name = name; | |||
#include "st_public_tmp.h" | |||
return TRUE; | |||
} | |||
#endif /* HAVE_DLADDR */ | |||
static boolean | |||
egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api) | |||
{ | |||
void *handle, *sym; | |||
boolean res = FALSE; | |||
/* already initialized */ | |||
if (stapi->st_notify_swapbuffers != NULL) | |||
return TRUE; | |||
handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); | |||
if (!handle) | |||
return FALSE; | |||
sym = dlsym(handle, api); | |||
if (sym && egl_g3d_fill_st(stapi, sym)) | |||
res = TRUE; | |||
dlclose(handle); | |||
return res; | |||
} | |||
static struct { | |||
const char *symbol; | |||
EGLint api_bit; | |||
} egl_g3d_st_info[NUM_EGL_G3D_STS] = { | |||
{ "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT }, | |||
{ "st_api_OpenVG", EGL_OPENVG_BIT }, | |||
{ "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT }, | |||
{ "st_api_OpenGL", EGL_OPENGL_BIT }, | |||
}; | |||
const struct egl_g3d_st * | |||
egl_g3d_get_st(enum egl_g3d_st_api api) | |||
{ | |||
static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS]; | |||
if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) { | |||
all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit; | |||
return &all_trackers[api]; | |||
} | |||
else { | |||
return NULL; | |||
} | |||
} |
@@ -1,20 +0,0 @@ | |||
ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share) | |||
ST_PUBLIC(st_destroy_context, void, struct st_context *st) | |||
ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask) | |||
ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData) | |||
ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height) | |||
ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf) | |||
ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height) | |||
ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface) | |||
ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture) | |||
ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb) | |||
ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb) | |||
ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read, void *winsys_drawable_handle) | |||
ST_PUBLIC(st_get_current, struct st_context *, void) | |||
ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence) | |||
ST_PUBLIC(st_finish, void, struct st_context *st) | |||
ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb) | |||
ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format) | |||
ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level) | |||
ST_PUBLIC(st_get_proc_address, st_proc, const char *procname) | |||
#undef ST_PUBLIC |
@@ -38,6 +38,7 @@ SYS_LIBS = -lm -pthread | |||
INCLUDE_DIRS = \ | |||
-I$(TOP)/src/mesa \ | |||
-I$(TOP)/src/gallium/include | |||
.c.o: |
@@ -1,3 +1,8 @@ | |||
#include "pipe/p_compiler.h" | |||
#include "state_tracker/st_manager.h" | |||
PUBLIC const int st_api_OpenGL_ES1 = 1; | |||
PUBLIC const struct st_module st_module_OpenGL_ES1 = { | |||
.api = ST_API_OPENGL_ES1, | |||
.create_api = st_manager_create_api | |||
}; |
@@ -1,3 +1,8 @@ | |||
#include "pipe/p_compiler.h" | |||
#include "state_tracker/st_manager.h" | |||
PUBLIC const int st_api_OpenGL_ES2 = 1; | |||
PUBLIC const struct st_module st_module_OpenGL_ES2 = { | |||
.api = ST_API_OPENGL_ES2, | |||
.create_api = st_manager_create_api | |||
}; |
@@ -12,6 +12,7 @@ C_SOURCES = \ | |||
glx_api.c \ | |||
glx_getproc.c \ | |||
glx_usefont.c \ | |||
xm_api.c | |||
xm_api.c \ | |||
xm_st.c | |||
include ../../../Makefile.template |
@@ -20,6 +20,7 @@ if env['platform'] == 'linux' \ | |||
'glx_getproc.c', | |||
'glx_usefont.c', | |||
'xm_api.c', | |||
'xm_st.c', | |||
] | |||
) | |||
Export('st_xlib') |
@@ -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); | |||
} | |||
@@ -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; | |||
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; | |||
} | |||
static struct pipe_screen *screen = 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,23 +988,20 @@ 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); | |||
} | |||
/* | |||
@@ -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; | |||
st_swapbuffers(b->stfb, &frontLeftSurf, NULL); | |||
if (frontLeftSurf) { | |||
screen->flush_frontbuffer( screen, | |||
frontLeftSurf, | |||
&b->ws ); | |||
XMesaContext xmctx = XMesaGetCurrentContext(); | |||
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); | |||
} |
@@ -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: */ | |||
}; | |||
/** cast wrapper */ | |||
static INLINE XMesaContext | |||
xmesa_context(GLcontext *ctx) | |||
{ | |||
return (XMesaContext) ctx->DriverCtx; | |||
} | |||
unsigned width, height; | |||
}; | |||
/** 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; | |||
} | |||
@@ -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 */ |
@@ -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); | |||
} |
@@ -0,0 +1,51 @@ | |||
/* | |||
* Mesa 3-D graphics library | |||
* Version: 7.9 | |||
* | |||
* Copyright (C) 2010 LunarG Inc. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included | |||
* in all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Chia-I Wu <olv@lunarg.com> | |||
*/ | |||
#ifndef _XM_ST_H_ | |||
#define _XM_ST_H_ | |||
#include "pipe/p_compiler.h" | |||
#include "state_tracker/st_api.h" | |||
#include "xm_api.h" | |||
struct st_framebuffer_iface * | |||
xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b); | |||
void | |||
xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); | |||
void | |||
xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi); | |||
void | |||
xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, | |||
enum st_attachment_type src, | |||
enum st_attachment_type dst, | |||
int x, int y, int w, int h); | |||
#endif /* _XM_ST_H_ */ |
@@ -25,6 +25,7 @@ VG_SOURCES = \ | |||
api_transform.c \ | |||
vgu.c \ | |||
vg_context.c \ | |||
vg_manager.c \ | |||
vg_state.c \ | |||
vg_tracker.c \ | |||
vg_translate.c \ |
@@ -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) |
@@ -118,10 +118,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); |
@@ -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)); |
@@ -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_resource *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]; | |||
@@ -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, | |||
}; |
@@ -0,0 +1,40 @@ | |||
/* | |||
* Mesa 3-D graphics library | |||
* Version: 7.9 | |||
* | |||
* Copyright (C) 2010 LunarG Inc. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included | |||
* in all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Chia-I Wu <olv@lunarg.com> | |||
*/ | |||
#ifndef VG_MANAGER_H | |||
#define VG_MANAGER_H | |||
#include "state_tracker/st_api.h" | |||
#include "vg_context.h" | |||
void | |||
vg_manager_flush_frontbuffer(struct vg_context *ctx); | |||
void | |||
vg_manager_validate_framebuffer(struct vg_context *ctx); | |||
#endif /* VG_MANAGER_H */ |
@@ -39,9 +39,15 @@ | |||
#include "target-helpers/wrap_screen.h" | |||
#include "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, | |||
}; | |||
@@ -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 \ |
@@ -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 |
@@ -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); | |||
} |
@@ -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 |
@@ -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; | |||
} |
@@ -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 |
@@ -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; | |||
} |
@@ -0,0 +1,35 @@ | |||
/********************************************************** | |||
* Copyright 2010 VMware, Inc. All rights reserved. | |||
* | |||
* Permission is hereby granted, free of charge, to any person | |||
* obtaining a copy of this software and associated documentation | |||
* files (the "Software"), to deal in the Software without | |||
* restriction, including without limitation the rights to use, copy, | |||
* modify, merge, publish, distribute, sublicense, and/or sell copies | |||
* of the Software, and to permit persons to whom the Software is | |||
* furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be | |||
* included in all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
* SOFTWARE. | |||
* | |||
**********************************************************/ | |||
#ifndef WRAPPER_SW_WINSYS | |||
#define WRAPPER_SW_WINSYS | |||
struct sw_winsys; | |||
struct pipe_screen; | |||
struct sw_winsys *wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen); | |||
#endif |
@@ -71,6 +71,7 @@ gdi_sw_displaytarget( struct sw_displaytarget *buf ) | |||
static boolean | |||
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; |
@@ -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; |
@@ -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; |
@@ -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', |
@@ -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 |
@@ -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; |
@@ -69,6 +69,7 @@ st_BlitFramebuffer(GLcontext *ctx, | |||
const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT | | |||
GL_STENCIL_BUFFER_BIT); | |||
struct st_context *st = ctx->st; | |||
struct pipe_context *pipe = st->pipe; | |||
const uint pFilter = ((filter == GL_NEAREST) | |||
? PIPE_TEX_MIPFILTER_NEAREST | |||
: PIPE_TEX_MIPFILTER_LINEAR); | |||
@@ -111,8 +112,8 @@ st_BlitFramebuffer(GLcontext *ctx, | |||
&readFB->Attachment[readFB->_ColorReadBufferIndex]; | |||
if(srcAtt->Type == GL_TEXTURE) { | |||
struct pipe_screen *screen = ctx->st->pipe->screen; | |||
const struct st_texture_object *srcObj = | |||
struct pipe_screen *screen = pipe->screen; | |||
struct st_texture_object *srcObj = | |||
st_texture_object(srcAtt->Texture); | |||
struct st_renderbuffer *dstRb = | |||
st_renderbuffer(drawFB->_ColorDrawBuffers[0]); | |||
@@ -132,7 +133,8 @@ st_BlitFramebuffer(GLcontext *ctx, | |||
return; | |||
util_blit_pixels(st->blit, | |||
srcSurf, srcX0, srcY0, srcX1, srcY1, | |||
srcSurf, st_get_stobj_sampler_view(srcObj), | |||
srcX0, srcY0, srcX1, srcY1, | |||
dstSurf, dstX0, dstY0, dstX1, dstY1, | |||
0.0, pFilter); | |||
@@ -144,10 +146,11 @@ st_BlitFramebuffer(GLcontext *ctx, | |||
struct st_renderbuffer *dstRb = | |||
st_renderbuffer(drawFB->_ColorDrawBuffers[0]); | |||
struct pipe_surface *srcSurf = srcRb->surface; | |||
struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcRb, pipe); | |||
struct pipe_surface *dstSurf = dstRb->surface; | |||
util_blit_pixels(st->blit, | |||
srcSurf, srcX0, srcY0, srcX1, srcY1, | |||
srcSurf, srcView, srcX0, srcY0, srcX1, srcY1, | |||
dstSurf, dstX0, dstY0, dstX1, dstY1, | |||
0.0, pFilter); | |||
} | |||
@@ -179,11 +182,13 @@ st_BlitFramebuffer(GLcontext *ctx, | |||
if ((mask & depthStencil) == depthStencil && | |||
srcDepthSurf == srcStencilSurf && | |||
dstDepthSurf == dstStencilSurf) { | |||
struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcDepthRb, pipe); | |||
/* Blitting depth and stencil values between combined | |||
* depth/stencil buffers. This is the ideal case for such buffers. | |||
*/ | |||
util_blit_pixels(st->blit, | |||
srcDepthSurf, srcX0, srcY0, srcX1, srcY1, | |||
srcDepthSurf, srcView, srcX0, srcY0, srcX1, srcY1, | |||
dstDepthSurf, dstX0, dstY0, dstX1, dstY1, | |||
0.0, pFilter); | |||
} |