Conditional rendering (GL_NV_conditional_render) DONE (swrast & softpipe)
Map buffer subranges (GL_APPLE_flush_buffer_range) not started
Float textures, renderbuffers some infrastructure done
+ (incl. GL_EXT_packed_float, GL_EXT_shared_exponent)
Framebuffer objects (GL_EXT_framebuffer_object) DONE
Half-float some infrastructure done
Multisample blit DONE
* \file stencil_twoside.c
*
* Simple test of GL_ATI_separate_stencil (or the OGL 2.0 equivalent) functionality.
- * Four squares are drawn
+ * Five squares (or six if stencil wrap is available) are drawn
* with different stencil modes, but all should be rendered with the same
* final color.
*/
#include <GL/glut.h>
static int use20syntax = 1;
-static int Width = 550;
+static int Width = 650;
static int Height = 200;
static const GLfloat Near = 5.0, Far = 25.0;
*/
glDisable(GL_STENCIL_TEST);
- glTranslatef(-6.0, 0, 0);
+ glTranslatef(-7.0, 0, 0);
glBegin(GL_QUADS);
glColor3f( 0.5, 0.5, 0.5 );
glVertex2f(-1, -1);
/* Draw the first two squares using incr for the affected face
*/
+ /*************************************************************************
+ * 2nd square
+ */
if (use20syntax) {
stencil_func_separate(GL_FRONT, GL_ALWAYS, 0, ~0);
stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0);
glTranslatef(3.0, 0, 0);
glBegin(GL_QUADS);
glColor3f( 0.9, 0.9, 0.9 );
- /* this should be front facing */
for ( i = 0 ; i < (max_stencil + 5) ; i++ ) {
+ /* this should be front facing */
glVertex2f(-1, -1);
glVertex2f( 1, -1);
glVertex2f( 1, 1);
}
glEnd();
+ /* stencil vals should be equal to max_stencil */
glStencilFunc(GL_EQUAL, max_stencil, ~0);
glBegin(GL_QUADS);
glColor3f( 0.5, 0.5, 0.5 );
glVertex2f(-1, 1);
glEnd();
+ /*************************************************************************
+ * 3rd square
+ */
if (use20syntax) {
stencil_func_separate(GL_FRONT, GL_ALWAYS, 0, ~0);
stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0);
glTranslatef(3.0, 0, 0);
glBegin(GL_QUADS);
glColor3f( 0.9, 0.9, 0.9 );
-
- /* this should be back facing */
for ( i = 0 ; i < (max_stencil + 5) ; i++ ) {
+ /* this should be back facing */
glVertex2f(-1, -1);
glVertex2f(-1, 1);
glVertex2f( 1, 1);
}
glEnd();
+ /* stencil vals should be equal to max_stencil */
glStencilFunc(GL_EQUAL, max_stencil, ~0);
glBegin(GL_QUADS);
glColor3f( 0.5, 0.5, 0.5 );
glVertex2f(-1, 1);
glEnd();
+ /*************************************************************************
+ * 4th square
+ */
if (use20syntax) {
stencil_func_separate(GL_FRONT, GL_NEVER, 0, ~0);
stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0);
glTranslatef(3.0, 0, 0);
glBegin(GL_QUADS);
glColor3f( 0.9, 0.9, 0.9 );
-
- /* this should be back facing */
for ( i = 0 ; i < (max_stencil + 5) ; i++ ) {
- /* this should be back facing */
+ /* this should be back facing */
glVertex2f(-1, -1);
glVertex2f(-1, 1);
glVertex2f( 1, 1);
glVertex2f( 1, -1);
- /* this should be front facing */
+ /* this should be front facing */
glVertex2f(-1, -1);
glVertex2f( 1, -1);
glVertex2f( 1, 1);
}
glEnd();
+ /* stencil vals should be equal to max_stencil */
glStencilFunc(GL_EQUAL, max_stencil, ~0);
glBegin(GL_QUADS);
glColor3f( 0.5, 0.5, 0.5 );
glVertex2f(-1, 1);
glEnd();
+ /*************************************************************************
+ * 5th square
+ */
if (use20syntax) {
stencil_func_separate(GL_FRONT, GL_ALWAYS, 0, ~0);
stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0);
else {
stencil_func_separate_ati(GL_ALWAYS, GL_ALWAYS, 0, ~0);
}
- stencil_op_separate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR);
- stencil_op_separate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR);
+ stencil_op_separate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR);
+ stencil_op_separate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR);
glTranslatef(3.0, 0, 0);
glBegin(GL_QUADS);
glColor3f( 0.9, 0.9, 0.9 );
-
- /* this should be back facing */
for ( i = 0 ; i < (max_stencil + 5) ; i++ ) {
- /* this should be back facing */
+ /* this should be back facing */
glVertex2f(-1, -1);
glVertex2f(-1, 1);
glVertex2f( 1, 1);
glVertex2f( 1, -1);
- /* this should be front facing */
+ /* this should be front facing */
glVertex2f(-1, -1);
glVertex2f( 1, -1);
glVertex2f( 1, 1);
glVertex2f(-1, 1);
glEnd();
+ /*************************************************************************
+ * 6th square
+ */
+ if (glutExtensionSupported("GL_EXT_stencil_wrap")) {
+ if (use20syntax) {
+ stencil_func_separate(GL_FRONT, GL_ALWAYS, 0, ~0);
+ stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0);
+ }
+ else {
+ stencil_func_separate_ati(GL_ALWAYS, GL_ALWAYS, 0, ~0);
+ }
+ stencil_op_separate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP);
+ stencil_op_separate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
+
+ glTranslatef(3.0, 0, 0);
+ glBegin(GL_QUADS);
+ glColor3f( 0.9, 0.9, 0.9 );
+ for ( i = 0 ; i < (max_stencil + 5) ; i++ ) {
+ /* this should be back facing */
+ glVertex2f(-1, -1);
+ glVertex2f(-1, 1);
+ glVertex2f( 1, 1);
+ glVertex2f( 1, -1);
+ /* this should be front facing */
+ glVertex2f(-1, -1);
+ glVertex2f( 1, -1);
+ glVertex2f( 1, 1);
+ glVertex2f(-1, 1);
+ }
+ glEnd();
+
+ glStencilFunc(GL_EQUAL, 260 - 255, ~0);
+ glBegin(GL_QUADS);
+ glColor3f( 0.5, 0.5, 0.5 );
+ glVertex2f(-1, -1);
+ glVertex2f( 1, -1);
+ glVertex2f( 1, 1);
+ glVertex2f(-1, 1);
+ glEnd();
+ }
+
glPopMatrix();
glutSwapBuffers();
stencil_func_separate_ati = (PFNGLSTENCILFUNCSEPARATEATIPROC) glutGetProcAddress( "glStencilFuncSeparateATI" );
stencil_op_separate = (PFNGLSTENCILOPSEPARATEPROC) glutGetProcAddress( "glStencilOpSeparate" );
- printf("\nAll 5 squares should be the same color.\n");
+ printf("\nAll 5 (or 6) squares should be the same color.\n");
}
}
-enum pipe_error cso_set_sampler_textures( struct cso_context *ctx,
- uint count,
- struct pipe_texture **textures )
-{
- uint i;
-
- ctx->nr_fragment_sampler_views = count;
-
- for (i = 0; i < count; i++) {
- struct pipe_sampler_view templ, *view;
-
- u_sampler_view_default_template(&templ,
- textures[i],
- textures[i]->format);
-
- view = ctx->pipe->create_sampler_view(ctx->pipe,
- textures[i],
- &templ);
-
- pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], view);
- }
- for ( ; i < PIPE_MAX_SAMPLERS; i++) {
- pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL);
- }
-
- ctx->pipe->set_fragment_sampler_views(ctx->pipe,
- count,
- ctx->fragment_sampler_views);
-
- return PIPE_OK;
-}
-
-void cso_save_sampler_textures( struct cso_context *ctx )
-{
- uint 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_sampler_view_reference(&ctx->fragment_sampler_views_saved[i],
- ctx->fragment_sampler_views[i]);
- }
-}
-
-void cso_restore_sampler_textures( struct cso_context *ctx )
-{
- uint i;
-
- 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_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL);
- }
-
- ctx->pipe->set_fragment_sampler_views(ctx->pipe,
- ctx->nr_fragment_sampler_views,
- ctx->fragment_sampler_views);
-
- ctx->nr_fragment_sampler_views_saved = 0;
-}
-
-
enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
const struct pipe_depth_stencil_alpha_state *templ)
{
cso_single_vertex_sampler_done(struct cso_context *cso);
-
-enum pipe_error cso_set_sampler_textures( struct cso_context *cso,
- uint count,
- struct pipe_texture **textures );
-void cso_save_sampler_textures( struct cso_context *cso );
-void cso_restore_sampler_textures( struct cso_context *cso );
-
-
enum pipe_error cso_set_vertex_elements(struct cso_context *ctx,
unsigned count,
const struct pipe_vertex_element *states);
* Z31 Z32 Z41 Z42 Z33 Z34 Z43 Z44 ...
* ... ... ... ... ... ... ... ... ...
*
- * FIXME: Code generate stencil test
+ *
+ * Stencil test:
+ * Two-sided stencil test is supported but probably not as efficient as
+ * it could be. Currently, we use if/then/else constructs to do the
+ * operations for front vs. back-facing polygons. We could probably do
+ * both the front and back arithmetic then use a Select() instruction to
+ * choose the result depending on polyon orientation. We'd have to
+ * measure performance both ways and see which is better.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#include "lp_bld_swizzle.h"
+/** Used to select fields from pipe_stencil_state */
+enum stencil_op {
+ S_FAIL_OP,
+ Z_FAIL_OP,
+ Z_PASS_OP
+};
+
+
/**
- * Do the stencil test comparison (compare fb Z values against ref value.
- * \param stencilVals vector of stencil values from framebuffer
+ * Do the stencil test comparison (compare FB stencil values against ref value).
+ * This will be used twice when generating two-sided stencil code.
+ * \param stencil the front/back stencil state
* \param stencilRef the stencil reference value, replicated as a vector
- * \return mask of pass/fail values
+ * \param stencilVals vector of stencil values from framebuffer
+ * \return vector mask of pass/fail values (~0 or 0)
*/
static LLVMValueRef
-lp_build_stencil_test(struct lp_build_context *bld,
- const struct pipe_stencil_state *stencil,
- LLVMValueRef stencilRef,
- LLVMValueRef stencilVals)
+lp_build_stencil_test_single(struct lp_build_context *bld,
+ const struct pipe_stencil_state *stencil,
+ LLVMValueRef stencilRef,
+ LLVMValueRef stencilVals)
{
const unsigned stencilMax = 255; /* XXX fix */
struct lp_type type = bld->type;
LLVMValueRef res;
+ assert(type.sign);
+
assert(stencil->enabled);
if (stencil->valuemask != stencilMax) {
}
+/**
+ * Do the one or two-sided stencil test comparison.
+ * \sa lp_build_stencil_test_single
+ * \param face an integer indicating front (+) or back (-) facing polygon.
+ * If NULL, assume front-facing.
+ */
+static LLVMValueRef
+lp_build_stencil_test(struct lp_build_context *bld,
+ const struct pipe_stencil_state stencil[2],
+ LLVMValueRef stencilRefs[2],
+ LLVMValueRef stencilVals,
+ LLVMValueRef face)
+{
+ LLVMValueRef res;
+
+ assert(stencil[0].enabled);
+
+ if (stencil[1].enabled && face) {
+ /* do two-sided test */
+ struct lp_build_flow_context *flow_ctx;
+ struct lp_build_if_state if_ctx;
+ LLVMValueRef front_facing;
+ LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0);
+ LLVMValueRef result = bld->undef;
+
+ flow_ctx = lp_build_flow_create(bld->builder);
+ lp_build_flow_scope_begin(flow_ctx);
+
+ lp_build_flow_scope_declare(flow_ctx, &result);
+
+ /* front_facing = face > 0.0 */
+ front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, "");
+
+ lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing);
+ {
+ result = lp_build_stencil_test_single(bld, &stencil[0],
+ stencilRefs[0], stencilVals);
+ }
+ lp_build_else(&if_ctx);
+ {
+ result = lp_build_stencil_test_single(bld, &stencil[1],
+ stencilRefs[1], stencilVals);
+ }
+ lp_build_endif(&if_ctx);
+
+ lp_build_flow_scope_end(flow_ctx);
+ lp_build_flow_destroy(flow_ctx);
+
+ res = result;
+ }
+ else {
+ /* do single-side test */
+ res = lp_build_stencil_test_single(bld, &stencil[0],
+ stencilRefs[0], stencilVals);
+ }
+
+ 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,
- const struct pipe_stencil_state *stencil,
- unsigned stencil_op,
- LLVMValueRef stencilRef,
- LLVMValueRef stencilVals,
- LLVMValueRef mask)
+lp_build_stencil_op_single(struct lp_build_context *bld,
+ const struct pipe_stencil_state *stencil,
+ enum stencil_op op,
+ LLVMValueRef stencilRef,
+ LLVMValueRef stencilVals,
+ LLVMValueRef mask)
{
const unsigned stencilMax = 255; /* XXX fix */
struct lp_type type = bld->type;
LLVMValueRef res;
LLVMValueRef max = lp_build_const_int_vec(type, stencilMax);
+ unsigned stencil_op;
+
+ assert(type.sign);
+
+ switch (op) {
+ case S_FAIL_OP:
+ stencil_op = stencil->fail_op;
+ break;
+ case Z_FAIL_OP:
+ stencil_op = stencil->zfail_op;
+ break;
+ case Z_PASS_OP:
+ stencil_op = stencil->zpass_op;
+ break;
+ default:
+ assert(0 && "Invalid stencil_op mode");
+ stencil_op = PIPE_STENCIL_OP_KEEP;
+ }
switch (stencil_op) {
case PIPE_STENCIL_OP_KEEP:
break;
case PIPE_STENCIL_OP_INVERT:
res = LLVMBuildNot(bld->builder, stencilVals, "");
+ res = LLVMBuildAnd(bld->builder, res, max, "");
break;
default:
assert(0 && "bad stencil op mode");
}
+/**
+ * Do the one or two-sided stencil test op/update.
+ */
+static LLVMValueRef
+lp_build_stencil_op(struct lp_build_context *bld,
+ const struct pipe_stencil_state stencil[2],
+ enum stencil_op op,
+ LLVMValueRef stencilRefs[2],
+ LLVMValueRef stencilVals,
+ LLVMValueRef mask,
+ LLVMValueRef face)
+
+{
+ assert(stencil[0].enabled);
+
+ if (stencil[1].enabled && face) {
+ /* do two-sided op */
+ struct lp_build_flow_context *flow_ctx;
+ struct lp_build_if_state if_ctx;
+ LLVMValueRef front_facing;
+ LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0);
+ LLVMValueRef result = bld->undef;
+
+ flow_ctx = lp_build_flow_create(bld->builder);
+ lp_build_flow_scope_begin(flow_ctx);
+
+ lp_build_flow_scope_declare(flow_ctx, &result);
+
+ /* front_facing = face > 0.0 */
+ front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, "");
+
+ lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing);
+ {
+ result = lp_build_stencil_op_single(bld, &stencil[0], op,
+ stencilRefs[0], stencilVals, mask);
+ }
+ lp_build_else(&if_ctx);
+ {
+ result = lp_build_stencil_op_single(bld, &stencil[1], op,
+ stencilRefs[1], stencilVals, mask);
+ }
+ lp_build_endif(&if_ctx);
+
+ lp_build_flow_scope_end(flow_ctx);
+ lp_build_flow_destroy(flow_ctx);
+
+ return result;
+ }
+ else {
+ /* do single-sided op */
+ return lp_build_stencil_op_single(bld, &stencil[0], op,
+ stencilRefs[0], stencilVals, mask);
+ }
+}
+
+
+
/**
* Return a type appropriate for depth/stencil testing.
*/
}
-static LLVMValueRef
-lp_build_get_stencil_ref(struct lp_build_context *bld,
- struct lp_type type, LLVMValueRef stencil_refs_ptr)
+/**
+ * Compute bitmask and bit shift to apply to the incoming fragment Z values
+ * and the Z buffer values needed before doing the Z comparison.
+ *
+ * Note that we leave the Z bits in the position that we find them
+ * in the Z buffer (typically 0xffffff00 or 0x00ffffff). That lets us
+ * get by with fewer bit twiddling steps.
+ */
+static boolean
+get_z_shift_and_mask(const struct util_format_description *format_desc,
+ unsigned *shift, unsigned *mask)
+{
+ const unsigned total_bits = format_desc->block.bits;
+ unsigned z_swizzle;
+ int chan;
+ unsigned padding_left, padding_right;
+
+ assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
+ assert(format_desc->block.width == 1);
+ assert(format_desc->block.height == 1);
+
+ z_swizzle = format_desc->swizzle[0];
+
+ if (z_swizzle == UTIL_FORMAT_SWIZZLE_NONE)
+ return FALSE;
+
+ padding_right = 0;
+ for (chan = 0; chan < z_swizzle; ++chan)
+ padding_right += format_desc->channel[chan].size;
+
+ padding_left =
+ total_bits - (padding_right + format_desc->channel[z_swizzle].size);
+
+ if (padding_left || padding_right) {
+ unsigned long long mask_left = (1ULL << (total_bits - padding_left)) - 1;
+ unsigned long long mask_right = (1ULL << (padding_right)) - 1;
+ *mask = mask_left ^ mask_right;
+ }
+ else {
+ *mask = 0xffffffff;
+ }
+
+ *shift = padding_left;
+
+ return TRUE;
+}
+
+
+/**
+ * Compute bitmask and bit shift to apply to the framebuffer pixel values
+ * to put the stencil bits in the least significant position.
+ * (i.e. 0x000000ff)
+ */
+static boolean
+get_s_shift_and_mask(const struct util_format_description *format_desc,
+ unsigned *shift, unsigned *mask)
{
- LLVMValueRef indexes[2], ptr, ref, ref_vec;
+ unsigned s_swizzle;
+ int chan, sz;
+
+ s_swizzle = format_desc->swizzle[1];
- /* load 0th element of the array */
- indexes[0] = indexes[1] = LLVMConstInt(LLVMInt32Type(), 0, 0);
- ptr = LLVMBuildGEP(bld->builder, stencil_refs_ptr, indexes, 2, "");
- ref = LLVMBuildLoad(bld->builder, ptr, "");
+ if (s_swizzle == UTIL_FORMAT_SWIZZLE_NONE)
+ return FALSE;
- /* convert int8 value to i32 */
- ref = LLVMBuildZExt(bld->builder, ref, LLVMIntType(type.width), "");
+ *shift = 0;
+ for (chan = 0; chan < s_swizzle; chan++)
+ *shift += format_desc->channel[chan].size;
- /* make scalar into vector */
- ref_vec = lp_build_broadcast_scalar(bld, ref);
+ sz = format_desc->channel[s_swizzle].size;
+ *mask = (1U << sz) - 1U;
- return ref_vec;
+ return TRUE;
}
+
/**
* Generate code for performing depth and/or stencil tests.
* We operate on a vector of values (typically a 2x2 quad).
*
+ * \param depth the depth test state
+ * \param stencil the front/back stencil state
* \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
+ * \param mask the alive/dead pixel mask for the quad (vector)
+ * \param stencil_refs the front/back stencil ref values (scalar)
+ * \param z_src the incoming depth/stencil values (a 2x2 quad)
+ * \param zs_dst_ptr pointer to depth/stencil values in framebuffer
+ * \param facing contains float value indicating front/back facing polygon
*/
void
lp_build_depth_stencil_test(LLVMBuilderRef builder,
struct lp_type type,
const struct util_format_description *format_desc,
struct lp_build_mask_context *mask,
- LLVMValueRef stencil_refs,
+ LLVMValueRef stencil_refs[2],
LLVMValueRef z_src,
- LLVMValueRef zs_dst_ptr)
+ LLVMValueRef zs_dst_ptr,
+ LLVMValueRef face)
{
struct lp_build_context bld;
- unsigned z_swizzle, s_swizzle;
+ struct lp_build_context sbld;
+ struct lp_type s_type;
LLVMValueRef zs_dst, z_dst = NULL;
LLVMValueRef stencil_vals = NULL;
- LLVMValueRef z_bitmask = NULL, s_bitmask = NULL;
+ LLVMValueRef z_bitmask = NULL, stencil_shift = NULL;
LLVMValueRef z_pass = NULL, s_pass_mask = NULL;
LLVMValueRef orig_mask = mask->value;
- assert(depth->enabled || stencil[0].enabled);
+ /* Sanity checking */
+ {
+ const unsigned z_swizzle = format_desc->swizzle[0];
+ const unsigned s_swizzle = format_desc->swizzle[1];
- assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
- assert(format_desc->block.width == 1);
- assert(format_desc->block.height == 1);
+ assert(z_swizzle != UTIL_FORMAT_SWIZZLE_NONE ||
+ s_swizzle != UTIL_FORMAT_SWIZZLE_NONE);
- z_swizzle = format_desc->swizzle[0];
- s_swizzle = format_desc->swizzle[1];
+ assert(depth->enabled || stencil[0].enabled);
- assert(z_swizzle != UTIL_FORMAT_SWIZZLE_NONE ||
- s_swizzle != UTIL_FORMAT_SWIZZLE_NONE);
+ assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
+ assert(format_desc->block.width == 1);
+ assert(format_desc->block.height == 1);
- /* Sanity checking */
- assert(z_swizzle < 4);
- assert(format_desc->block.bits == type.width);
- if(type.floating) {
- assert(z_swizzle == 0);
- assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_FLOAT);
- assert(format_desc->channel[z_swizzle].size == format_desc->block.bits);
- }
- else {
- assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED);
- assert(format_desc->channel[z_swizzle].normalized);
- assert(!type.fixed);
- assert(!type.sign);
- assert(type.norm);
+ if (stencil[0].enabled) {
+ assert(format_desc->format == PIPE_FORMAT_Z24S8_UNORM ||
+ format_desc->format == PIPE_FORMAT_S8Z24_UNORM);
+ }
+
+ assert(z_swizzle < 4);
+ assert(format_desc->block.bits == type.width);
+ if (type.floating) {
+ assert(z_swizzle == 0);
+ assert(format_desc->channel[z_swizzle].type ==
+ UTIL_FORMAT_TYPE_FLOAT);
+ assert(format_desc->channel[z_swizzle].size ==
+ format_desc->block.bits);
+ }
+ else {
+ assert(format_desc->channel[z_swizzle].type ==
+ UTIL_FORMAT_TYPE_UNSIGNED);
+ assert(format_desc->channel[z_swizzle].normalized);
+ assert(!type.fixed);
+ assert(!type.sign);
+ assert(type.norm);
+ }
}
- /* Setup build context */
+
+ /* Setup build context for Z vals */
lp_build_context_init(&bld, builder, type);
+ /* Setup build context for stencil vals */
+ s_type = lp_type_int_vec(type.width);
+ lp_build_context_init(&sbld, builder, s_type);
+
/* Load current z/stencil value from z/stencil buffer */
zs_dst = LLVMBuildLoad(builder, zs_dst_ptr, "");
lp_build_name(zs_dst, "zsbufval");
- /* Align the source depth bits with the destination's, and mask out any
- * stencil or padding bits from both */
- if(format_desc->channel[z_swizzle].size == format_desc->block.bits) {
- assert(z_swizzle == 0);
- z_dst = zs_dst;
- }
- else {
- /* shift/mask bits to right-justify the Z bits */
- unsigned padding_left;
- unsigned padding_right;
- unsigned chan;
-
- assert(format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN);
- assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED);
- assert(format_desc->channel[z_swizzle].size <= format_desc->block.bits);
- assert(format_desc->channel[z_swizzle].normalized);
-
- padding_right = 0;
- for(chan = 0; chan < z_swizzle; ++chan)
- padding_right += format_desc->channel[chan].size;
- padding_left = format_desc->block.bits -
- (padding_right + format_desc->channel[z_swizzle].size);
-
- if(padding_left || padding_right) {
- const unsigned long long mask_left = (1ULL << (format_desc->block.bits - padding_left)) - 1;
- const unsigned long long mask_right = (1ULL << (padding_right)) - 1;
- z_bitmask = lp_build_const_int_vec(type, mask_left ^ mask_right);
- }
-
- s_bitmask = LLVMBuildNot(builder, z_bitmask, "");
- stencil_vals = LLVMBuildAnd(builder, zs_dst, s_bitmask, "");
+ /* Compute and apply the Z/stencil bitmasks and shifts.
+ */
+ {
+ unsigned z_shift, z_mask;
+ unsigned s_shift, s_mask;
+
+ if (get_z_shift_and_mask(format_desc, &z_shift, &z_mask)) {
+ if (z_shift) {
+ LLVMValueRef shift = lp_build_const_int_vec(type, z_shift);
+ z_src = LLVMBuildLShr(builder, z_src, shift, "");
+ }
+
+ if (z_mask != 0xffffffff) {
+ LLVMValueRef mask = lp_build_const_int_vec(type, z_mask);
+ z_src = LLVMBuildAnd(builder, z_src, mask, "");
+ z_dst = LLVMBuildAnd(builder, zs_dst, mask, "");
+ z_bitmask = mask; /* used below */
+ }
+ else {
+ z_dst = zs_dst;
+ }
+
+ lp_build_name(z_dst, "zsbuf.z");
+ }
- if(padding_left)
- z_src = LLVMBuildLShr(builder, z_src,
- lp_build_const_int_vec(type, padding_left), "");
- if(padding_right)
- z_src = LLVMBuildAnd(builder, z_src, z_bitmask, "");
- if(padding_left || padding_right)
- z_dst = LLVMBuildAnd(builder, zs_dst, z_bitmask, "");
- else
- z_dst = zs_dst;
+ if (get_s_shift_and_mask(format_desc, &s_shift, &s_mask)) {
+ if (s_shift) {
+ LLVMValueRef shift = lp_build_const_int_vec(type, s_shift);
+ stencil_vals = LLVMBuildLShr(builder, zs_dst, shift, "");
+ stencil_shift = shift; /* used below */
+ }
+ else {
+ stencil_vals = zs_dst;
+ }
+
+ if (s_mask != 0xffffffff) {
+ LLVMValueRef mask = lp_build_const_int_vec(type, s_mask);
+ stencil_vals = LLVMBuildAnd(builder, stencil_vals, mask, "");
+ }
+
+ lp_build_name(stencil_vals, "stencil");
+ }
}
- lp_build_name(z_dst, "zsbuf.z");
-
- /*
- printf("build depth %d stencil %d\n",
- depth->enabled,
- stencil[0].enabled);
- */
if (stencil[0].enabled) {
- /* Incoming stencil_refs is ptr to int8[2]. Get/convert to int32[4]. */
- stencil_refs = lp_build_get_stencil_ref(&bld, type, stencil_refs);
+ /* convert scalar stencil refs into vectors */
+ stencil_refs[0] = lp_build_broadcast_scalar(&bld, stencil_refs[0]);
+ stencil_refs[1] = lp_build_broadcast_scalar(&bld, stencil_refs[1]);
- s_pass_mask = lp_build_stencil_test(&bld, stencil,
- stencil_refs, stencil_vals);
+ s_pass_mask = lp_build_stencil_test(&sbld, stencil,
+ stencil_refs, stencil_vals, face);
/* apply stencil-fail operator */
{
LLVMValueRef s_fail_mask = lp_build_andc(&bld, orig_mask, s_pass_mask);
- stencil_vals = lp_build_stencil_op(&bld, stencil, stencil[0].fail_op,
+ stencil_vals = lp_build_stencil_op(&sbld, stencil, S_FAIL_OP,
stencil_refs, stencil_vals,
- s_fail_mask);
+ s_fail_mask, face);
}
}
/* apply Z-fail operator */
z_fail_mask = lp_build_andc(&bld, orig_mask, z_pass);
- stencil_vals = lp_build_stencil_op(&bld, stencil, stencil[0].zfail_op,
+ stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_FAIL_OP,
stencil_refs, stencil_vals,
- z_fail_mask);
+ z_fail_mask, face);
/* apply Z-pass operator */
z_pass_mask = LLVMBuildAnd(bld.builder, orig_mask, z_pass, "");
- stencil_vals = lp_build_stencil_op(&bld, stencil, stencil[0].zpass_op,
+ stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_PASS_OP,
stencil_refs, stencil_vals,
- z_pass_mask);
+ z_pass_mask, face);
}
}
else {
* passed the stencil test.
*/
s_pass_mask = LLVMBuildAnd(bld.builder, orig_mask, s_pass_mask, "");
- stencil_vals = lp_build_stencil_op(&bld, stencil, stencil[0].zpass_op,
- stencil_refs, stencil_vals, s_pass_mask);
+ stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_PASS_OP,
+ stencil_refs, stencil_vals,
+ s_pass_mask, face);
}
+ /* The Z bits are already in the right place but we may need to shift the
+ * stencil bits before ORing Z with Stencil to make the final pixel value.
+ */
+ if (stencil_vals && stencil_shift)
+ stencil_vals = LLVMBuildShl(bld.builder, stencil_vals,
+ stencil_shift, "");
+
/* Finally, merge/store the z/stencil values */
if ((depth->enabled && depth->writemask) ||
(stencil[0].enabled && stencil[0].writemask)) {
struct lp_type type,
const struct util_format_description *format_desc,
struct lp_build_mask_context *mask,
- LLVMValueRef stencil_refs,
+ LLVMValueRef stencil_refs[2],
LLVMValueRef zs_src,
- LLVMValueRef zs_dst_ptr);
+ LLVMValueRef zs_dst_ptr,
+ LLVMValueRef facing);
#endif /* !LP_BLD_DEPTH_H */
PIPE_FORMAT_X8R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , yzw1, rgb
PIPE_FORMAT_A8B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , wzyx, rgb
PIPE_FORMAT_X8B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , wzy1, rgb
+PIPE_FORMAT_B5G5R5X1_UNORM , plain, 1, 1, un5 , un5 , un5 , un1 , zyx1, rgb
PIPE_FORMAT_B5G5R5A1_UNORM , plain, 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb
PIPE_FORMAT_B4G4R4A4_UNORM , plain, 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb
PIPE_FORMAT_B5G6R5_UNORM , plain, 1, 1, un5 , un6 , un5 , , zyx1, rgb
* 16-bit rendertarget formats
*/
+ {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 0.0}},
+ {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x03e0), {0.0, 1.0, 0.0, 0.0}},
+ {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x7c00), {1.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x8000), {0.0, 0.0, 0.0, 1.0}},
+ {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}},
+
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}},
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 0.0}},
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x03e0), {0.0, 1.0, 0.0, 0.0}},
*datatype = DTYPE_UBYTE;
*comps = 4;
return;
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
case PIPE_FORMAT_B5G5R5A1_UNORM:
*datatype = DTYPE_USHORT_1_5_5_5_REV;
*comps = 4;
uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
}
return;
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ {
+ uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
+ }
+ return;
case PIPE_FORMAT_B5G5R5A1_UNORM:
{
uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
*a = (ubyte) 0xff;
}
return;
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ {
+ ushort p = uc->us;
+ *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
+ *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
+ *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
+ *a = (ubyte) 0xff;
+ }
+ return;
case PIPE_FORMAT_B5G5R5A1_UNORM:
{
ushort p = uc->us;
uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
}
return;
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ {
+ uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
+ }
+ return;
case PIPE_FORMAT_B5G5R5A1_UNORM:
{
uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
}
+/*** PIPE_FORMAT_B5G5R5X1_UNORM ***/
+
+static void
+x1r5g5b5_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ const ushort pixel = *src++;
+ pRow[0] = ((pixel >> 10) & 0x1f) * (1.0f / 31.0f);
+ pRow[1] = ((pixel >> 5) & 0x1f) * (1.0f / 31.0f);
+ pRow[2] = ((pixel ) & 0x1f) * (1.0f / 31.0f);
+ pRow[3] = 1.0f;
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+x1r5g5b5_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, g, b;
+ r = float_to_ubyte(pRow[0]);
+ g = float_to_ubyte(pRow[1]);
+ b = float_to_ubyte(pRow[2]);
+ r = r >> 3; /* 5 bits */
+ g = g >> 3; /* 5 bits */
+ b = b >> 3; /* 5 bits */
+ *dst++ = (1 << 15) | (r << 10) | (g << 5) | b;
+ }
+ p += src_stride;
+ }
+}
+
+
/*** PIPE_FORMAT_B5G5R5A1_UNORM ***/
static void
case PIPE_FORMAT_A8B8G8R8_UNORM:
r8g8b8a8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
break;
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ x1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
+ break;
case PIPE_FORMAT_B5G5R5A1_UNORM:
a1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_A8B8G8R8_UNORM:
r8g8b8a8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);
break;
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ x1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
+ break;
case PIPE_FORMAT_B5G5R5A1_UNORM:
a1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
break;
These pieces of state are too small, variable, and/or trivial to have CSO
objects. They all follow simple, one-method binding calls, e.g.
``set_blend_color``.
+
* ``set_stencil_ref`` sets the stencil front and back reference values
which are used as comparison values in stencil test.
* ``set_blend_color``
formats, that is formats that have matching component order and sizes.
Swizzle fields specify they way in which fetched texel components are placed
-in the result register. For example, swizzle_r specifies what is going to be
-placed in destination register x (AKA r).
+in the result register. For example, ``swizzle_r`` specifies what is going to be
+placed in first component of result register.
-first_level and last_level fields of sampler view template specify the LOD
-range the texture is going to be constrained to.
+The ``first_level`` and ``last_level`` fields of sampler view template specify
+the LOD range the texture is going to be constrained to.
* ``set_fragment_sampler_views`` binds an array of sampler views to
fragment shader stage. Every binding point acquires a reference
shader stage. Every binding point acquires a reference to a respective
sampler view and releases a reference to the previous sampler view.
-* ``create_sampler_view`` creates a new sampler view. texture is associated
+* ``create_sampler_view`` creates a new sampler view. ``texture`` is associated
with the sampler view which results in sampler view holding a reference
to the texture. Format specified in template must be compatible
with texture format.
-.. _vertex,elements
+.. _vertexelements:
Vertex Elements
===============
elem_types[LP_JIT_CTX_CONSTANTS] = LLVMPointerType(LLVMFloatType(), 0);
elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatType();
- elem_types[LP_JIT_CTX_STENCIL_REF] = LLVMArrayType(LLVMInt8Type(), 2);
+ elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] = LLVMInt32Type();
+ elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32Type();
elem_types[LP_JIT_CTX_SCISSOR_XMIN] = LLVMFloatType();
elem_types[LP_JIT_CTX_SCISSOR_YMIN] = LLVMFloatType();
elem_types[LP_JIT_CTX_SCISSOR_XMAX] = LLVMFloatType();
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
screen->target, context_type,
LP_JIT_CTX_ALPHA_REF);
- LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref,
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_front,
screen->target, context_type,
- LP_JIT_CTX_STENCIL_REF);
+ LP_JIT_CTX_STENCIL_REF_FRONT);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_back,
+ screen->target, context_type,
+ LP_JIT_CTX_STENCIL_REF_BACK);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmin,
screen->target, context_type,
LP_JIT_CTX_SCISSOR_XMIN);
float alpha_ref_value;
- uint8_t stencil_ref[2];
+ uint32_t stencil_ref_front, stencil_ref_back;
/** floats, not ints */
float scissor_xmin, scissor_ymin, scissor_xmax, scissor_ymax;
enum {
LP_JIT_CTX_CONSTANTS = 0,
LP_JIT_CTX_ALPHA_REF,
- LP_JIT_CTX_STENCIL_REF,
+ LP_JIT_CTX_STENCIL_REF_FRONT,
+ LP_JIT_CTX_STENCIL_REF_BACK,
LP_JIT_CTX_SCISSOR_XMIN,
LP_JIT_CTX_SCISSOR_YMIN,
LP_JIT_CTX_SCISSOR_XMAX,
#define lp_jit_context_alpha_ref_value(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_ALPHA_REF, "alpha_ref_value")
-#define lp_jit_context_stencil_ref_values(_builder, _ptr) \
- lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CTX_STENCIL_REF, "stencil_ref")
+#define lp_jit_context_stencil_ref_front_value(_builder, _ptr) \
+ lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_STENCIL_REF_FRONT, "stencil_ref_front")
+
+#define lp_jit_context_stencil_ref_back_value(_builder, _ptr) \
+ lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_STENCIL_REF_BACK, "stencil_ref_back")
#define lp_jit_context_scissor_xmin_value(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_SCISSOR_XMIN, "scissor_xmin")
lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES, "textures")
+/** Indexes into jit_function[] array */
+#define RAST_WHOLE 0
+#define RAST_EDGE_TEST 1
+
+
typedef void
(*lp_jit_frag_func)(const struct lp_jit_context *context,
uint32_t x,
uint32_t y,
+ float facing,
const void *a0,
const void *dadx,
const void *dady,
depth = lp_rast_depth_pointer(rast, tile_x + x, tile_y + y);
/* run shader */
- state->jit_function[0]( &state->jit_context,
- tile_x + x, tile_y + y,
- inputs->a0,
- inputs->dadx,
- inputs->dady,
- color,
- depth,
- INT_MIN, INT_MIN, INT_MIN,
- NULL, NULL, NULL );
+ state->jit_function[RAST_WHOLE]( &state->jit_context,
+ tile_x + x, tile_y + y,
+ inputs->facing,
+ inputs->a0,
+ inputs->dadx,
+ inputs->dady,
+ color,
+ depth,
+ INT_MIN, INT_MIN, INT_MIN,
+ NULL, NULL, NULL );
}
}
}
assert(lp_check_alignment(inputs->step[2], 16));
/* run shader */
- state->jit_function[1]( &state->jit_context,
- x, y,
- inputs->a0,
- inputs->dadx,
- inputs->dady,
- color,
- depth,
- c1, c2, c3,
- inputs->step[0], inputs->step[1], inputs->step[2]);
+ state->jit_function[RAST_EDGE_TEST]( &state->jit_context,
+ x, y,
+ inputs->facing,
+ inputs->a0,
+ inputs->dadx,
+ inputs->dady,
+ color,
+ depth,
+ c1, c2, c3,
+ inputs->step[0],
+ inputs->step[1],
+ inputs->step[2]);
}
* These pointers point into the bin data buffer.
*/
struct lp_rast_shader_inputs {
+ float facing; /** Positive for front-facing, negative for back-facing */
+
float (*a0)[4];
float (*dadx)[4];
float (*dady)[4];
/* run shader */
state->jit_function[0]( &state->jit_context,
x, y,
+ inputs->facing,
inputs->a0,
inputs->dadx,
inputs->dady,
{
LP_DBG(DEBUG_SETUP, "%s %d %d\n", __FUNCTION__, refs[0], refs[1]);
- if (setup->fs.current.jit_context.stencil_ref[0] != refs[0] ||
- setup->fs.current.jit_context.stencil_ref[1] != refs[1]) {
- setup->fs.current.jit_context.stencil_ref[0] = refs[0];
- setup->fs.current.jit_context.stencil_ref[1] = refs[1];
+ if (setup->fs.current.jit_context.stencil_ref_front != refs[0] ||
+ setup->fs.current.jit_context.stencil_ref_back != refs[1]) {
+ setup->fs.current.jit_context.stencil_ref_front = refs[0];
+ setup->fs.current.jit_context.stencil_ref_back = refs[1];
setup->dirty |= LP_SETUP_NEW_FS;
}
}
*/
setup_tri_coefficients( setup, tri, oneoverarea, v1, v2, v3, frontfacing );
+ tri->inputs.facing = frontfacing ? 1.0F : -1.0F;
+
/* half-edge constants, will be interated over the whole render target.
*/
tri->c1 = tri->dy12 * x1 - tri->dx12 * y1;
const struct lp_fragment_shader_variant_key *key,
struct lp_type src_type,
struct lp_build_mask_context *mask,
- LLVMValueRef stencil_refs,
+ LLVMValueRef stencil_refs[2],
LLVMValueRef src,
- LLVMValueRef dst_ptr)
+ LLVMValueRef dst_ptr,
+ LLVMValueRef facing)
{
const struct util_format_description *format_desc;
struct lp_type dst_type;
+ if (!key->depth.enabled && !key->stencil[0].enabled && !key->stencil[1].enabled)
+ return;
+
format_desc = util_format_description(key->zsbuf_format);
assert(format_desc);
mask,
stencil_refs,
src,
- dst_ptr);
+ dst_ptr,
+ facing);
}
LLVMValueRef *pmask,
LLVMValueRef (*color)[4],
LLVMValueRef depth_ptr,
+ LLVMValueRef facing,
unsigned do_tri_test,
LLVMValueRef c0,
LLVMValueRef c1,
LLVMValueRef consts_ptr;
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
LLVMValueRef z = interp->pos[2];
- LLVMValueRef stencil_refs;
+ LLVMValueRef stencil_refs[2];
struct lp_build_flow_context *flow;
struct lp_build_mask_context mask;
boolean early_depth_stencil_test;
assert(i < 4);
- stencil_refs = lp_jit_context_stencil_ref_values(builder, context_ptr);
+ stencil_refs[0] = lp_jit_context_stencil_ref_front_value(builder, context_ptr);
+ stencil_refs[1] = lp_jit_context_stencil_ref_back_value(builder, context_ptr);
elem_type = lp_build_elem_type(type);
vec_type = lp_build_vec_type(type);
if (early_depth_stencil_test)
generate_depth_stencil(builder, key,
type, &mask,
- stencil_refs, z, depth_ptr);
+ stencil_refs, z, depth_ptr, facing);
lp_build_tgsi_soa(builder, tokens, type, &mask,
consts_ptr, interp->pos, interp->inputs,
if (!early_depth_stencil_test)
generate_depth_stencil(builder, key,
type, &mask,
- stencil_refs, z, depth_ptr);
+ stencil_refs, z, depth_ptr, facing);
lp_build_mask_end(&mask);
LLVMTypeRef fs_int_vec_type;
LLVMTypeRef blend_vec_type;
LLVMTypeRef blend_int_vec_type;
- LLVMTypeRef arg_types[14];
+ LLVMTypeRef arg_types[15];
LLVMTypeRef func_type;
LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_type();
LLVMValueRef context_ptr;
LLVMValueRef blend_mask;
LLVMValueRef blend_in_color[NUM_CHANNELS];
LLVMValueRef function;
+ LLVMValueRef facing;
unsigned num_fs;
unsigned i;
unsigned chan;
arg_types[0] = screen->context_ptr_type; /* context */
arg_types[1] = LLVMInt32Type(); /* x */
arg_types[2] = LLVMInt32Type(); /* y */
- arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */
- arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */
- arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */
- arg_types[6] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */
- arg_types[7] = LLVMPointerType(fs_int_vec_type, 0); /* depth */
- arg_types[8] = LLVMInt32Type(); /* c0 */
- arg_types[9] = LLVMInt32Type(); /* c1 */
- arg_types[10] = LLVMInt32Type(); /* c2 */
+ arg_types[3] = LLVMFloatType(); /* facing */
+ arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* a0 */
+ arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dadx */
+ arg_types[6] = LLVMPointerType(fs_elem_type, 0); /* dady */
+ arg_types[7] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */
+ arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */
+ arg_types[9] = LLVMInt32Type(); /* c0 */
+ arg_types[10] = LLVMInt32Type(); /* c1 */
+ arg_types[11] = LLVMInt32Type(); /* c2 */
/* Note: the step arrays are built as int32[16] but we interpret
* them here as int32_vec4[4].
*/
- arg_types[11] = LLVMPointerType(int32_vec4_type, 0);/* step0 */
- arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step1 */
- arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step2 */
+ arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step0 */
+ arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step1 */
+ arg_types[14] = LLVMPointerType(int32_vec4_type, 0);/* step2 */
func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
context_ptr = LLVMGetParam(function, 0);
x = LLVMGetParam(function, 1);
y = LLVMGetParam(function, 2);
- a0_ptr = LLVMGetParam(function, 3);
- dadx_ptr = LLVMGetParam(function, 4);
- dady_ptr = LLVMGetParam(function, 5);
- color_ptr_ptr = LLVMGetParam(function, 6);
- depth_ptr = LLVMGetParam(function, 7);
- c0 = LLVMGetParam(function, 8);
- c1 = LLVMGetParam(function, 9);
- c2 = LLVMGetParam(function, 10);
- step0_ptr = LLVMGetParam(function, 11);
- step1_ptr = LLVMGetParam(function, 12);
- step2_ptr = LLVMGetParam(function, 13);
+ facing = LLVMGetParam(function, 3);
+ a0_ptr = LLVMGetParam(function, 4);
+ dadx_ptr = LLVMGetParam(function, 5);
+ dady_ptr = LLVMGetParam(function, 6);
+ color_ptr_ptr = LLVMGetParam(function, 7);
+ depth_ptr = LLVMGetParam(function, 8);
+ c0 = LLVMGetParam(function, 9);
+ c1 = LLVMGetParam(function, 10);
+ c2 = LLVMGetParam(function, 11);
+ step0_ptr = LLVMGetParam(function, 12);
+ step1_ptr = LLVMGetParam(function, 13);
+ step2_ptr = LLVMGetParam(function, 14);
lp_build_name(context_ptr, "context");
lp_build_name(x, "x");
&fs_mask[i], /* output */
out_color,
depth_ptr_i,
+ facing,
do_tri_test,
c0, c1, c2,
step0_ptr, step1_ptr, step2_ptr);
opaque = !key.blend.logicop_enable &&
!key.blend.rt[0].blend_enable &&
key.blend.rt[0].colormask == 0xf &&
+ !key.stencil[0].enabled &&
!key.alpha.enabled &&
!key.depth.enabled &&
!key.scissor &&
? TRUE : FALSE;
lp_setup_set_fs_functions(lp->setup,
- shader->current->jit_function[0],
- shader->current->jit_function[1],
+ shader->current->jit_function[RAST_WHOLE],
+ shader->current->jit_function[RAST_EDGE_TEST],
opaque);
}
}
static unsigned int
-r300_is_texture_referenced(struct pipe_context *pipe,
+r300_is_texture_referenced(struct pipe_context *context,
struct pipe_texture *texture,
unsigned face, unsigned level)
{
- return 0;
+ struct r300_context* r300 = r300_context(context);
+ struct r300_texture* tex = (struct r300_texture*)texture;
+
+ return r300->rws->is_buffer_referenced(r300->rws, tex->buffer);
}
static unsigned int
-r300_is_buffer_referenced(struct pipe_context *pipe,
+r300_is_buffer_referenced(struct pipe_context *context,
struct pipe_buffer *buf)
{
- /* This only checks to see whether actual hardware buffers are
- * referenced. Since we use managed BOs and transfers, it's actually not
- * possible for pipe_buffers to ever reference the actual hardware, so
- * buffers are never referenced.
- */
-
- /* XXX: that doesn't make sense given that
- * r300_is_texture_referenced is implemented on top of this
- * function and hardware can certainly refer to textures
- * directly...
- */
- return 0;
+ struct r300_context* r300 = r300_context(context);
+
+ return r300_buffer_is_referenced(r300, buf);
}
static void r300_flush_cb(void *data)
r300_setup_atoms(r300);
+ r300->sprite_coord_index = -1;
+
/* Open up the OQ BO. */
r300->oqbo = screen->buffer_create(screen, 4096,
PIPE_BUFFER_USAGE_VERTEX, 4096);
uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */
uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */
uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */
+
+ /* Specifies top of Raster pipe specific enable controls,
+ * i.e. texture coordinates stuffing for points, lines, triangles */
+ uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */
+
+ /* Point sprites texture coordinates, 0: lower left, 1: upper right */
+ float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */
+ float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */
+ float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */
+ float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */
};
struct r300_rs_block {
uint32_t zbuffer_bpp;
/* Whether scissor is enabled. */
boolean scissor_enabled;
+ /* Point sprites texcoord index, -1 = unused. */
+ int sprite_coord_index;
+
/* upload managers */
struct u_upload_mgr *upload_vb;
struct u_upload_mgr *upload_ib;
OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config);
OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value);
OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode);
+ OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable);
+ OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
+ OUT_CS_32F(rs->point_texcoord_left);
+ OUT_CS_32F(rs->point_texcoord_bottom);
+ OUT_CS_32F(rs->point_texcoord_right);
+ OUT_CS_32F(rs->point_texcoord_top);
END_CS;
}
}
/* ...textures... */
for (i = 0; i < texstate->count; i++) {
- tex = (struct r300_texture*)texstate->fragment_sampler_views[i]->texture;
- if (!tex || !texstate->sampler_states[i])
+ if (!(texstate->tx_enable & (1 << i))) {
continue;
+ }
+
+ tex = (struct r300_texture*)texstate->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);
unsigned vertex_element_count = r300->velems->count;
unsigned i, vbi;
- if (count > 4) {
+ if (count > 10) {
return FALSE;
}
if (!checked[vbi]) {
vbuf = &r300->vertex_buffer[vbi];
- if (r300_buffer_is_referenced(r300,
- vbuf->buffer)) {
+ if (r300_buffer_is_referenced(r300, vbuf->buffer)) {
/* It's a very bad idea to map it... */
return FALSE;
}
#endif
CS_LOCALS(r300);
- assert((start * indexSize) % 4 == 0);
assert(count < (1 << 24));
- maxIndex = MIN3(maxIndex, r300->vertex_buffer_max_index, count - minIndex);
+ maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index);
DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n",
count, minIndex, maxIndex);
static void r300_shorten_ubyte_elts(struct r300_context* r300,
struct pipe_buffer** elts,
+ unsigned start,
unsigned count)
{
struct pipe_screen* screen = r300->context.screen;
in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ);
out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE);
+ in_map += start;
+
for (i = 0; i < count; i++) {
*out_map = (unsigned short)*in_map;
in_map++;
*elts = new_elts;
}
+static void r300_align_ushort_elts(struct r300_context *r300,
+ struct pipe_buffer **elts,
+ unsigned start, unsigned count)
+{
+ struct pipe_screen* screen = r300->context.screen;
+ struct pipe_buffer* new_elts;
+ unsigned short *in_map;
+ unsigned short *out_map;
+
+ new_elts = screen->buffer_create(screen, 32,
+ PIPE_BUFFER_USAGE_INDEX |
+ PIPE_BUFFER_USAGE_CPU_WRITE |
+ PIPE_BUFFER_USAGE_GPU_READ,
+ 2 * count);
+
+ in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ);
+ out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ memcpy(out_map, in_map+start, 2 * count);
+
+ pipe_buffer_unmap(screen, *elts);
+ pipe_buffer_unmap(screen, new_elts);
+
+ *elts = new_elts;
+}
+
/* This is the fast-path drawing & emission for HW TCL. */
void r300_draw_range_elements(struct pipe_context* pipe,
struct pipe_buffer* indexBuffer,
}
if (indexSize == 1) {
- r300_shorten_ubyte_elts(r300, &indexBuffer, count);
+ r300_shorten_ubyte_elts(r300, &indexBuffer, start, count);
indexSize = 2;
+ start = 0;
+ } else if (indexSize == 2 && start % 2 != 0) {
+ r300_align_ushort_elts(r300, &indexBuffer, start, count);
+ start = 0;
}
r300_update_derived_state(r300);
{
struct r300_screen* r300screen = r300_screen(pipe->screen);
struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
+ unsigned coord_index;
/* Copy rasterizer state for Draw. */
rs->rs = *state;
rs->color_control = R300_SHADE_MODEL_SMOOTH;
}
+ /* Point sprites */
+ if (state->sprite_coord_enable) {
+ coord_index = ffs(state->sprite_coord_enable)-1;
+
+ SCREEN_DBG(r300screen, DBG_DRAW,
+ "r300: point sprite: shader coord=%d\n", coord_index);
+
+ rs->stuffing_enable =
+ R300_GB_POINT_STUFF_ENABLE |
+ R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (coord_index*2));
+
+ rs->point_texcoord_left = 0.0f;
+ rs->point_texcoord_right = 1.0f;
+
+ switch (state->sprite_coord_mode) {
+ case PIPE_SPRITE_COORD_UPPER_LEFT:
+ rs->point_texcoord_top = 0.0f;
+ rs->point_texcoord_bottom = 1.0f;
+ break;
+ case PIPE_SPRITE_COORD_LOWER_LEFT:
+ rs->point_texcoord_top = 1.0f;
+ rs->point_texcoord_bottom = 0.0f;
+ break;
+ }
+ }
+
return (void*)rs;
}
struct r300_context* r300 = r300_context(pipe);
struct r300_rs_state* rs = (struct r300_rs_state*)state;
boolean scissor_was_enabled = r300->scissor_enabled;
+ int last_sprite_coord_index = r300->sprite_coord_index;
if (r300->draw) {
draw_flush(r300->draw);
if (rs) {
r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw;
r300->scissor_enabled = rs->rs.scissor;
+ r300->sprite_coord_index = ffs(rs->rs.sprite_coord_enable)-1;
} else {
r300->polygon_offset_enabled = FALSE;
r300->scissor_enabled = FALSE;
+ r300->sprite_coord_index = -1;
}
UPDATE_STATE(state, r300->rs_state);
- r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0);
+ r300->rs_state.size = 24 + (r300->polygon_offset_enabled ? 5 : 0);
if (scissor_was_enabled != r300->scissor_enabled) {
r300->scissor_state.dirty = TRUE;
}
+ if (last_sprite_coord_index != r300->sprite_coord_index) {
+ r300->rs_block_state.dirty = TRUE;
+ }
}
/* Free rasterizer state. */
struct r300_context* r300 = r300_context(pipe);
struct r300_textures_state* state =
(struct r300_textures_state*)r300->textures_state.state;
+ struct r300_texture *texture;
unsigned i;
boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
boolean dirty_tex = FALSE;
for (i = 0; i < count; i++) {
if (state->fragment_sampler_views[i] != views[i]) {
- struct r300_texture *texture;
-
pipe_sampler_view_reference(&state->fragment_sampler_views[i],
views[i]);
- dirty_tex = TRUE;
- texture = (struct r300_texture *)views[i]->texture;
+ if (!views[i]) {
+ continue;
+ }
+
+ /* A new sampler view (= texture)... */
+ dirty_tex = TRUE;
/* R300-specific - set the texrect factor in the fragment shader */
+ texture = (struct r300_texture *)views[i]->texture;
if (!is_r500 && texture->is_npot) {
/* XXX It would be nice to re-emit just 1 constant,
* XXX not all of them */
return view;
}
-
static void
r300_sampler_view_destroy(struct pipe_context *pipe,
struct pipe_sampler_view *view)
const struct pipe_vertex_buffer* buffers)
{
struct r300_context* r300 = r300_context(pipe);
- int i;
- unsigned max_index = (1 << 24) - 1;
- boolean any_user_buffer = false;
+ struct pipe_vertex_buffer *vbo;
+ unsigned i, max_index = (1 << 24) - 1;
+ boolean any_user_buffer = FALSE;
if (count == r300->vertex_buffer_count &&
- memcmp(r300->vertex_buffer, buffers, count * sizeof(buffers[0])) == 0)
+ memcmp(r300->vertex_buffer, buffers,
+ sizeof(struct pipe_vertex_buffer) * count) == 0) {
return;
+ }
+ /* Check if the stride is aligned to the size of DWORD. */
for (i = 0; i < count; i++) {
- pipe_buffer_reference(&r300->vertex_buffer[i].buffer, buffers[i].buffer);
- if (r300_buffer_is_user_buffer(buffers[i].buffer))
- any_user_buffer = true;
- max_index = MIN2(buffers[i].max_index, max_index);
+ if (buffers[i].buffer) {
+ if (buffers[i].stride % 4 != 0) {
+ // XXX Shouldn't we align the buffer?
+ fprintf(stderr, "r300_set_vertex_buffers: "
+ "Unaligned buffer stride %i isn't supported.\n",
+ buffers[i].stride);
+ assert(0);
+ abort();
+ }
+ }
}
- for ( ; i < r300->vertex_buffer_count; i++)
- pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL);
+ for (i = 0; i < count; i++) {
+ /* Why, yes, I AM casting away constness. How did you know? */
+ vbo = (struct pipe_vertex_buffer*)&buffers[i];
+
+ /* Reference our buffer. */
+ pipe_buffer_reference(&r300->vertex_buffer[i].buffer, vbo->buffer);
+
+ /* Skip NULL buffers */
+ if (!buffers[i].buffer) {
+ continue;
+ }
+
+ if (r300_buffer_is_user_buffer(vbo->buffer)) {
+ any_user_buffer = TRUE;
+ }
+
+ if (vbo->max_index == ~0) {
+ /* Bogus value from broken state tracker; hax it. */
+ vbo->max_index =
+ (vbo->buffer->size - vbo->buffer_offset) / vbo->stride;
+ }
+
+ max_index = MIN2(vbo->max_index, max_index);
+ }
+
+ for (; i < r300->vertex_buffer_count; i++) {
+ /* Dereference any old buffers. */
+ pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL);
+ }
memcpy(r300->vertex_buffer, buffers,
- sizeof(struct pipe_vertex_buffer) * count);
+ sizeof(struct pipe_vertex_buffer) * count);
r300->vertex_buffer_count = count;
r300->vertex_buffer_max_index = max_index;
}
}
-static boolean r300_validate_aos(struct r300_context *r300)
-{
- struct pipe_vertex_buffer *vbuf = r300->vertex_buffer;
- struct pipe_vertex_element *velem = r300->velems->velem;
- int i;
-
- /* Check if formats and strides are aligned to the size of DWORD. */
- for (i = 0; i < r300->velems->count; i++) {
- if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 ||
- util_format_get_blocksize(velem[i].src_format) % 4 != 0) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
static void r300_draw_emit_attrib(struct r300_context* r300,
enum attrib_emit emit,
enum interp_mode interp,
struct r300_context *r300 = r300_context(pipe);
struct r300_screen* r300screen = r300_screen(pipe->screen);
struct r300_vertex_element_state *velems;
+ unsigned i, size;
assert(count <= PIPE_MAX_ATTRIBS);
velems = CALLOC_STRUCT(r300_vertex_element_state);
memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count);
if (r300screen->caps->has_tcl) {
+ /* Check if the format is aligned to the size of DWORD. */
+ for (i = 0; i < count; i++) {
+ size = util_format_get_blocksize(attribs[i].src_format);
+
+ if (size % 4 != 0) {
+ /* XXX Shouldn't we align the format? */
+ fprintf(stderr, "r300_create_vertex_elements_state: "
+ "Unaligned format %s:%i isn't supported\n",
+ util_format_name(attribs[i].src_format), size);
+ assert(0);
+ abort();
+ }
+ }
+
r300_vertex_psc(velems);
} else {
memset(&r300->vertex_info, 0, sizeof(struct vertex_info));
draw_set_vertex_elements(r300->draw, velems->count, velems->velem);
}
- if (!r300_validate_aos(r300)) {
- /* XXX We should fallback using draw. */
- assert(0);
- abort();
- }
-
UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state);
r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2;
}
/* Rasterize texture coordinates. */
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
- if (vs_outputs->generic[i] != ATTR_UNUSED) {
+ if (vs_outputs->generic[i] != ATTR_UNUSED ||
+ r300->sprite_coord_index == i) {
/* Always rasterize if it's written by the VS,
* otherwise it locks up. */
rX00_rs_tex(&rs, tex_count, tex_count, FALSE);
/* Write it to the FS input register if it's used by the FS. */
if (fs_inputs->generic[i] != ATTR_UNUSED) {
rX00_rs_tex_write(&rs, tex_count, fp_offset);
+ if (r300->sprite_coord_index == i)
+ debug_printf("r300: SpriteCoord (generic index %i) is being written to reg %i\n", i, fp_offset);
fp_offset++;
}
tex_count++;
(struct r300_textures_state*)r300->textures_state.state;
struct r300_texture_sampler_state *texstate;
struct r300_sampler_state *sampler;
+ struct pipe_sampler_view *view;
struct r300_texture *tex;
unsigned min_level, max_level, i, size;
unsigned count = MIN2(state->texture_count, state->sampler_count);
state->tx_enable = 0;
+ state->count = 0;
size = 2;
for (i = 0; i < count; i++) {
if (state->fragment_sampler_views[i] && state->sampler_states[i]) {
state->tx_enable |= 1 << i;
- tex = (struct r300_texture *)state->fragment_sampler_views[i]->texture;
+ view = state->fragment_sampler_views[i];
+ tex = (struct r300_texture *)view->texture;
sampler = state->sampler_states[i];
+ assert(view->format == tex->tex.format);
+
texstate = &state->regs[i];
memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3);
texstate->filter[0] = sampler->filter0;
} else {
/* determine min/max levels */
/* the MAX_MIP level is the largest (finest) one */
- max_level = MIN2(sampler->max_lod, tex->tex.last_level);
- min_level = MIN2(sampler->min_lod, max_level);
+ max_level = MIN3(sampler->max_lod + view->first_level,
+ tex->tex.last_level, view->last_level);
+ min_level = MIN2(sampler->min_lod + view->first_level,
+ max_level);
texstate->format[0] |= R300_TX_NUM_LEVELS(max_level);
texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level);
}
struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
CS_LOCALS(r300);
- BEGIN_CS(14 + (caps->has_tcl ? 2: 0));
+ BEGIN_CS(12 + (caps->has_tcl ? 2: 0));
/*** Graphics Backend (GB) ***/
- /* Various GB enables */
- OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
- R300_GB_LINE_STUFF_ENABLE |
- R300_GB_TRIANGLE_STUFF_ENABLE);
/* Subpixel multisampling for AA
* These are commented out because glisse's CS checker doesn't like them.
* I presume these will be re-enabled later.
END_CS;
/* XXX unsorted stuff from surface_fill */
- BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) +
+ BEGIN_CS(40 + (caps->has_tcl ? 7 : 0) +
(caps->family >= CHIP_FAMILY_RV350 ? 4 : 0));
if (caps->has_tcl) {
OUT_CS_32F(1.0);
OUT_CS_32F(1.0);
}
- /* XXX point tex stuffing */
- OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1);
- OUT_CS_32F(0.0);
- OUT_CS_REG_SEQ(R300_GA_POINT_S1, 1);
- OUT_CS_32F(1.0);
/* XXX line tex stuffing */
OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1);
OUT_CS_32F(0.0);
case PIPE_FORMAT_A8_UNORM:
case PIPE_FORMAT_I8_UNORM:
case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_L8_SRGB:
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8_SNORM:
return R300_COLOR_FORMAT_I8;
case PIPE_FORMAT_B5G6R5_UNORM:
return R300_COLOR_FORMAT_RGB565;
case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
return R300_COLOR_FORMAT_ARGB1555;
case PIPE_FORMAT_B4G4R4A4_UNORM:
return R300_COLOR_FORMAT_ARGB4444;
/* 32-bit buffers. */
case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_SRGB:
case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_SRGB:
case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_SRGB:
case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_SRGB:
case PIPE_FORMAT_A8B8G8R8_UNORM:
case PIPE_FORMAT_R8G8B8A8_SNORM:
- case PIPE_FORMAT_A8B8G8R8_SRGB:
case PIPE_FORMAT_X8B8G8R8_UNORM:
- case PIPE_FORMAT_X8B8G8R8_SRGB:
case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
return R300_COLOR_FORMAT_ARGB8888;
case PIPE_FORMAT_R10G10B10A2_UNORM:
desc = util_format_description(format);
/* Specifies how the shader output is written to the fog unit. */
- if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
- /* The gamma correction causes precision loss so we need
- * higher precision to maintain reasonable quality.
- * It has nothing to do with the colorbuffer format. */
- modifier |= R300_US_OUT_FMT_C4_10_GAMMA;
- } else if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
+ if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
if (desc->channel[0].size == 32) {
modifier |= R300_US_OUT_FMT_C4_32_FP;
} else {
return modifier | R300_C2_SEL_A;
case PIPE_FORMAT_I8_UNORM:
case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_L8_SRGB:
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8_SNORM:
return modifier | R300_C2_SEL_R;
- /* ARGB 32-bit outputs. */
+ /* BGRA outputs. */
case PIPE_FORMAT_B5G6R5_UNORM:
case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
case PIPE_FORMAT_B4G4R4A4_UNORM:
case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_SRGB:
case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_SRGB:
return modifier |
R300_C0_SEL_B | R300_C1_SEL_G |
R300_C2_SEL_R | R300_C3_SEL_A;
- /* BGRA 32-bit outputs. */
+ /* ARGB outputs. */
case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_SRGB:
case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_SRGB:
return modifier |
R300_C0_SEL_A | R300_C1_SEL_R |
R300_C2_SEL_G | R300_C3_SEL_B;
- /* RGBA 32-bit outputs. */
+ /* ABGR outputs. */
case PIPE_FORMAT_A8B8G8R8_UNORM:
- case PIPE_FORMAT_R8G8B8A8_SNORM:
- case PIPE_FORMAT_A8B8G8R8_SRGB:
case PIPE_FORMAT_X8B8G8R8_UNORM:
- case PIPE_FORMAT_X8B8G8R8_SRGB:
return modifier |
R300_C0_SEL_A | R300_C1_SEL_B |
R300_C2_SEL_G | R300_C3_SEL_R;
- /* ABGR 32-bit outputs. */
+ /* RGBA outputs. */
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
case PIPE_FORMAT_R10G10B10A2_UNORM:
- /* RGBA high precision outputs (same swizzles as ABGR low precision) */
case PIPE_FORMAT_R16G16B16A16_UNORM:
case PIPE_FORMAT_R16G16B16A16_SNORM:
//case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */
PIPE_FORMAT_DXT5_SRGBA = 109,
PIPE_FORMAT_A8B8G8R8_UNORM = 110,
+ PIPE_FORMAT_B5G5R5X1_UNORM = 111,
PIPE_FORMAT_COUNT
};
INCLUDE_DIRS = \
+ -I$(TOP)/include \
-I$(TOP)/src/mesa \
-I$(TOP)/src/gallium/include
#include "util/u_format.h"
#include "util/u_memory.h"
+#include "util/u_sampler.h"
#include "asm_filters.h"
const void *const_buffer;
VGint const_buffer_len;
VGTilingMode tiling_mode;
- struct pipe_texture *extra_texture;
+ struct pipe_sampler_view *extra_texture_view;
};
static INLINE struct pipe_texture *create_texture_1d(struct vg_context *ctx,
return tex;
}
+static INLINE struct pipe_sampler_view *create_texture_1d_view(struct vg_context *ctx,
+ const VGuint *color_data,
+ const VGint color_data_len)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_texture *texture;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *view;
+
+ texture = create_texture_1d(ctx, color_data, color_data_len);
+
+ if (!texture)
+ return NULL;
+
+ u_sampler_view_default_template(&view_templ, texture, texture->format);
+ view = pipe->create_sampler_view(pipe, texture, &view_templ);
+ /* want the texture to go away if the view is freed */
+ pipe_texture_reference(&texture, NULL);
+
+ return view;
+}
+
static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
struct pipe_framebuffer_state fb;
struct pipe_surface *dst_surf = pipe->screen->get_tex_surface(
- pipe->screen, dst->texture, 0, 0, 0,
+ pipe->screen, dst->sampler_view->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
/* drawing dest */
static void setup_samplers(struct vg_context *ctx, struct filter_info *info)
{
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
- struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
struct pipe_sampler_state sampler[3];
int num_samplers = 0;
int num_textures = 0;
samplers[1] = NULL;
samplers[2] = NULL;
samplers[3] = NULL;
- textures[0] = NULL;
- textures[1] = NULL;
- textures[2] = NULL;
- textures[3] = NULL;
+ sampler_views[0] = NULL;
+ sampler_views[1] = NULL;
+ sampler_views[2] = NULL;
+ sampler_views[3] = NULL;
memset(&sampler[0], 0, sizeof(struct pipe_sampler_state));
sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
}
samplers[0] = &sampler[0];
- textures[0] = info->src->texture;
+ sampler_views[0] = info->src->sampler_view;
++num_samplers;
++num_textures;
- if (info->extra_texture) {
+ if (info->extra_texture_view) {
memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state));
samplers[1] = &sampler[1];
- textures[1] = info->extra_texture;
+ sampler_views[1] = info->extra_texture_view;
++num_samplers;
++num_textures;
}
cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers);
- cso_set_sampler_textures(ctx->cso_context, num_textures, textures);
+ cso_set_fragment_sampler_views(ctx->cso_context, num_textures, sampler_views);
}
static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data)
cso_save_viewport(ctx->cso_context);
cso_save_blend(ctx->cso_context);
cso_save_samplers(ctx->cso_context);
- cso_save_sampler_textures(ctx->cso_context);
+ cso_save_fragment_sampler_views(ctx->cso_context);
dst_surf = setup_framebuffer(info->dst);
setup_viewport(info->dst);
setup_samplers(ctx, info);
renderer_draw_texture(ctx->renderer,
- info->src->texture,
+ info->src->sampler_view->texture,
info->dst->x, info->dst->y,
info->dst->x + info->dst->width,
info->dst->y + info->dst->height,
cso_restore_viewport(ctx->cso_context);
cso_restore_blend(ctx->cso_context);
cso_restore_samplers(ctx->cso_context);
- cso_restore_sampler_textures(ctx->cso_context);
+ cso_restore_fragment_sampler_views(ctx->cso_context);
vg_shader_destroy(ctx, shader);
info.const_buffer = matrix;
info.const_buffer_len = 20 * sizeof(VGfloat);
info.tiling_mode = VG_TILE_PAD;
- info.extra_texture = 0;
+ info.extra_texture_view = NULL;
execute_filter(ctx, &info);
}
info.const_buffer = buffer;
info.const_buffer_len = buffer_len * sizeof(VGfloat);
info.tiling_mode = tilingMode;
- info.extra_texture = 0;
+ info.extra_texture_view = NULL;
execute_filter(ctx, &info);
free(buffer);
info.const_buffer = buffer;
info.const_buffer_len = buffer_len * sizeof(VGfloat);
info.tiling_mode = tilingMode;
- info.extra_texture = 0;
+ info.extra_texture_view = NULL;
execute_filter(ctx, &info);
free(buffer);
struct vg_image *d, *s;
VGuint color_data[256];
VGint i;
- struct pipe_texture *lut_texture;
+ struct pipe_sampler_view *lut_texture_view;
VGfloat buffer[4];
struct filter_info info;
color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 |
redLUT[i] << 8 | alphaLUT[i];
}
- lut_texture = create_texture_1d(ctx, color_data, 255);
+ lut_texture_view = create_texture_1d_view(ctx, color_data, 255);
buffer[0] = 0.f;
buffer[1] = 0.f;
info.const_buffer = buffer;
info.const_buffer_len = 4 * sizeof(VGfloat);
info.tiling_mode = VG_TILE_PAD;
- info.extra_texture = lut_texture;
+ info.extra_texture_view = lut_texture_view;
execute_filter(ctx, &info);
- pipe_texture_reference(&lut_texture, NULL);
+ pipe_sampler_view_reference(&lut_texture_view, NULL);
}
void vgLookupSingle(VGImage dst, VGImage src,
{
struct vg_context *ctx = vg_current_context();
struct vg_image *d, *s;
- struct pipe_texture *lut_texture;
+ struct pipe_sampler_view *lut_texture_view;
VGfloat buffer[4];
struct filter_info info;
VGuint color_data[256];
color_data[i] = blue << 24 | green << 16 |
red << 8 | alpha;
}
- lut_texture = create_texture_1d(ctx, color_data, 256);
+ lut_texture_view = create_texture_1d_view(ctx, color_data, 256);
buffer[0] = 0.f;
buffer[1] = 0.f;
info.const_buffer = buffer;
info.const_buffer_len = 4 * sizeof(VGfloat);
info.tiling_mode = VG_TILE_PAD;
- info.extra_texture = lut_texture;
+ info.extra_texture_view = lut_texture_view;
execute_filter(ctx, &info);
- pipe_texture_reference(&lut_texture, NULL);
+ pipe_sampler_view_reference(&lut_texture_view, NULL);
}
#include "util/u_tile.h"
#include "util/u_memory.h"
#include "util/u_math.h"
+#include "util/u_sampler.h"
static enum pipe_format vg_format_to_pipe(VGImageFormat format)
{
static void vg_copy_texture(struct vg_context *ctx,
struct pipe_texture *dst, VGint dx, VGint dy,
- struct pipe_texture *src, VGint sx, VGint sy,
+ struct pipe_sampler_view *src, VGint sx, VGint sy,
VGint width, VGint height)
{
VGfloat dst_loc[4], src_loc[4];
src_loc[3] = height;
src_bounds[0] = 0.f;
src_bounds[1] = 0.f;
- src_bounds[2] = src->width0;
- src_bounds[3] = src->height0;
+ src_bounds[2] = src->texture->width0;
+ src_bounds[3] = src->texture->height0;
vg_bound_rect(src_loc, src_bounds, src_shift);
vg_bound_rect(dst_loc, dst_bounds, dst_shift);
static struct pipe_texture *image_texture(struct vg_image *img)
{
- struct pipe_texture *tex = img->texture;
+ struct pipe_texture *tex = img->sampler_view->texture;
return tex;
}
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe = ctx->pipe;
struct vg_image *image = CALLOC_STRUCT(vg_image);
enum pipe_format pformat = vg_format_to_pipe(format);
struct pipe_texture pt, *newtex;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *view;
struct pipe_screen *screen = ctx->pipe->screen;
vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
debug_assert(newtex);
- image->texture = newtex;
+ u_sampler_view_default_template(&view_templ, newtex, newtex->format);
+ view = pipe->create_sampler_view(pipe, newtex, &view_templ);
+ /* want the texture to go away if the view is freed */
+ pipe_texture_reference(&newtex, NULL);
+
+ image->sampler_view = view;
vg_context_add_object(ctx, VG_OBJECT_IMAGE, image);
array_destroy(img->children_array);
}
- pipe_texture_reference(&img->texture, NULL);
+ pipe_sampler_view_reference(&img->sampler_view, NULL);
free(img);
}
{
struct pipe_transfer *transfer =
pipe->get_tex_transfer(pipe,
- image->texture, 0, 0, 0,
+ image->sampler_view->texture, 0, 0, 0,
PIPE_TRANSFER_READ,
0, 0,
image->x + image->width,
image->width = width;
image->height = height;
image->parent = parent;
- image->texture = 0;
- pipe_texture_reference(&image->texture,
- parent->texture);
+ image->sampler_view = NULL;
+ pipe_sampler_view_reference(&image->sampler_view,
+ parent->sampler_view);
image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
}
/* make sure rendering has completed */
ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
- vg_copy_texture(ctx, dst->texture, dst->x + dx, dst->y + dy,
- src->texture, src->x + sx, src->y + sy, width, height);
+ vg_copy_texture(ctx, dst->sampler_view->texture, dst->x + dx, dst->y + dy,
+ src->sampler_view, src->x + sx, src->y + sy, width, height);
}
void image_draw(struct vg_image *img)
}
VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers,
- struct pipe_texture **textures)
+ struct pipe_sampler_view **sampler_views)
{
img->sampler.min_img_filter = image_sampler_filter(img->base.ctx);
img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx);
samplers[3] = &img->sampler;
- textures[3] = img->texture;
+ sampler_views[3] = img->sampler_view;
return 1;
}
struct vg_image *parent;
- struct pipe_texture *texture;
+ struct pipe_sampler_view *sampler_view;
struct pipe_sampler_state sampler;
struct array *children_array;
VGint width, VGint height);
VGint image_bind_samplers(struct vg_image *dst, struct pipe_sampler_state **samplers,
- struct pipe_texture **textures);
+ struct pipe_sampler_view **sampler_views);
VGboolean vg_image_overlaps(struct vg_image *dst,
struct vg_image *src);
VGint width;
VGint height;
- struct pipe_texture *texture;
+ struct pipe_sampler_view *sampler_view;
};
static INLINE struct pipe_surface *
struct pipe_screen *screen = ctx->pipe->screen;
struct st_framebuffer *stfb = ctx->draw_buffer;
return screen->get_tex_surface(screen,
- stfb->alpha_mask,
+ stfb->alpha_mask_view->texture,
0, 0, 0,
usage);
}
cso_set_fragment_shader_handle(ctx->cso_context, shader);
}
-static void setup_mask_samplers(struct pipe_texture *umask)
+static void setup_mask_samplers(struct pipe_sampler_view *umask)
{
struct vg_context *ctx = vg_current_context();
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
- struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
struct st_framebuffer *fb_buffers = ctx->draw_buffer;
- struct pipe_texture *uprev = NULL;
+ struct pipe_sampler_view *uprev = NULL;
struct pipe_sampler_state sampler;
- uprev = fb_buffers->blend_texture;
+ uprev = fb_buffers->blend_texture_view;
sampler = ctx->mask.sampler;
sampler.normalized_coords = 1;
samplers[0] = NULL;
samplers[1] = NULL;
- samplers[2] = NULL;
- textures[0] = NULL;
- textures[1] = NULL;
- textures[2] = NULL;
+ sampler_views[0] = NULL;
+ sampler_views[1] = NULL;
samplers[0] = &sampler;
samplers[1] = &ctx->mask.sampler;
- textures[0] = umask;
- textures[1] = uprev;
+ sampler_views[0] = umask;
+ sampler_views[1] = uprev;
cso_set_samplers(ctx->cso_context, 2,
(const struct pipe_sampler_state **)samplers);
- cso_set_sampler_textures(ctx->cso_context, 2, textures);
+ cso_set_fragment_sampler_views(ctx->cso_context, 2, sampler_views);
}
}
-static void mask_using_texture(struct pipe_texture *texture,
+static void mask_using_texture(struct pipe_sampler_view *sampler_view,
VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
+ struct pipe_texture *texture = sampler_view->texture;
struct pipe_surface *surface =
alpha_mask_surface(ctx, PIPE_BUFFER_USAGE_GPU_WRITE);
VGint offsets[4], loc[4];
vg_prepare_blend_surface_from_mask(ctx);
cso_save_samplers(ctx->cso_context);
- cso_save_sampler_textures(ctx->cso_context);
+ cso_save_fragment_sampler_views(ctx->cso_context);
cso_save_framebuffer(ctx->cso_context);
cso_save_blend(ctx->cso_context);
cso_save_fragment_shader(ctx->cso_context);
cso_save_viewport(ctx->cso_context);
- setup_mask_samplers(texture);
+ setup_mask_samplers(sampler_view);
setup_mask_blend();
setup_mask_operation(operation);
setup_mask_framebuffer(surface, surface->width, surface->height);
cso_restore_framebuffer(ctx->cso_context);
cso_restore_fragment_shader(ctx->cso_context);
cso_restore_samplers(ctx->cso_context);
- cso_restore_sampler_textures(ctx->cso_context);
+ cso_restore_fragment_sampler_views(ctx->cso_context);
cso_restore_viewport(ctx->cso_context);
pipe_surface_reference(&surface, NULL);
{
struct pipe_texture pt;
+ struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = ctx->pipe->screen;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *view = NULL;
+ struct pipe_texture *texture;
memset(&pt, 0, sizeof(pt));
pt.target = PIPE_TEXTURE_2D;
pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
pt.compressed = 0;
- mask->texture = screen->texture_create(screen, &pt);
+ texture = screen->texture_create(screen, &pt);
+
+ if (texture) {
+ u_sampler_view_default_template(&view_templ, texture, texture->format);
+ view = pipe->create_sampler_view(pipe, texture, &view_templ);
+ }
+ pipe_texture_reference(&texture, NULL);
+ mask->sampler_view = view;
}
vg_context_add_object(ctx, VG_OBJECT_MASK, mask);
alpha_color[3] = value;
surface = ctx->pipe->screen->get_tex_surface(
- ctx->pipe->screen, layer->texture,
+ ctx->pipe->screen, layer->sampler_view->texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
struct st_framebuffer *fb_buffers = ctx->draw_buffer;
renderer_copy_texture(ctx->renderer,
- layer->texture,
+ layer->sampler_view,
sx, sy,
sx + width, sy + height,
- fb_buffers->alpha_mask,
+ fb_buffers->alpha_mask_view->texture,
dx, dy,
dx + width, dy + height);
}
struct pipe_screen *screen = ctx->pipe->screen;
struct pipe_surface *surface;
- surface = screen->get_tex_surface(screen, layer->texture, 0, 0, 0,
+ surface = screen->get_tex_surface(screen, layer->sampler_view->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
cso_save_framebuffer(ctx->cso_context);
struct vg_mask_layer *temp_layer;
VGint width, height;
- width = fb_buffers->alpha_mask->width0;
- height = fb_buffers->alpha_mask->width0;
+ width = fb_buffers->alpha_mask_view->texture->width0;
+ height = fb_buffers->alpha_mask_view->texture->width0;
temp_layer = mask_layer_create(width, height);
VGint x, VGint y,
VGint width, VGint height)
{
- mask_using_texture(layer->texture, operation,
+ mask_using_texture(layer->sampler_view, operation,
x, y, width, height);
}
VGint x, VGint y,
VGint width, VGint height)
{
- mask_using_texture(image->texture, operation,
+ mask_using_texture(image->sampler_view, operation,
x, y, width, height);
}
}
VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
- struct pipe_texture **textures)
+ struct pipe_sampler_view **sampler_views)
{
struct vg_context *ctx = vg_current_context();
struct st_framebuffer *fb_buffers = ctx->draw_buffer;
samplers[1] = &ctx->mask.sampler;
- textures[1] = fb_buffers->alpha_mask;
+ sampler_views[1] = fb_buffers->alpha_mask_view;
return 1;
} else
return 0;
VGfloat value);
VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
- struct pipe_texture **textures);
+ struct pipe_sampler_view **sampler_views);
#endif
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_math.h"
+#include "util/u_sampler.h"
#include "cso_cache/cso_context.h"
VGfloat vals[5];
VGint valsi[5];
} radial;
- struct pipe_texture *texture;
+ struct pipe_sampler_view *sampler_view;
struct pipe_sampler_state sampler;
VGfloat *ramp_stops;
} gradient;
struct {
- struct pipe_texture *texture;
+ struct pipe_sampler_view *sampler_view;
VGTilingMode tiling_mode;
struct pipe_sampler_state sampler;
} pattern;
return tex;
}
+static INLINE struct pipe_sampler_view *create_gradient_sampler_view(struct vg_paint *p)
+{
+ struct pipe_context *pipe = p->base.ctx->pipe;
+ struct pipe_texture *texture;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *view;
+
+ texture = create_gradient_texture(p);
+
+ if (!texture)
+ return NULL;
+
+ u_sampler_view_default_template(&view_templ, texture, texture->format);
+ view = pipe->create_sampler_view(pipe, texture, &view_templ);
+ /* want the texture to go away if the view is freed */
+ pipe_texture_reference(&texture, NULL);
+
+ return view;
+}
+
struct vg_paint * paint_create(struct vg_context *ctx)
{
struct vg_paint *paint = CALLOC_STRUCT(vg_paint);
void paint_destroy(struct vg_paint *paint)
{
struct vg_context *ctx = paint->base.ctx;
- if (paint->pattern.texture)
- pipe_texture_reference(&paint->pattern.texture, NULL);
+ pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL);
+ if (paint->pattern.sampler_view)
+ pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL);
if (ctx)
vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint);
map[4] = 0.f;
map[5] = 1.f;
- map[6] = paint->pattern.texture->width0;
- map[7] = paint->pattern.texture->height0;
+ map[6] = paint->pattern.sampler_view->texture->width0;
+ map[7] = paint->pattern.sampler_view->texture->height0;
{
struct matrix mat;
memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix,
create_gradient_data(stops, num / 5, paint->gradient.color_data,
1024);
- if (paint->gradient.texture) {
- pipe_texture_reference(&paint->gradient.texture, NULL);
- paint->gradient.texture = 0;
+ if (paint->gradient.sampler_view) {
+ pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL);
+ paint->gradient.sampler_view = NULL;
}
- paint->gradient.texture = create_gradient_texture(paint);
+ paint->gradient.sampler_view = create_gradient_sampler_view(paint);
}
void paint_set_colori(struct vg_paint *p,
void paint_set_pattern(struct vg_paint *paint,
struct vg_image *img)
{
- if (paint->pattern.texture)
- pipe_texture_reference(&paint->pattern.texture, NULL);
+ if (paint->pattern.sampler_view)
+ pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL);
- paint->pattern.texture = 0;
- pipe_texture_reference(&paint->pattern.texture,
- img->texture);
+ paint->pattern.sampler_view = NULL;
+ pipe_sampler_view_reference(&paint->pattern.sampler_view,
+ img->sampler_view);
}
void paint_set_pattern_tiling(struct vg_paint *paint,
}
VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
- struct pipe_texture **textures)
+ struct pipe_sampler_view **sampler_views)
{
struct vg_context *ctx = vg_current_context();
switch(paint->type) {
case VG_PAINT_TYPE_LINEAR_GRADIENT:
case VG_PAINT_TYPE_RADIAL_GRADIENT: {
- if (paint->gradient.texture) {
+ if (paint->gradient.sampler_view) {
paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx);
paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx);
samplers[0] = &paint->gradient.sampler;
- textures[0] = paint->gradient.texture;
+ sampler_views[0] = paint->gradient.sampler_view;
return 1;
}
}
paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx);
paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx);
samplers[0] = &paint->pattern.sampler;
- textures[0] = paint->pattern.texture;
+ sampler_views[0] = paint->pattern.sampler_view;
return 1;
}
break;
void paint_resolve_type(struct vg_paint *paint)
{
if (paint->type == VG_PAINT_TYPE_PATTERN &&
- !paint->pattern.texture) {
+ !paint->pattern.sampler_view) {
paint->type = VG_PAINT_TYPE_COLOR;
}
}
VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
- struct pipe_texture **textures);
+ struct pipe_sampler_view **sampler_views);
VGint paint_constant_buffer_size(struct vg_paint *paint);
void paint_fill_constant_buffer(struct vg_paint *paint,
#include "util/u_simple_shaders.h"
#include "util/u_memory.h"
#include "util/u_rect.h"
+#include "util/u_sampler.h"
#include "cso_cache/cso_context.h"
}
void renderer_copy_texture(struct renderer *ctx,
- struct pipe_texture *src,
+ struct pipe_sampler_view *src,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
struct pipe_texture *dst,
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *tex = src->texture;
struct pipe_buffer *buf;
struct pipe_surface *dst_surf = screen->get_tex_surface(
screen, dst, 0, 0, 0,
struct pipe_framebuffer_state fb;
float s0, t0, s1, t1;
- assert(src->width0 != 0);
- assert(src->height0 != 0);
+ assert(tex->width0 != 0);
+ assert(tex->height0 != 0);
assert(dst->width0 != 0);
assert(dst->height0 != 0);
#endif
#if 1
- s0 = sx1 / src->width0;
- s1 = sx2 / src->width0;
- t0 = sy1 / src->height0;
- t1 = sy2 / src->height0;
+ s0 = sx1 / tex->width0;
+ s1 = sx2 / tex->width0;
+ t0 = sy1 / tex->height0;
+ t1 = sy2 / tex->height0;
#else
s0 = 0;
s1 = 1;
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_samplers(ctx->cso);
- cso_save_sampler_textures(ctx->cso);
+ cso_save_fragment_sampler_views(ctx->cso);
cso_save_framebuffer(ctx->cso);
cso_save_fragment_shader(ctx->cso);
cso_save_vertex_shader(ctx->cso);
vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
/* texture */
- cso_set_sampler_textures(ctx->cso, 1, &src);
+ cso_set_fragment_sampler_views(ctx->cso, 1, &src);
/* shaders */
cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
/* restore state we changed */
cso_restore_blend(ctx->cso);
cso_restore_samplers(ctx->cso);
- cso_restore_sampler_textures(ctx->cso);
+ cso_restore_fragment_sampler_views(ctx->cso);
cso_restore_framebuffer(ctx->cso);
cso_restore_vertex_shader(ctx->cso);
cso_restore_fragment_shader(ctx->cso);
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_buffer *buf;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *view;
struct pipe_texture texTemp, *tex;
struct pipe_surface *texSurf;
struct pipe_framebuffer_state fb;
if (!tex)
return;
+ u_sampler_view_default_template(&view_templ, tex, tex->format);
+ view = pipe->create_sampler_view(pipe, tex, &view_templ);
+
+ if (!view)
+ return;
+
texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_samplers(ctx->cso);
- cso_save_sampler_textures(ctx->cso);
+ cso_save_fragment_sampler_views(ctx->cso);
cso_save_framebuffer(ctx->cso);
cso_save_fragment_shader(ctx->cso);
cso_save_vertex_shader(ctx->cso);
}
/* texture */
- cso_set_sampler_textures(ctx->cso, 1, &tex);
+ cso_set_fragment_sampler_views(ctx->cso, 1, &view);
/* shaders */
cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
/* restore state we changed */
cso_restore_blend(ctx->cso);
cso_restore_samplers(ctx->cso);
- cso_restore_sampler_textures(ctx->cso);
+ cso_restore_fragment_sampler_views(ctx->cso);
cso_restore_framebuffer(ctx->cso);
cso_restore_fragment_shader(ctx->cso);
cso_restore_vertex_shader(ctx->cso);
cso_restore_viewport(ctx->cso);
pipe_texture_reference(&tex, NULL);
+ pipe_sampler_view_reference(&view, NULL);
}
void renderer_texture_quad(struct renderer *r,
struct vg_context;
struct pipe_texture;
+struct pipe_sampler_view;
struct pipe_surface;
struct renderer *renderer_create(struct vg_context *owner);
VGfloat x3, VGfloat y3,
VGfloat x4, VGfloat y4);
void renderer_copy_texture(struct renderer *r,
- struct pipe_texture *src,
+ struct pipe_sampler_view *src,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
struct pipe_texture *dst,
static VGint blend_bind_samplers(struct vg_context *ctx,
struct pipe_sampler_state **samplers,
- struct pipe_texture **textures)
+ struct pipe_sampler_view **sampler_views)
{
VGBlendMode bmode = ctx->state.vg.blend_mode;
vg_prepare_blend_surface(ctx);
samplers[2] = &ctx->blend_sampler;
- textures[2] = stfb->blend_texture;
+ sampler_views[2] = stfb->blend_texture_view;
- if (!samplers[0] || !textures[0]) {
+ if (!samplers[0] || !sampler_views[0]) {
samplers[0] = samplers[2];
- textures[0] = textures[2];
+ sampler_views[0] = sampler_views[2];
}
- if (!samplers[1] || !textures[1]) {
+ if (!samplers[1] || !sampler_views[1]) {
samplers[1] = samplers[0];
- textures[1] = textures[0];
+ sampler_views[1] = sampler_views[0];
}
return 1;
static void setup_samplers(struct shader *shader)
{
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
- struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
struct vg_context *ctx = shader->context;
/* a little wonky: we use the num as a boolean that just says
* whether any sampler/textures have been set. the actual numbering
samplers[1] = NULL;
samplers[2] = NULL;
samplers[3] = NULL;
- textures[0] = NULL;
- textures[1] = NULL;
- textures[2] = NULL;
- textures[3] = NULL;
-
- num += paint_bind_samplers(shader->paint, samplers, textures);
- num += mask_bind_samplers(samplers, textures);
- num += blend_bind_samplers(ctx, samplers, textures);
+ sampler_views[0] = NULL;
+ sampler_views[1] = NULL;
+ sampler_views[2] = NULL;
+ sampler_views[3] = NULL;
+
+ num += paint_bind_samplers(shader->paint, samplers, sampler_views);
+ num += mask_bind_samplers(samplers, sampler_views);
+ num += blend_bind_samplers(ctx, samplers, sampler_views);
if (shader->drawing_image && shader->image)
- num += image_bind_samplers(shader->image, samplers, textures);
+ num += image_bind_samplers(shader->image, samplers, sampler_views);
if (num) {
cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers);
- cso_set_sampler_textures(ctx->cso_context, 4, textures);
+ cso_set_fragment_sampler_views(ctx->cso_context, 4, sampler_views);
}
}
#include "util/u_simple_shaders.h"
#include "util/u_memory.h"
#include "util/u_blit.h"
+#include "util/u_sampler.h"
struct vg_context *_vg_context = 0;
{
struct pipe_surface *dest_surface = NULL;
struct pipe_context *pipe = ctx->pipe;
+ struct pipe_sampler_view *view;
+ struct pipe_sampler_view view_templ;
struct st_framebuffer *stfb = ctx->draw_buffer;
struct st_renderbuffer *strb = stfb->strb;
/* first finish all pending rendering */
vgFinish();
+ u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format);
+ view = pipe->create_sampler_view(pipe, strb->texture, &view_templ);
+
dest_surface = pipe->screen->get_tex_surface(pipe->screen,
- stfb->blend_texture,
+ stfb->blend_texture_view->texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
/* flip it, because we want to use it as a sampler */
util_blit_pixels_tex(ctx->blit,
- strb->texture,
+ view,
0, strb->height,
strb->width, 0,
dest_surface,
/* make sure it's complete */
vgFinish();
+
+ pipe_sampler_view_reference(&view, NULL);
}
vgFinish();
dest_surface = pipe->screen->get_tex_surface(pipe->screen,
- stfb->blend_texture,
+ stfb->blend_texture_view->texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
/* flip it, because we want to use it as a sampler */
util_blit_pixels_tex(ctx->blit,
- stfb->alpha_mask,
+ stfb->alpha_mask_view,
0, strb->height,
strb->width, 0,
dest_surface,
struct st_renderbuffer *strb;
struct st_renderbuffer *dsrb;
- struct pipe_texture *alpha_mask;
+ struct pipe_sampler_view *alpha_mask_view;
+
+ struct pipe_sampler_view *blend_texture_view;
- struct pipe_texture *blend_texture;
struct st_framebuffer_iface *iface;
enum st_attachment_type strb_att;
#include "util/u_inlines.h"
#include "pipe/p_screen.h"
#include "util/u_format.h"
+#include "util/u_sampler.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_rect.h"
static struct pipe_texture *
create_texture(struct pipe_context *pipe, enum pipe_format format,
- VGint width, VGint height)
+ VGint width, VGint height)
{
struct pipe_texture templ;
return pipe->screen->texture_create(pipe->screen, &templ);
}
+static struct pipe_sampler_view *
+create_tex_and_view(struct pipe_context *pipe, enum pipe_format format,
+ VGint width, VGint height)
+{
+ struct pipe_texture *texture;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *view;
+
+ texture = create_texture(pipe, format, width, height);
+
+ if (!texture)
+ return NULL;
+
+ u_sampler_view_default_template(&view_templ, texture, texture->format);
+ view = pipe->create_sampler_view(pipe, texture, &view_templ);
+ /* want the texture to go away if the view is freed */
+ pipe_texture_reference(&texture, NULL);
+
+ return view;
+}
+
/**
* Allocate a renderbuffer for a an on-screen window (not a user-created
* renderbuffer). The window system code determines the format.
surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
PIPE_BUFFER_USAGE_GPU_WRITE);
- strb->texture = create_texture(pipe, strb->format,
- width, height);
+ strb->texture = create_texture(pipe, strb->format, width, height);
+
if (!strb->texture)
return FALSE;
/*### currently we always allocate it but it's possible it's
not necessary if EGL_ALPHA_MASK_SIZE was 0
*/
- stfb->alpha_mask = 0;
+ stfb->alpha_mask_view = NULL;
stfb->width = width;
stfb->height = height;
uint width, uint height)
{
struct pipe_context *pipe = ctx->pipe;
- struct pipe_texture *old_texture = stfb->alpha_mask;
+ struct pipe_sampler_view *old_sampler_view = stfb->alpha_mask_view;
/*
we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
this texture and use it as a sampler, so while this wastes some
space it makes both of those a lot simpler
*/
- stfb->alpha_mask =
- create_texture(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
+ stfb->alpha_mask_view =
+ create_tex_and_view(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
- if (!stfb->alpha_mask) {
- if (old_texture)
- pipe_texture_reference(&old_texture, NULL);
+ if (!stfb->alpha_mask_view) {
+ if (old_sampler_view)
+ pipe_sampler_view_reference(&old_sampler_view, NULL);
return;
}
mask_fill(0, 0, width, height, 1.f);
/* if we had an old surface copy it over */
- if (old_texture) {
+ if (old_sampler_view) {
struct pipe_surface *surface = pipe->screen->get_tex_surface(
pipe->screen,
- stfb->alpha_mask,
+ stfb->alpha_mask_view->texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
struct pipe_surface *old_surface = pipe->screen->get_tex_surface(
pipe->screen,
- old_texture,
+ old_sampler_view->texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ);
if (pipe->surface_copy) {
/* Free the old texture
*/
- if (old_texture)
- pipe_texture_reference(&old_texture, NULL);
+ if (old_sampler_view)
+ pipe_sampler_view_reference(&old_sampler_view, NULL);
}
void st_resize_framebuffer(struct st_framebuffer *stfb,
setup_new_alpha_mask(ctx, stfb, width, height);
- pipe_texture_reference( &stfb->blend_texture, NULL );
- stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM,
- width, height);
+ pipe_sampler_view_reference( &stfb->blend_texture_view, NULL );
+ stfb->blend_texture_view = create_tex_and_view(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM,
+ width, height);
}
void st_set_framebuffer_surface(struct st_framebuffer *stfb,
boolean flinked;
uint32_t flink;
- boolean mapped;
struct radeon_drm_buffer *next, *prev;
};
{
struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
- if (buf->mapped) {
+ if (buf->bo->ptr != NULL) {
remove_from_list(buf);
radeon_bo_unmap(buf->bo);
- buf->mapped = false;
+ buf->bo->ptr = NULL;
}
radeon_bo_unref(buf->bo);
struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
int write;
- if (buf->mapped)
+ if (buf->bo->ptr != NULL)
return buf->bo->ptr;
if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
if (radeon_bo_map(buf->bo, write)) {
return NULL;
}
- buf->mapped = true;
insert_at_tail(&buf->mgr->buffer_map_list, buf);
return buf->bo->ptr;
}
retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
if (retval) {
- return false;
+ return FALSE;
}
buf->flinked = TRUE;
void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf, boolean microtiled, boolean macrotiled, uint32_t pitch)
{
struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
- uint32_t flags = 0;
-
+ uint32_t flags = 0, old_flags, old_pitch;
if (microtiled)
flags |= RADEON_BO_FLAGS_MICRO_TILE;
if (macrotiled)
flags |= RADEON_BO_FLAGS_MACRO_TILE;
+ radeon_bo_get_tiling(buf->bo, &old_flags, &old_pitch);
+
+ if (flags != old_flags || pitch != old_pitch) {
+ /* Tiling determines how DRM treats the buffer data.
+ * We must flush CS when changing it if the buffer is referenced. */
+ if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
+ buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
+ }
+ }
radeon_bo_set_tiling(buf->bo, flags, pitch);
}
struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo,
rd, wd);
- return true;
+ return TRUE;
}
void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
struct radeon_drm_buffer *rpb, *t_rpb;
foreach_s(rpb, t_rpb, &mgr->buffer_map_list) {
- rpb->mapped = 0;
radeon_bo_unmap(rpb->bo);
+ rpb->bo->ptr = NULL;
remove_from_list(rpb);
}
make_empty_list(&mgr->buffer_map_list);
-
-
}
struct gl_framebuffer *fb = driDrawPriv->driverPrivate;
struct gl_framebuffer *readFb = driReadPriv->driverPrivate;
- _mesa_make_current(&intel->ctx, fb, readFb);
intel->driReadDrawable = driReadPriv;
intel->driDrawable = driDrawPriv;
driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
intel_prepare_render(intel);
+ _mesa_make_current(&intel->ctx, fb, readFb);
}
else {
_mesa_make_current(NULL, NULL, NULL);
}
}
+static inline unsigned
+nvgl_texgen_mode(unsigned mode)
+{
+ switch (mode) {
+ case GL_EYE_LINEAR:
+ return 0x2400;
+ case GL_OBJECT_LINEAR:
+ return 0x2401;
+ case GL_SPHERE_MAP:
+ return 0x2402;
+ case GL_NORMAL_MAP:
+ return 0x8511;
+ case GL_REFLECTION_MAP:
+ return 0x8512;
+ default:
+ assert(0);
+ }
+}
+
#endif
*/
static inline unsigned
get_max_vertices(GLcontext *ctx, const struct _mesa_index_buffer *ib,
- unsigned n)
+ int n)
{
struct nouveau_render_state *render = to_render_state(ctx);
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
break;
+ case GL_TEXTURE_GEN_S:
+ case GL_TEXTURE_GEN_T:
+ case GL_TEXTURE_GEN_R:
+ case GL_TEXTURE_GEN_Q:
+ context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
+ context_dirty(ctx, MODELVIEW);
+ break;
}
}
nouveau_tex_gen(GLcontext *ctx, GLenum coord, GLenum pname,
const GLfloat *params)
{
- context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
+ context_dirty(ctx, MODELVIEW);
+ break;
+ default:
+ context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
+ break;
+ }
}
static void
static void
nouveau_update_state(GLcontext *ctx, GLbitfield new_state)
{
+ int i;
+
if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW))
context_dirty(ctx, PROJECTION);
if (new_state & _NEW_MODELVIEW)
context_dirty(ctx, MODELVIEW);
+ if (new_state & _NEW_TEXTURE_MATRIX) {
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
+ context_dirty_i(ctx, TEX_MAT, i);
+ }
+
if (new_state & _NEW_CURRENT_ATTRIB &&
new_state & _NEW_LIGHT) {
context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
NOUVEAU_STATE_TEX_GEN1,
NOUVEAU_STATE_TEX_GEN2,
NOUVEAU_STATE_TEX_GEN3,
+ NOUVEAU_STATE_TEX_MAT0,
+ NOUVEAU_STATE_TEX_MAT1,
+ NOUVEAU_STATE_TEX_MAT2,
+ NOUVEAU_STATE_TEX_MAT3,
NOUVEAU_STATE_TEX_OBJ0,
NOUVEAU_STATE_TEX_OBJ1,
NOUVEAU_STATE_TEX_OBJ2,
}
static GLboolean
-teximage_fits(struct gl_texture_object *t, int level,
- struct gl_texture_image *ti)
+teximage_fits(struct gl_texture_object *t, int level)
{
struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
+ struct gl_texture_image *ti = t->Image[0][level];
- return t->Target == GL_TEXTURE_RECTANGLE ||
- (s->bo && s->width == ti->Width &&
- s->height == ti->Height &&
- s->format == ti->TexFormat);
+ return ti && (t->Target == GL_TEXTURE_RECTANGLE ||
+ (s->bo && s->width == ti->Width &&
+ s->height == ti->Height &&
+ s->format == ti->TexFormat));
}
static GLboolean
{
struct gl_texture_image *ti = t->Image[0][level];
- if (ti && teximage_fits(t, level, ti)) {
+ if (teximage_fits(t, level)) {
struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
validate_teximage(ctx, t, i, 0, 0, 0,
s->width, s->height, 1);
}
+
+ FIRE_RING(context_chan(ctx));
}
return GL_TRUE;
void
nouveau_texture_reallocate(GLcontext *ctx, struct gl_texture_object *t)
{
- texture_dirty(t);
- relayout_texture(ctx, t);
- nouveau_texture_validate(ctx, t);
+ if (!teximage_fits(t, t->BaseLevel) ||
+ !teximage_fits(t, get_last_level(t))) {
+ texture_dirty(t);
+ relayout_texture(ctx, t);
+ nouveau_texture_validate(ctx, t);
+ }
}
static unsigned
}
if (level == t->BaseLevel) {
- if (!teximage_fits(t, level, ti))
+ if (!teximage_fits(t, level))
relayout_texture(ctx, t);
nouveau_texture_validate(ctx, t);
}
return s == GL_TEXTURE || (s >= GL_TEXTURE0 && s <= GL_TEXTURE31);
}
+static inline struct gl_texgen *
+get_texgen_coord(struct gl_texture_unit *u, int i)
+{
+ return ((struct gl_texgen *[])
+ { &u->GenS, &u->GenT, &u->GenR, &u->GenQ }) [i];
+}
+
+static inline float *
+get_texgen_coeff(struct gl_texgen *c)
+{
+ if (c->Mode == GL_OBJECT_LINEAR)
+ return c->ObjectPlane;
+ else if (c->Mode == GL_EYE_LINEAR)
+ return c->EyePlane;
+ else
+ return NULL;
+}
+
#endif
if (ctx->Fog.Enabled && ctx->Fog.FogCoordinateSource == GL_FOG_COORD)
vbo_emit_attr(ctx, arrays, VERT_ATTRIB_FOG);
- if (ctx->Light.Enabled) {
+ if (ctx->Light.Enabled ||
+ (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))
vbo_emit_attr(ctx, arrays, VERT_ATTRIB_NORMAL);
+ if (ctx->Light.Enabled) {
vbo_emit_attr(ctx, arrays, MAT(FRONT_AMBIENT));
vbo_emit_attr(ctx, arrays, MAT(FRONT_DIFFUSE));
vbo_emit_attr(ctx, arrays, MAT(FRONT_SPECULAR));
}
static unsigned
-get_max_client_stride(GLcontext *ctx)
+get_max_client_stride(GLcontext *ctx, const struct gl_client_array **arrays)
{
struct nouveau_render_state *render = to_render_state(ctx);
int i, s = 0;
for (i = 0; i < render->attr_count; i++) {
int attr = render->map[i];
- struct nouveau_array_state *a = &render->attrs[attr];
- if (attr >= 0 && !a->bo)
- s = MAX2(a->stride, s);
+ if (attr >= 0) {
+ const struct gl_client_array *a = arrays[attr];
+
+ if (!_mesa_is_bufferobj(a->BufferObj))
+ s = MAX2(a->StrideB, s);
+ }
}
return s;
{
struct nouveau_context *nctx = to_nouveau_context(ctx);
struct nouveau_render_state *render = to_render_state(ctx);
- unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * nctx->bo.count,
+ unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * (nctx->bo.count +
+ render->attr_count),
vert_avail = get_max_vertices(ctx, NULL, pushbuf_avail),
idx_avail = get_max_vertices(ctx, ib, pushbuf_avail);
int stride;
/* Try to keep client buffers smaller than the scratch BOs. */
if (render->mode == VBO &&
- (stride = get_max_client_stride(ctx)))
+ (stride = get_max_client_stride(ctx, arrays)))
vert_avail = MIN2(vert_avail,
RENDER_SCRATCH_SIZE / stride);
dispatch(ctx, start, delta, count);
BATCH_END();
}
-
- FIRE_RING(chan);
}
/* Immediate rendering path. */
BATCH_END();
}
-
- FIRE_RING(chan);
}
/* draw_prims entry point when we're doing hw-tnl. */
nouveau_emit_nothing,
nouveau_emit_nothing,
nouveau_emit_nothing,
+ nouveau_emit_nothing,
+ nouveau_emit_nothing,
+ nouveau_emit_nothing,
+ nouveau_emit_nothing,
nv04_emit_tex_obj,
nv04_emit_tex_obj,
nouveau_emit_nothing,
OUT_RING(chan, 0);
BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1);
OUT_RING(chan, 0);
- BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_S(0), 8);
+ BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_MODE_S(0), 8);
for (i = 0; i < 8; i++)
OUT_RING(chan, 0);
nv10_emit_tex_gen,
nouveau_emit_nothing,
nouveau_emit_nothing,
+ nv10_emit_tex_mat,
+ nv10_emit_tex_mat,
+ nouveau_emit_nothing,
+ nouveau_emit_nothing,
nv10_emit_tex_obj,
nv10_emit_tex_obj,
nouveau_emit_nothing,
void
nv10_emit_tex_gen(GLcontext *ctx, int emit);
+void
+nv10_emit_tex_mat(GLcontext *ctx, int emit);
+
void
nv10_emit_tex_obj(GLcontext *ctx, int emit);
nouveau_bo_markl(bctx, celsius, NV17TCL_LMA_DEPTH_BUFFER_OFFSET,
nfb->lma_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ WAIT_RING(chan, 9);
BEGIN_RING(chan, celsius, NV17TCL_LMA_DEPTH_WINDOW_X, 4);
OUT_RINGf(chan, - 1792);
OUT_RINGf(chan, - 2304 + fb->Height);
#include "nouveau_util.h"
#include "nv10_driver.h"
+#define TX_GEN_MODE(i, j) (NV10TCL_TX_GEN_MODE_S(i) + 4 * (j))
+#define TX_GEN_COEFF(i, j) (NV10TCL_TX_GEN_COEFF_S_A(i) + 16 * (j))
+#define TX_MATRIX(i) (NV10TCL_TX0_MATRIX(0) + 64 * (i))
+
void
nv10_emit_tex_gen(GLcontext *ctx, int emit)
{
+ const int i = emit - NOUVEAU_STATE_TEX_GEN0;
+ struct nouveau_context *nctx = to_nouveau_context(ctx);
+ struct nouveau_channel *chan = context_chan(ctx);
+ struct nouveau_grobj *celsius = context_eng3d(ctx);
+ struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
+ int j;
+
+ for (j = 0; j < 4; j++) {
+ if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) {
+ struct gl_texgen *coord = get_texgen_coord(unit, j);
+ float *k = get_texgen_coeff(coord);
+
+ if (k) {
+ BEGIN_RING(chan, celsius,
+ TX_GEN_COEFF(i, j), 4);
+ OUT_RINGf(chan, k[0]);
+ OUT_RINGf(chan, k[1]);
+ OUT_RINGf(chan, k[2]);
+ OUT_RINGf(chan, k[3]);
+ }
+
+ BEGIN_RING(chan, celsius, TX_GEN_MODE(i, j), 1);
+ OUT_RING(chan, nvgl_texgen_mode(coord->Mode));
+
+ } else {
+ BEGIN_RING(chan, celsius, TX_GEN_MODE(i, j), 1);
+ OUT_RING(chan, 0);
+ }
+ }
+
+ context_dirty_i(ctx, TEX_MAT, i);
+}
+
+void
+nv10_emit_tex_mat(GLcontext *ctx, int emit)
+{
+ const int i = emit - NOUVEAU_STATE_TEX_MAT0;
+ struct nouveau_context *nctx = to_nouveau_context(ctx);
+ struct nouveau_channel *chan = context_chan(ctx);
+ struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+ if (nctx->fallback == HWTNL &&
+ ((ctx->Texture._TexMatEnabled & 1 << i) ||
+ ctx->Texture.Unit[i]._GenFlags)) {
+ BEGIN_RING(chan, celsius, NV10TCL_TX_MATRIX_ENABLE(i), 1);
+ OUT_RING(chan, 1);
+
+ BEGIN_RING(chan, celsius, TX_MATRIX(i), 16);
+ OUT_RINGm(chan, ctx->TextureMatrixStack[i].Top->m);
+
+ } else {
+ BEGIN_RING(chan, celsius, NV10TCL_TX_MATRIX_ENABLE(i), 1);
+ OUT_RING(chan, 0);
+ }
}
static uint32_t
if (nctx->fallback != HWTNL)
return;
- if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled) {
+ if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled ||
+ (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) {
BEGIN_RING(chan, celsius, NV10TCL_MODELVIEW0_MATRIX(0), 16);
OUT_RINGm(chan, m->m);
}
- if (ctx->Light.Enabled) {
+ if (ctx->Light.Enabled ||
+ (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) {
int i, j;
BEGIN_RING(chan, celsius,
BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_STIPPLE_ENABLE, 1);
OUT_RING (chan, 0);
- BEGIN_RING(chan, kelvin, NV20TCL_TX_GEN_S(0),
- 4 * NV20TCL_TX_GEN_S__SIZE);
- for (i=0; i < 4 * NV20TCL_TX_GEN_S__SIZE; i++)
+ BEGIN_RING(chan, kelvin, NV20TCL_TX_GEN_MODE_S(0),
+ 4 * NV20TCL_TX_GEN_MODE_S__SIZE);
+ for (i=0; i < 4 * NV20TCL_TX_GEN_MODE_S__SIZE; i++)
OUT_RING(chan, 0);
BEGIN_RING(chan, kelvin, NV20TCL_FOG_EQUATION_CONSTANT, 3);
nv20_emit_tex_env,
nv20_emit_tex_env,
nv20_emit_tex_env,
- nv10_emit_tex_gen,
- nv10_emit_tex_gen,
- nv10_emit_tex_gen,
- nv10_emit_tex_gen,
+ nv20_emit_tex_gen,
+ nv20_emit_tex_gen,
+ nv20_emit_tex_gen,
+ nv20_emit_tex_gen,
+ nv20_emit_tex_mat,
+ nv20_emit_tex_mat,
+ nv20_emit_tex_mat,
+ nv20_emit_tex_mat,
nv20_emit_tex_obj,
nv20_emit_tex_obj,
nv20_emit_tex_obj,
nv20_emit_frag(GLcontext *ctx, int emit);
/* nv20_state_tex.c */
+void
+nv20_emit_tex_gen(GLcontext *ctx, int emit);
+
+void
+nv20_emit_tex_mat(GLcontext *ctx, int emit);
+
void
nv20_emit_tex_obj(GLcontext *ctx, int emit);
#include "nouveau_util.h"
#include "nv20_driver.h"
+#define TX_GEN_MODE(i, j) (NV20TCL_TX_GEN_MODE_S(i) + 4 * (j))
+#define TX_GEN_COEFF(i, j) (NV20TCL_TX_GEN_COEFF_S_A(i) + 16 * (j))
+#define TX_MATRIX(i) (NV20TCL_TX0_MATRIX(0) + 64 * (i))
+
+void
+nv20_emit_tex_gen(GLcontext *ctx, int emit)
+{
+ const int i = emit - NOUVEAU_STATE_TEX_GEN0;
+ struct nouveau_context *nctx = to_nouveau_context(ctx);
+ struct nouveau_channel *chan = context_chan(ctx);
+ struct nouveau_grobj *kelvin = context_eng3d(ctx);
+ struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
+ int j;
+
+ for (j = 0; j < 4; j++) {
+ if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) {
+ struct gl_texgen *coord = get_texgen_coord(unit, j);
+ float *k = get_texgen_coeff(coord);
+
+ if (k) {
+ BEGIN_RING(chan, kelvin, TX_GEN_COEFF(i, j), 4);
+ OUT_RINGf(chan, k[0]);
+ OUT_RINGf(chan, k[1]);
+ OUT_RINGf(chan, k[2]);
+ OUT_RINGf(chan, k[3]);
+ }
+
+ BEGIN_RING(chan, kelvin, TX_GEN_MODE(i, j), 1);
+ OUT_RING(chan, nvgl_texgen_mode(coord->Mode));
+
+ } else {
+ BEGIN_RING(chan, kelvin, TX_GEN_MODE(i, j), 1);
+ OUT_RING(chan, 0);
+ }
+ }
+}
+
+void
+nv20_emit_tex_mat(GLcontext *ctx, int emit)
+{
+ const int i = emit - NOUVEAU_STATE_TEX_MAT0;
+ struct nouveau_context *nctx = to_nouveau_context(ctx);
+ struct nouveau_channel *chan = context_chan(ctx);
+ struct nouveau_grobj *kelvin = context_eng3d(ctx);
+
+ if (nctx->fallback == HWTNL &&
+ (ctx->Texture._TexMatEnabled & 1 << i)) {
+ BEGIN_RING(chan, kelvin, NV20TCL_TX_MATRIX_ENABLE(i), 1);
+ OUT_RING(chan, 1);
+
+ BEGIN_RING(chan, kelvin, TX_MATRIX(i), 16);
+ OUT_RINGm(chan, ctx->TextureMatrixStack[i].Top->m);
+
+ } else {
+ BEGIN_RING(chan, kelvin, NV20TCL_TX_MATRIX_ENABLE(i), 1);
+ OUT_RING(chan, 0);
+ }
+}
+
static uint32_t
get_tex_format_pot(struct gl_texture_image *ti)
{
if (nctx->fallback != HWTNL)
return;
- if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled) {
+ if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled ||
+ (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) {
BEGIN_RING(chan, kelvin, NV20TCL_MODELVIEW0_MATRIX(0), 16);
OUT_RINGm(chan, m->m);
}
- if (ctx->Light.Enabled) {
+ if (ctx->Light.Enabled ||
+ (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) {
int i, j;
BEGIN_RING(chan, kelvin,
if (compiler->Base.Error)
return;
- assert(code->inst_end >= 0);
-
- if ((code->inst[code->inst_end].inst0 & R500_INST_TYPE_MASK) != R500_INST_TYPE_OUT) {
+ if (code->inst_end == -1 ||
+ (code->inst[code->inst_end].inst0 & R500_INST_TYPE_MASK) != R500_INST_TYPE_OUT) {
/* This may happen when dead-code elimination is disabled or
* when most of the fragment program logic is leading to a KIL */
if (code->inst_end >= 511) {
#include "glheader.h"
+#include "enums.h"
#include "hash.h"
#include "imports.h"
#include "image.h"
bufObj = get_buffer(ctx, target);
if (!bufObj) {
- _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" );
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)" );
return;
}
if (!_mesa_is_bufferobj(bufObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" );
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameterivARB" );
return;
}
switch (pname) {
case GL_BUFFER_SIZE_ARB:
*params = (GLint) bufObj->Size;
- break;
+ return;
case GL_BUFFER_USAGE_ARB:
*params = bufObj->Usage;
- break;
+ return;
case GL_BUFFER_ACCESS_ARB:
*params = simplified_access_mode(bufObj->AccessFlags);
- break;
+ return;
case GL_BUFFER_MAPPED_ARB:
*params = _mesa_bufferobj_mapped(bufObj);
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)");
return;
+ case GL_BUFFER_ACCESS_FLAGS:
+ if (ctx->VersionMajor < 3)
+ goto invalid_pname;
+ *params = bufObj->AccessFlags;
+ return;
+ case GL_BUFFER_MAP_OFFSET:
+ if (ctx->VersionMajor < 3)
+ goto invalid_pname;
+ *params = (GLint) bufObj->Offset;
+ return;
+ case GL_BUFFER_MAP_LENGTH:
+ if (ctx->VersionMajor < 3)
+ goto invalid_pname;
+ *params = (GLint) bufObj->Length;
+ return;
+ default:
+ ; /* fall-through */
}
+
+invalid_pname:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)",
+ _mesa_lookup_enum_by_nr(pname));
}
bufObj = get_buffer(ctx, target);
if (!bufObj) {
- _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameteri64v(target)" );
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(target)" );
return;
}
if (!_mesa_is_bufferobj(bufObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameteri64v" );
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameteri64v" );
return;
}
switch (pname) {
case GL_BUFFER_SIZE_ARB:
*params = bufObj->Size;
- break;
+ return;
case GL_BUFFER_USAGE_ARB:
*params = bufObj->Usage;
- break;
+ return;
case GL_BUFFER_ACCESS_ARB:
*params = simplified_access_mode(bufObj->AccessFlags);
- break;
+ return;
+ case GL_BUFFER_ACCESS_FLAGS:
+ if (ctx->VersionMajor < 3)
+ goto invalid_pname;
+ *params = bufObj->AccessFlags;
+ return;
case GL_BUFFER_MAPPED_ARB:
*params = _mesa_bufferobj_mapped(bufObj);
- break;
+ return;
+ case GL_BUFFER_MAP_OFFSET:
+ if (ctx->VersionMajor < 3)
+ goto invalid_pname;
+ *params = bufObj->Offset;
+ return;
+ case GL_BUFFER_MAP_LENGTH:
+ if (ctx->VersionMajor < 3)
+ goto invalid_pname;
+ *params = bufObj->Length;
+ return;
default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname)");
+ ; /* fall-through */
return;
}
+
+invalid_pname:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)",
+ _mesa_lookup_enum_by_nr(pname));
}
return &fb->Attachment[BUFFER_COLOR0 + i];
case GL_DEPTH_STENCIL_ATTACHMENT:
/* fall-through */
+ case GL_DEPTH_BUFFER:
+ /* fall-through / new in GL 3.0 */
case GL_DEPTH_ATTACHMENT_EXT:
return &fb->Attachment[BUFFER_DEPTH];
+ case GL_STENCIL_BUFFER:
+ /* fall-through / new in GL 3.0 */
case GL_STENCIL_ATTACHMENT_EXT:
return &fb->Attachment[BUFFER_STENCIL];
default:
CHECK_EXT1(MESA_texture_array, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name);
break;
+ case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxArrayTextureLayers);
+ break;
case GL_TEXTURE_GEN_S:
params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0);
break;
case GL_MINOR_VERSION:
params[0] = INT_TO_BOOLEAN(ctx->VersionMinor);
break;
+ case GL_CONTEXT_FLAGS:
+ params[0] = INT_TO_BOOLEAN(ctx->Const.ContextFlags);
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanv(pname=0x%x)", pname);
}
CHECK_EXT1(MESA_texture_array, "GetFloatv");
params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name);
break;
+ case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxArrayTextureLayers);
+ break;
case GL_TEXTURE_GEN_S:
params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
break;
case GL_MINOR_VERSION:
params[0] = (GLfloat)(ctx->VersionMinor);
break;
+ case GL_CONTEXT_FLAGS:
+ params[0] = (GLfloat)(ctx->Const.ContextFlags);
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetFloatv(pname=0x%x)", pname);
}
CHECK_EXT1(MESA_texture_array, "GetIntegerv");
params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name;
break;
+ case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetIntegerv");
+ params[0] = ctx->Const.MaxArrayTextureLayers;
+ break;
case GL_TEXTURE_GEN_S:
params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
break;
case GL_MINOR_VERSION:
params[0] = ctx->VersionMinor;
break;
+ case GL_CONTEXT_FLAGS:
+ params[0] = ctx->Const.ContextFlags;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerv(pname=0x%x)", pname);
}
CHECK_EXT1(MESA_texture_array, "GetInteger64v");
params[0] = (GLint64)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name);
break;
+ case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = (GLint64)(ctx->Const.MaxArrayTextureLayers);
+ break;
case GL_TEXTURE_GEN_S:
params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
break;
case GL_MINOR_VERSION:
params[0] = (GLint64)(ctx->VersionMinor);
break;
+ case GL_CONTEXT_FLAGS:
+ params[0] = (GLint64)(ctx->Const.ContextFlags);
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetInteger64v(pname=0x%x)", pname);
}
["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name"], "", ["MESA_texture_array"] ),
( "GL_TEXTURE_BINDING_2D_ARRAY_EXT", GLint,
["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name"], "", ["MESA_texture_array"] ),
+ ( "GL_MAX_ARRAY_TEXTURE_LAYERS_EXT", GLint,
+ ["ctx->Const.MaxArrayTextureLayers"], "", ["MESA_texture_array"] ),
( "GL_TEXTURE_GEN_S", GLboolean,
["((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)"], "", None ),
( "GL_TEXTURE_GEN_T", GLboolean,
# GL3
( "GL_NUM_EXTENSIONS", GLint, ["_mesa_get_extension_count(ctx)"], "", None ),
( "GL_MAJOR_VERSION", GLint, ["ctx->VersionMajor"], "", None ),
- ( "GL_MINOR_VERSION", GLint, ["ctx->VersionMinor"], "", None )
+ ( "GL_MINOR_VERSION", GLint, ["ctx->VersionMinor"], "", None ),
+ ( "GL_CONTEXT_FLAGS", GLint, ["ctx->Const.ContextFlags"], "", None )
]
/**< GL_EXT_provoking_vertex */
GLboolean QuadsFollowProvokingVertexConvention;
+
+ /**< OpenGL version 3.x */
+ GLbitfield ContextFlags; /**< Ex: GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT */
};
"glGetTexLevelParameter[if]v(pname)");
}
break;
+ case GL_TEXTURE_SHARED_SIZE:
+ if (ctx->VersionMajor >= 3) {
+ /* XXX return number of exponent bits for shared exponent texture
+ * formats, like GL_RGB9_E5.
+ */
+ *params = 0;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
/* GL_ARB_texture_compression */
case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: