*/
-#include "pipe/p_util.h"
#include "pipe/p_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
-#include "tgsi/util/tgsi_transform.h"
-#include "tgsi/util/tgsi_dump.h"
+#include "tgsi/tgsi_transform.h"
+#include "tgsi/tgsi_dump.h"
#include "draw_context.h"
#include "draw_private.h"
+#include "draw_pipe.h"
/**
/** For AA lines, this is the vertex attrib slot for the new texcoords */
uint tex_slot;
+ /** position, not necessarily output zero */
+ uint pos_slot;
void *sampler_cso;
struct pipe_texture *texture;
if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR &&
decl->Semantic.SemanticIndex == 0) {
- aactx->colorOutput = decl->u.DeclarationRange.First;
+ aactx->colorOutput = decl->DeclarationRange.First;
}
else if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
uint i;
- for (i = decl->u.DeclarationRange.First;
- i <= decl->u.DeclarationRange.Last; i++) {
+ for (i = decl->DeclarationRange.First;
+ i <= decl->DeclarationRange.Last; i++) {
aactx->samplersUsed |= 1 << i;
}
}
else if (decl->Declaration.File == TGSI_FILE_INPUT) {
- if ((int) decl->u.DeclarationRange.Last > aactx->maxInput)
- aactx->maxInput = decl->u.DeclarationRange.Last;
+ if ((int) decl->DeclarationRange.Last > aactx->maxInput)
+ aactx->maxInput = decl->DeclarationRange.Last;
if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC &&
(int) decl->Semantic.SemanticIndex > aactx->maxGeneric) {
aactx->maxGeneric = decl->Semantic.SemanticIndex;
}
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
uint i;
- for (i = decl->u.DeclarationRange.First;
- i <= decl->u.DeclarationRange.Last; i++) {
+ for (i = decl->DeclarationRange.First;
+ i <= decl->DeclarationRange.Last; i++) {
aactx->tempsUsed |= (1 << i);
}
}
/* declare new generic input/texcoord */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
+ /* XXX this could be linear... */
+ decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
decl.Semantic.SemanticIndex = aactx->maxGeneric + 1;
- decl.Declaration.Interpolate = 1;
- /* XXX this could be linear... */
- decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
- decl.u.DeclarationRange.First =
- decl.u.DeclarationRange.Last = aactx->maxInput + 1;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->maxInput + 1;
ctx->emit_declaration(ctx, &decl);
/* declare new sampler */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
- decl.u.DeclarationRange.First =
- decl.u.DeclarationRange.Last = aactx->freeSampler;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->freeSampler;
ctx->emit_declaration(ctx, &decl);
/* declare new temp regs */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
- decl.u.DeclarationRange.First =
- decl.u.DeclarationRange.Last = aactx->texTemp;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->texTemp;
ctx->emit_declaration(ctx, &decl);
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
- decl.u.DeclarationRange.First =
- decl.u.DeclarationRange.Last = aactx->colorTemp;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->colorTemp;
ctx->emit_declaration(ctx, &decl);
aactx->firstInstruction = FALSE;
* Generate the frag shader we'll use for drawing AA lines.
* This will be the user's shader plus some texture/modulate instructions.
*/
-static void
+static boolean
generate_aaline_fs(struct aaline_stage *aaline)
{
const struct pipe_shader_state *orig_fs = &aaline->fs->state;
- //struct draw_context *draw = aaline->stage.draw;
struct pipe_shader_state aaline_fs;
struct aa_transform_context transform;
aaline_fs = *orig_fs; /* copy to init */
aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
+ if (aaline_fs.tokens == NULL)
+ return FALSE;
memset(&transform, 0, sizeof(transform));
transform.colorOutput = -1;
aaline->fs->aaline_fs
= aaline->driver_create_fs_state(aaline->pipe, &aaline_fs);
+ if (aaline->fs->aaline_fs == NULL)
+ return FALSE;
aaline->fs->generic_attrib = transform.maxGeneric + 1;
+ return TRUE;
}
/**
* Create the texture map we'll use for antialiasing the lines.
*/
-static void
+static boolean
aaline_create_texture(struct aaline_stage *aaline)
{
struct pipe_context *pipe = aaline->pipe;
memset(&texTemp, 0, sizeof(texTemp));
texTemp.target = PIPE_TEXTURE_2D;
- texTemp.format = PIPE_FORMAT_U_A8; /* XXX verify supported by driver! */
+ texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
texTemp.last_level = MAX_TEXTURE_LEVEL;
texTemp.width[0] = 1 << MAX_TEXTURE_LEVEL;
texTemp.height[0] = 1 << MAX_TEXTURE_LEVEL;
texTemp.depth[0] = 1;
- texTemp.cpp = 1;
+ pf_get_block(texTemp.format, &texTemp.block);
aaline->texture = screen->texture_create(screen, &texTemp);
+ if (!aaline->texture)
+ return FALSE;
/* Fill in mipmap images.
* Basically each level is solid opaque, except for the outermost
assert(aaline->texture->width[level] == aaline->texture->height[level]);
- surface = screen->get_tex_surface(screen, aaline->texture, 0, level, 0);
- data = pipe_surface_map(surface);
+ /* This texture is new, no need to flush.
+ */
+ surface = screen->get_tex_surface(screen, aaline->texture, 0, level, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ data = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE);
+ if (data == NULL)
+ return FALSE;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
else {
d = 255;
}
- data[i * surface->pitch + j] = d;
+ data[i * surface->stride + j] = d;
}
}
/* unmap */
- pipe_surface_unmap(surface);
- pipe_surface_reference(&surface, NULL);
- pipe->texture_update(pipe, aaline->texture, 0, (1 << level));
+ screen->surface_unmap(screen, surface);
+ screen->tex_surface_release(screen, &surface);
}
+ return TRUE;
}
* By using a mipmapped texture, we don't have to generate a different
* texture image for each line size.
*/
-static void
+static boolean
aaline_create_sampler(struct aaline_stage *aaline)
{
struct pipe_sampler_state sampler;
sampler.max_lod = MAX_TEXTURE_LEVEL;
aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
+ if (aaline->sampler_cso == NULL)
+ return FALSE;
+
+ return TRUE;
}
* When we're about to draw our first AA line in a batch, this function is
* called to tell the driver to bind our modified fragment shader.
*/
-static void
+static boolean
bind_aaline_fragment_shader(struct aaline_stage *aaline)
{
- if (!aaline->fs->aaline_fs) {
- generate_aaline_fs(aaline);
- }
+ struct draw_context *draw = aaline->stage.draw;
+
+ if (!aaline->fs->aaline_fs &&
+ !generate_aaline_fs(aaline))
+ return FALSE;
+
+ draw->suspend_flushing = TRUE;
aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs);
+ draw->suspend_flushing = FALSE;
+
+ return TRUE;
}
}
-static void
-passthrough_point(struct draw_stage *stage, struct prim_header *header)
-{
- stage->next->point(stage->next, header);
-}
-
-
-static void
-passthrough_tri(struct draw_stage *stage, struct prim_header *header)
-{
- stage->next->tri(stage->next, header);
-}
-
-
/**
* Draw a wide line by drawing a quad, using geometry which will
* fullfill GL's antialiased line requirements.
struct prim_header tri;
struct vertex_header *v[8];
uint texPos = aaline->tex_slot;
+ uint posPos = aaline->pos_slot;
float *pos, *tex;
- float dx = header->v[1]->data[0][0] - header->v[0]->data[0][0];
- float dy = header->v[1]->data[0][1] - header->v[0]->data[0][1];
+ float dx = header->v[1]->data[posPos][0] - header->v[0]->data[posPos][0];
+ float dy = header->v[1]->data[posPos][1] - header->v[0]->data[posPos][1];
double a = atan2(dy, dx);
float c_a = (float) cos(a), s_a = (float) sin(a);
uint i;
*/
/* new verts */
- pos = v[0]->data[0];
+ pos = v[0]->data[posPos];
pos[0] += (-dx * c_a - dy * s_a);
pos[1] += (-dx * s_a + dy * c_a);
- pos = v[1]->data[0];
+ pos = v[1]->data[posPos];
pos[0] += (-dx * c_a - -dy * s_a);
pos[1] += (-dx * s_a + -dy * c_a);
- pos = v[2]->data[0];
+ pos = v[2]->data[posPos];
pos[0] += ( dx * c_a - dy * s_a);
pos[1] += ( dx * s_a + dy * c_a);
- pos = v[3]->data[0];
+ pos = v[3]->data[posPos];
pos[0] += ( dx * c_a - -dy * s_a);
pos[1] += ( dx * s_a + -dy * c_a);
- pos = v[4]->data[0];
+ pos = v[4]->data[posPos];
pos[0] += (-dx * c_a - dy * s_a);
pos[1] += (-dx * s_a + dy * c_a);
- pos = v[5]->data[0];
+ pos = v[5]->data[posPos];
pos[0] += (-dx * c_a - -dy * s_a);
pos[1] += (-dx * s_a + -dy * c_a);
- pos = v[6]->data[0];
+ pos = v[6]->data[posPos];
pos[0] += ( dx * c_a - dy * s_a);
pos[1] += ( dx * s_a + dy * c_a);
- pos = v[7]->data[0];
+ pos = v[7]->data[posPos];
pos[0] += ( dx * c_a - -dy * s_a);
pos[1] += ( dx * s_a + -dy * c_a);
/*
* Bind (generate) our fragprog, sampler and texture
*/
- bind_aaline_fragment_shader(aaline);
+ if (!bind_aaline_fragment_shader(aaline)) {
+ stage->line = draw_pipe_passthrough_line;
+ stage->line(stage, header);
+ return;
+ }
/* update vertex attrib info */
- aaline->tex_slot = draw->num_vs_outputs;
- assert(aaline->tex_slot > 0); /* output[0] is vertex pos */
+ aaline->tex_slot = draw->vs.num_vs_outputs;
+ aaline->pos_slot = draw->vs.position_output;
/* advertise the extra post-transformed vertex attribute */
draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
pipe_texture_reference(&aaline->state.texture[aaline->fs->sampler_unit],
aaline->texture);
+ draw->suspend_flushing = TRUE;
aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler);
aaline->driver_set_sampler_textures(pipe, num_samplers, aaline->state.texture);
+ draw->suspend_flushing = FALSE;
/* now really draw first line */
stage->line = aaline_line;
stage->line = aaline_first_line;
stage->next->flush( stage->next, flags );
- /* restore original frag shader */
+ /* restore original frag shader, texture, sampler state */
+ draw->suspend_flushing = TRUE;
aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs);
-
- /* XXX restore original texture, sampler state */
aaline->driver_bind_sampler_states(pipe, aaline->num_samplers,
aaline->state.sampler);
aaline->driver_set_sampler_textures(pipe, aaline->num_textures,
aaline->state.texture);
+ draw->suspend_flushing = FALSE;
draw->extra_vp_outputs.slot = 0;
}
aaline_destroy(struct draw_stage *stage)
{
struct aaline_stage *aaline = aaline_stage(stage);
+ uint i;
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ pipe_texture_reference(&aaline->state.texture[i], NULL);
+ }
- aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso);
+ if (aaline->sampler_cso)
+ aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso);
- pipe_texture_release(&aaline->texture);
+ if (aaline->texture)
+ pipe_texture_release(&aaline->texture);
draw_free_temp_verts( stage );
draw_aaline_stage(struct draw_context *draw)
{
struct aaline_stage *aaline = CALLOC_STRUCT(aaline_stage);
+ if (aaline == NULL)
+ return NULL;
- draw_alloc_temp_verts( &aaline->stage, 8 );
+ if (!draw_alloc_temp_verts( &aaline->stage, 8 ))
+ goto fail;
aaline->stage.draw = draw;
aaline->stage.next = NULL;
- aaline->stage.point = passthrough_point;
+ aaline->stage.point = draw_pipe_passthrough_point;
aaline->stage.line = aaline_first_line;
- aaline->stage.tri = passthrough_tri;
+ aaline->stage.tri = draw_pipe_passthrough_tri;
aaline->stage.flush = aaline_flush;
aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter;
aaline->stage.destroy = aaline_destroy;
return aaline;
+
+ fail:
+ if (aaline)
+ aaline_destroy(&aaline->stage);
+
+ return NULL;
}
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
struct aaline_fragment_shader *aafs = CALLOC_STRUCT(aaline_fragment_shader);
+ if (aafs == NULL)
+ return NULL;
- if (aafs) {
- aafs->state = *fs;
+ aafs->state = *fs;
- /* pass-through */
- aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs);
- }
+ /* pass-through */
+ aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs);
return aafs;
}
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
+
/* save current */
aaline->fs = aafs;
/* pass-through */
unsigned num, void **sampler)
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+
/* save current */
memcpy(aaline->state.sampler, sampler, num * sizeof(void *));
aaline->num_samplers = num;
+
/* pass-through */
aaline->driver_bind_sampler_states(aaline->pipe, num, sampler);
}
for (i = 0; i < num; i++) {
pipe_texture_reference(&aaline->state.texture[i], texture[i]);
}
+ for ( ; i < PIPE_MAX_SAMPLERS; i++) {
+ pipe_texture_reference(&aaline->state.texture[i], NULL);
+ }
aaline->num_textures = num;
/* pass-through */
* into the draw module's pipeline. This will not be used if the
* hardware has native support for AA lines.
*/
-void
+boolean
draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe)
{
struct aaline_stage *aaline;
* Create / install AA line drawing / prim stage
*/
aaline = draw_aaline_stage( draw );
- assert(aaline);
- draw->pipeline.aaline = &aaline->stage;
+ if (!aaline)
+ goto fail;
aaline->pipe = pipe;
/* create special texture, sampler state */
- aaline_create_texture(aaline);
- aaline_create_sampler(aaline);
+ if (!aaline_create_texture(aaline))
+ goto fail;
+
+ if (!aaline_create_sampler(aaline))
+ goto fail;
/* save original driver functions */
aaline->driver_create_fs_state = pipe->create_fs_state;
pipe->bind_sampler_states = aaline_bind_sampler_states;
pipe->set_sampler_textures = aaline_set_sampler_textures;
+
+ /* Install once everything is known to be OK:
+ */
+ draw->pipeline.aaline = &aaline->stage;
+
+ return TRUE;
+
+ fail:
+ if (aaline)
+ aaline->stage.destroy( &aaline->stage );
+
+ return FALSE;
}