--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Framebuffer/renderbuffer functions.
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/fbobject.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "st_context.h"
+#include "st_cb_fbo.h"
+#include "st_cb_teximage.h"
+
+
+/**
+ * Derived renderbuffer class. Just need to add a pointer to the
+ * pipe surface.
+ */
+struct st_renderbuffer
+{
+ struct gl_renderbuffer Base;
+ struct pipe_surface *surface;
+};
+
+
+/**
+ * Cast wrapper.
+ */
+static INLINE struct st_renderbuffer *
+st_renderbuffer(struct gl_renderbuffer *rb)
+{
+ return (struct st_renderbuffer *) rb;
+}
+
+
+struct pipe_format_info
+{
+ GLuint format;
+ GLenum base_format;
+ GLubyte red_bits;
+ GLubyte green_bits;
+ GLubyte blue_bits;
+ GLubyte alpha_bits;
+ GLubyte luminance_bits;
+ GLubyte intensity_bits;
+ GLubyte depth_bits;
+ GLubyte stencil_bits;
+ GLubyte size; /**< in bytes */
+};
+
+
+/*
+ * XXX temporary here
+ */
+static const struct pipe_format_info *
+pipe_get_format_info(GLuint format)
+{
+ static const struct pipe_format_info info[] = {
+ {
+ PIPE_FORMAT_U_R8_G8_B8_A8, /* format */
+ GL_RGBA, /* base_format */
+ 4, 4, 4, 4, 0, 0, /* color bits */
+ 0, 0, /* depth, stencil */
+ 4 /* size in bytes */
+ },
+ {
+ PIPE_FORMAT_U_A8_R8_G8_B8,
+ GL_RGBA, /* base_format */
+ 4, 4, 4, 4, 0, 0, /* color bits */
+ 0, 0, /* depth, stencil */
+ 4 /* size in bytes */
+ },
+ {
+ PIPE_FORMAT_U_A1_R5_G5_B5,
+ GL_RGBA, /* base_format */
+ 5, 5, 5, 1, 0, 0, /* color bits */
+ 0, 0, /* depth, stencil */
+ 2 /* size in bytes */
+ },
+ {
+ PIPE_FORMAT_U_R5_G6_B5,
+ GL_RGBA, /* base_format */
+ 5, 6, 5, 0, 0, 0, /* color bits */
+ 0, 0, /* depth, stencil */
+ 2 /* size in bytes */
+ },
+ /* XXX lots more */
+ {
+ PIPE_FORMAT_S8_Z24,
+ GL_DEPTH_STENCIL_EXT, /* base_format */
+ 0, 0, 0, 0, 0, 0, /* color bits */
+ 24, 8, /* depth, stencil */
+ 4 /* size in bytes */
+ }
+ };
+ GLuint i;
+
+ for (i = 0; i < sizeof(info) / sizeof(info[0]); i++) {
+ if (info[i].format == format)
+ return info + i;
+ }
+ return NULL;
+}
+
+
+/**
+ * gl_renderbuffer::AllocStorage()
+ */
+static GLboolean
+st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ const GLuint pipeFormat
+ = st_choose_pipe_format(pipe, internalFormat, GL_NONE, GL_NONE);
+ const struct pipe_format_info *info = pipe_get_format_info(pipeFormat);
+ GLuint cpp, pitch;
+
+ if (!info)
+ return GL_FALSE;
+
+ strb->Base._ActualFormat = info->base_format;
+ strb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix */
+ strb->Base.RedBits = info->red_bits;
+ strb->Base.GreenBits = info->green_bits;
+ strb->Base.BlueBits = info->blue_bits;
+ strb->Base.AlphaBits = info->alpha_bits;
+ strb->Base.DepthBits = info->depth_bits;
+ strb->Base.StencilBits = info->stencil_bits;
+
+ cpp = info->size;
+
+ if (!strb->surface) {
+ strb->surface = pipe->surface_alloc(pipe, pipeFormat);
+ if (!strb->surface)
+ return GL_FALSE;
+ }
+
+ /* free old region */
+ if (strb->surface->region) {
+ pipe->region_release(pipe, &strb->surface->region);
+ }
+
+ /* Choose a pitch to match hardware requirements:
+ */
+ pitch = ((cpp * width + 63) & ~63) / cpp; /* XXX fix: device-specific */
+
+ strb->surface->region = pipe->region_alloc(pipe, cpp, pitch, height);
+ if (!strb->surface->region)
+ return GL_FALSE; /* out of memory, try s/w buffer? */
+
+ ASSERT(strb->surface->region->buffer);
+
+ strb->Base.Width = strb->surface->width = width;
+ strb->Base.Height = strb->surface->height = height;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * gl_renderbuffer::Delete()
+ */
+static void
+st_renderbuffer_delete(struct gl_renderbuffer *rb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ ASSERT(strb);
+ if (strb && strb->surface) {
+ if (rb->surface->region) {
+ pipe->region_release(pipe, &strb->surface->region);
+ }
+ free(strb->surface);
+ }
+ free(strb);
+}
+
+
+/**
+ * gl_renderbuffer::GetPointer()
+ */
+static void *
+null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ /* By returning NULL we force all software rendering to go through
+ * the span routines.
+ */
+ assert(0); /* Should never get called with softpipe */
+ return NULL;
+}
+
+
+/**
+ * Called via ctx->Driver.NewFramebuffer()
+ */
+static struct gl_framebuffer *
+st_new_framebuffer(GLcontext *ctx, GLuint name)
+{
+ /* XXX not sure we need to subclass gl_framebuffer for pipe */
+ return _mesa_new_framebuffer(ctx, name);
+}
+
+
+/**
+ * Called via ctx->Driver.NewRenderbuffer()
+ */
+static struct gl_renderbuffer *
+st_new_renderbuffer(GLcontext *ctx, GLuint name)
+{
+ struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer);
+ if (strb) {
+ _mesa_init_renderbuffer(&strb->Base, name);
+ strb->Base.Delete = st_renderbuffer_delete;
+ strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+ strb->Base.GetPointer = null_get_pointer;
+ return &strb->Base;
+ }
+ return NULL;
+}
+
+/**
+ * Called via ctx->Driver.BindFramebufferEXT().
+ */
+static void
+st_bind_framebuffer(GLcontext *ctx, GLenum target,
+ struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
+{
+
+}
+
+/**
+ * Called by ctx->Driver.FramebufferRenderbuffer
+ */
+static void
+st_framebuffer_renderbuffer(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb)
+{
+ /* XXX no need for derivation? */
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+}
+
+
+/**
+ * Called by ctx->Driver.RenderTexture
+ */
+static void
+st_render_texture(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_surface *texsurface;
+
+ texsurface = NULL; /* find the mipmap level, cube face, etc */
+
+ /*
+ * XXX basically like this... set the current color (or depth)
+ * drawing surface to be the given texture renderbuffer.
+ */
+ memset(&framebuffer, 0, sizeof(framebuffer));
+ framebuffer.num_cbufs = 1;
+ framebuffer.cbufs[0] = texsurface;
+
+ if (memcmp(&framebuffer, &st->state.framebuffer, sizeof(framebuffer)) != 0) {
+ st->state.framebuffer = framebuffer;
+ st->pipe->set_framebuffer_state( st->pipe, &framebuffer );
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.FinishRenderTexture.
+ */
+static void
+st_finish_render_texture(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+ /* restore drawing to normal framebuffer. may be a no-op */
+}
+
+
+
+void st_init_cb_fbo( struct st_context *st )
+{
+ struct dd_function_table *functions = &st->ctx->Driver;
+
+ functions->NewFramebuffer = st_new_framebuffer;
+ functions->NewRenderbuffer = st_new_renderbuffer;
+ functions->BindFramebuffer = st_bind_framebuffer;
+ functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
+ functions->RenderTexture = st_render_texture;
+ functions->FinishRenderTexture = st_finish_render_texture;
+ /* no longer needed by core Mesa, drivers handle resizes...
+ functions->ResizeBuffers = st_resize_buffers;
+ */
+}
+
+
+void st_destroy_cb_fbo( struct st_context *st )
+{
+}