*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Brian Paul
+ * Michel Dänzer
*/
#include "main/glheader.h"
#include "st_program.h"
#include "st_public.h"
#include "st_mesa_to_tgsi.h"
+#include "st_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
{
struct pipe_context *pipe = st->pipe;
- /* rasterizer state: bypass clipping */
memset(&st->clear.raster, 0, sizeof(st->clear.raster));
st->clear.raster.gl_rasterization_rules = 1;
- st->clear.raster.bypass_clipping = 1;
-
- /* viewport state: identity since we're drawing in window coords */
- st->clear.viewport.scale[0] = 1.0;
- st->clear.viewport.scale[1] = 1.0;
- st->clear.viewport.scale[2] = 1.0;
- st->clear.viewport.scale[3] = 1.0;
- st->clear.viewport.translate[0] = 0.0;
- st->clear.viewport.translate[1] = 0.0;
- st->clear.viewport.translate[2] = 0.0;
- st->clear.viewport.translate[3] = 0.0;
+
+ /* rasterizer state: bypass vertex shader, clipping and viewport */
+ st->clear.raster.bypass_vs_clip_and_viewport = 1;
/* fragment shader state: color pass-through program */
st->clear.fs =
- util_make_fragment_passthrough_shader(pipe, &st->clear.frag_shader);
+ util_make_fragment_passthrough_shader(pipe);
/* vertex shader state: color/position pass-through */
{
const uint semantic_indexes[] = { 0, 0 };
st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2,
semantic_names,
- semantic_indexes,
- &st->clear.vert_shader);
+ semantic_indexes);
}
}
void
st_destroy_clear(struct st_context *st)
{
- struct pipe_context *pipe = st->pipe;
-
- if (st->clear.vert_shader.tokens) {
- FREE((void *) st->clear.vert_shader.tokens);
- st->clear.vert_shader.tokens = NULL;
- }
-
- if (st->clear.frag_shader.tokens) {
- FREE((void *) st->clear.frag_shader.tokens);
- st->clear.frag_shader.tokens = NULL;
- }
-
if (st->clear.fs) {
cso_delete_fragment_shader(st->cso_context, st->clear.fs);
st->clear.fs = NULL;
st->clear.vs = NULL;
}
if (st->clear.vbuf) {
- pipe_buffer_reference(pipe->screen, &st->clear.vbuf, NULL);
+ pipe_buffer_reference(&st->clear.vbuf, NULL);
st->clear.vbuf = NULL;
}
}
-static GLboolean
-is_depth_stencil_format(enum pipe_format pipeFormat)
-{
- switch (pipeFormat) {
- case PIPE_FORMAT_S8Z24_UNORM:
- case PIPE_FORMAT_Z24S8_UNORM:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-
/**
* Draw a screen-aligned quadrilateral.
- * Coords are window coords with y=0=bottom. These coords will be transformed
- * by the vertex shader and viewport transform (which will flip Y if needed).
+ * Coords are window coords with y=0=bottom. These will be passed
+ * through unmodified to the rasterizer as we have set
+ * rasterizer->bypass_vs_clip_and_viewport.
*/
static void
draw_quad(GLcontext *ctx,
struct pipe_context *pipe = st->pipe;
const GLuint max_slots = 1024 / sizeof(st->clear.vertices);
GLuint i;
- void *buf;
if (st->clear.vbuf_slot >= max_slots) {
- pipe_buffer_reference(pipe->screen, &st->clear.vbuf, NULL);
+ pipe_buffer_reference(&st->clear.vbuf, NULL);
st->clear.vbuf_slot = 0;
}
}
/* put vertex data into vbuf */
- buf = pipe_buffer_map(pipe->screen, st->clear.vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
-
- memcpy((char *)buf + st->clear.vbuf_slot * sizeof(st->clear.vertices),
- st->clear.vertices,
- sizeof(st->clear.vertices));
-
- pipe_buffer_unmap(pipe->screen, st->clear.vbuf);
+ st_no_flush_pipe_buffer_write(st, st->clear.vbuf,
+ st->clear.vbuf_slot * sizeof(st->clear.vertices),
+ sizeof(st->clear.vertices),
+ st->clear.vertices);
/* draw */
util_draw_vertex_buffer(pipe,
cso_save_blend(st->cso_context);
cso_save_depth_stencil_alpha(st->cso_context);
cso_save_rasterizer(st->cso_context);
- cso_save_viewport(st->cso_context);
cso_save_fragment_shader(st->cso_context);
cso_save_vertex_shader(st->cso_context);
}
cso_set_rasterizer(st->cso_context, &st->clear.raster);
- cso_set_viewport(st->cso_context, &st->clear.viewport);
cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
cso_restore_blend(st->cso_context);
cso_restore_depth_stencil_alpha(st->cso_context);
cso_restore_rasterizer(st->cso_context);
- cso_restore_viewport(st->cso_context);
cso_restore_fragment_shader(st->cso_context);
cso_restore_vertex_shader(st->cso_context);
}
static INLINE GLboolean
check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
{
- const struct st_renderbuffer *strb = st_renderbuffer(rb);
-
- if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
- return FALSE;
-
- if (ctx->Scissor.Enabled)
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
return TRUE;
if (!ctx->Color.ColorMask[0] ||
static INLINE GLboolean
check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
{
- const struct st_renderbuffer *strb = st_renderbuffer(rb);
const GLuint stencilMax = (1 << rb->StencilBits) - 1;
GLboolean maskStencil
= (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
- if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
- return FALSE;
-
- if (ctx->Scissor.Enabled)
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
return TRUE;
if (maskStencil)
check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
{
const struct st_renderbuffer *strb = st_renderbuffer(rb);
- const GLboolean isDS = is_depth_stencil_format(strb->surface->format);
-
- if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
- return FALSE;
+ const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
- if (ctx->Scissor.Enabled)
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
return TRUE;
if (isDS &&
- strb->surface->status == PIPE_SURFACE_STATUS_DEFINED &&
ctx->DrawBuffer->Visual.stencilBits > 0)
return TRUE;
check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
{
const struct st_renderbuffer *strb = st_renderbuffer(rb);
- const GLboolean isDS = is_depth_stencil_format(strb->surface->format);
+ const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
const GLuint stencilMax = (1 << rb->StencilBits) - 1;
const GLboolean maskStencil
= (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
- if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
- return FALSE;
-
if (maskStencil)
return TRUE;
- if (ctx->Scissor.Enabled)
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
return TRUE;
/* This is correct, but it is necessary to look at the depth clear
* current state.
*/
if (isDS &&
- strb->surface->status == PIPE_SURFACE_STATUS_DEFINED &&
ctx->DrawBuffer->Visual.depthBits > 0)
return TRUE;
-static void
-clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
-{
- struct st_renderbuffer *strb = st_renderbuffer(rb);
-
- if (!strb->surface)
- return;
-
- if (check_clear_color_with_quad( ctx, rb )) {
- /* masking or scissoring */
- clear_with_quad(ctx, GL_TRUE, GL_FALSE, GL_FALSE);
- }
- else {
- /* clear whole buffer w/out masking */
- uint clearValue;
- /* NOTE: we always pass the clear color as PIPE_FORMAT_A8R8G8B8_UNORM
- * at this time!
- */
- util_pack_color(ctx->Color.ClearColor, PIPE_FORMAT_A8R8G8B8_UNORM, &clearValue);
- ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
- }
-}
-
-
-static void
-clear_depth_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
-{
- struct st_renderbuffer *strb = st_renderbuffer(rb);
-
- if (!strb->surface)
- return;
-
- if (check_clear_depth_with_quad(ctx, rb)) {
- /* scissoring or we have a combined depth/stencil buffer */
- clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_FALSE);
- }
- else {
- /* simple clear of whole buffer */
- uint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear);
- ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
- }
-}
-
-
-static void
-clear_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
-{
- struct st_renderbuffer *strb = st_renderbuffer(rb);
-
- if (!strb->surface)
- return;
-
- if (check_clear_stencil_with_quad(ctx, rb)) {
- /* masking or scissoring or combined depth/stencil buffer */
- clear_with_quad(ctx, GL_FALSE, GL_FALSE, GL_TRUE);
- }
- else {
- /* simple clear of whole buffer */
- GLuint clearValue = ctx->Stencil.Clear;
-
- switch (strb->surface->format) {
- case PIPE_FORMAT_S8Z24_UNORM:
- clearValue <<= 24;
- break;
- default:
- ; /* no-op, stencil value is in least significant bits */
- }
-
- ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
- }
-}
-
-
-static void
-clear_depth_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
-{
- struct st_renderbuffer *strb = st_renderbuffer(rb);
-
- if (!strb->surface)
- return;
-
- if (check_clear_depth_stencil_with_quad(ctx, rb)) {
- /* masking or scissoring */
- clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_TRUE);
- }
- else {
- /* clear whole buffer w/out masking */
- GLuint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear);
-
- switch (strb->surface->format) {
- case PIPE_FORMAT_S8Z24_UNORM:
- clearValue |= ctx->Stencil.Clear << 24;
- break;
- case PIPE_FORMAT_Z24S8_UNORM:
- clearValue |= ctx->Stencil.Clear;
- break;
- default:
- assert(0);
- }
-
- ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
- }
-}
-
-
void st_flush_clear( struct st_context *st )
{
/* Release vertex buffer to avoid synchronous rendering if we were
* to map it in the next frame.
*/
- pipe_buffer_reference(st->pipe->screen, &st->clear.vbuf, NULL);
+ pipe_buffer_reference(&st->clear.vbuf, NULL);
st->clear.vbuf_slot = 0;
}
= ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
struct gl_renderbuffer *stencilRb
= ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
- GLbitfield cmask = mask & BUFFER_BITS_COLOR;
+ GLbitfield quad_buffers = 0;
+ GLbitfield clear_buffers = 0;
+ GLuint i;
- /* This makes sure the softpipe has the latest scissor, etc values */
+ /* This makes sure the pipe has the latest scissor, etc values */
st_validate_state( st );
- /*
- * XXX TO-DO:
- * If we're going to use clear_with_quad() for any reason, use it to
- * clear as many other buffers as possible.
- * As it is now, we sometimes call clear_with_quad() three times to clear
- * color/depth/stencil individually...
- */
+ if (mask & BUFFER_BITS_COLOR) {
+ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
- if (cmask) {
- GLuint b;
- for (b = 0; cmask; b++) {
- if (cmask & (1 << b)) {
+ if (mask & (1 << b)) {
struct gl_renderbuffer *rb
= ctx->DrawBuffer->Attachment[b].Renderbuffer;
+ struct st_renderbuffer *strb;
+
assert(rb);
- clear_color_buffer(ctx, rb);
- cmask &= ~(1 << b); /* turn off bit */
+
+ strb = st_renderbuffer(rb);
+
+ if (!strb->surface)
+ continue;
+
+ if (check_clear_color_with_quad( ctx, rb ))
+ quad_buffers |= PIPE_CLEAR_COLOR;
+ else
+ clear_buffers |= PIPE_CLEAR_COLOR;
}
- assert(b < BUFFER_COUNT);
}
}
- if (mask & BUFFER_BIT_ACCUM) {
- st_clear_accum_buffer(ctx,
- ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
- }
-
if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) {
/* clearing combined depth + stencil */
- clear_depth_stencil_buffer(ctx, depthRb);
+ struct st_renderbuffer *strb = st_renderbuffer(depthRb);
+
+ if (strb->surface) {
+ if (check_clear_depth_stencil_with_quad(ctx, depthRb))
+ quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ }
}
else {
/* separate depth/stencil clears */
if (mask & BUFFER_BIT_DEPTH) {
- clear_depth_buffer(ctx, depthRb);
+ struct st_renderbuffer *strb = st_renderbuffer(depthRb);
+
+ if (strb->surface) {
+ if (check_clear_depth_with_quad(ctx, depthRb))
+ quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ }
}
if (mask & BUFFER_BIT_STENCIL) {
- clear_stencil_buffer(ctx, stencilRb);
+ struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
+
+ if (strb->surface) {
+ if (check_clear_stencil_with_quad(ctx, stencilRb))
+ quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ }
}
}
+
+ /*
+ * If we're going to use clear_with_quad() for any reason, use it for
+ * everything possible.
+ */
+ if (quad_buffers) {
+ quad_buffers |= clear_buffers;
+ clear_with_quad(ctx,
+ quad_buffers & PIPE_CLEAR_COLOR,
+ mask & BUFFER_BIT_DEPTH,
+ mask & BUFFER_BIT_STENCIL);
+ } else if (clear_buffers)
+ ctx->st->pipe->clear(ctx->st->pipe, clear_buffers, ctx->Color.ClearColor,
+ ctx->Depth.Clear, ctx->Stencil.Clear);
+
+ if (mask & BUFFER_BIT_ACCUM)
+ st_clear_accum_buffer(ctx,
+ ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
}