diff options
-rw-r--r-- | libX11/src/xcms/LRGB.c | 1 | ||||
-rw-r--r-- | libX11/src/xcms/cmsProp.c | 17 | ||||
-rw-r--r-- | mesalib/include/EGL/eglplatform.h | 246 | ||||
-rw-r--r-- | mesalib/scons/gallium.py | 10 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_atom_framebuffer.c | 362 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_cb_fbo.c | 1240 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_draw_feedback.c | 19 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_extensions.c | 9 |
8 files changed, 964 insertions, 940 deletions
diff --git a/libX11/src/xcms/LRGB.c b/libX11/src/xcms/LRGB.c index 750c4924e..2dca82ee8 100644 --- a/libX11/src/xcms/LRGB.c +++ b/libX11/src/xcms/LRGB.c @@ -573,7 +573,6 @@ LINEAR_RGB_InitSCCData( if (CorrectAtom == None || !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), CorrectAtom, &format_return, &nitems, &nbytes_return, &property_return)) { - Xfree ((char *)property_return); goto FreeSCCData; } diff --git a/libX11/src/xcms/cmsProp.c b/libX11/src/xcms/cmsProp.c index 856ae84b6..2826ee7be 100644 --- a/libX11/src/xcms/cmsProp.c +++ b/libX11/src/xcms/cmsProp.c @@ -121,20 +121,23 @@ _XcmsGetProperty( long len = 6516; unsigned long nitems_ret, after_ret; Atom atom_ret; + int xgwp_ret; - while (XGetWindowProperty (pDpy, w, property, 0, len, False, - XA_INTEGER, &atom_ret, &format_ret, - &nitems_ret, &after_ret, - (unsigned char **)&prop_ret)) { - if (after_ret > 0) { + while (True) { + xgwp_ret = XGetWindowProperty (pDpy, w, property, 0, len, False, + XA_INTEGER, &atom_ret, &format_ret, + &nitems_ret, &after_ret, + (unsigned char **)&prop_ret); + if (xgwp_ret == Success && after_ret > 0) { len += nitems_ret * (format_ret >> 3); XFree (prop_ret); } else { break; } } - if (format_ret == 0 || nitems_ret == 0) { - /* the property does not exist or is of an unexpected type */ + if (xgwp_ret != Success || format_ret == 0 || nitems_ret == 0) { + /* the property does not exist or is of an unexpected type or + getting window property failed */ return(XcmsFailure); } diff --git a/mesalib/include/EGL/eglplatform.h b/mesalib/include/EGL/eglplatform.h index 18dfb83a0..ee371eab9 100644 --- a/mesalib/include/EGL/eglplatform.h +++ b/mesalib/include/EGL/eglplatform.h @@ -1,120 +1,126 @@ -#ifndef __eglplatform_h_
-#define __eglplatform_h_
-
-/*
-** Copyright (c) 2007-2009 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a
-** copy of this software and/or associated documentation files (the
-** "Materials"), to deal in the Materials without restriction, including
-** without limitation the rights to use, copy, modify, merge, publish,
-** distribute, sublicense, and/or sell copies of the Materials, and to
-** permit persons to whom the Materials are furnished to do so, subject to
-** the following conditions:
-**
-** The above copyright notice and this permission notice shall be included
-** in all copies or substantial portions of the Materials.
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-*/
-
-/* Platform-specific types and definitions for egl.h
- * $Revision$ on $Date: 2009-12-02 02:05:33 -0800 (Wed, 02 Dec 2009) $
- *
- * Adopters may modify khrplatform.h and this file to suit their platform.
- * You are encouraged to submit all modifications to the Khronos group so that
- * they can be included in future versions of this file. Please submit changes
- * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
- * by filing a bug against product "EGL" component "Registry".
- */
-
-#include <KHR/khrplatform.h>
-
-/* Macros used in EGL function prototype declarations.
- *
- * EGL functions should be prototyped as:
- *
- * EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
- * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
- *
- * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
- */
-
-#ifndef EGLAPI
-#define EGLAPI KHRONOS_APICALL
-#endif
-
-#ifndef EGLAPIENTRY
-#define EGLAPIENTRY KHRONOS_APIENTRY
-#endif
-#define EGLAPIENTRYP EGLAPIENTRY*
-
-/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
- * are aliases of window-system-dependent types, such as X Display * or
- * Windows Device Context. They must be defined in platform-specific
- * code below. The EGL-prefixed versions of Native*Type are the same
- * types, renamed in EGL 1.3 so all types in the API start with "EGL".
- */
-
-#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN 1
-#endif
-#include <windows.h>
-
-typedef HDC EGLNativeDisplayType;
-typedef HBITMAP EGLNativePixmapType;
-typedef HWND EGLNativeWindowType;
-
-#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
-
-typedef int EGLNativeDisplayType;
-typedef void *EGLNativeWindowType;
-typedef void *EGLNativePixmapType;
-
-#elif defined(__unix__) || defined(__unix)
-
-#ifdef MESA_EGL_NO_X11_HEADERS
-
-typedef void *EGLNativeDisplayType;
-typedef khronos_uint32_t EGLNativePixmapType;
-typedef khronos_uint32_t EGLNativeWindowType;
-
-#else
-
-/* X11 (tentative) */
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-typedef Display *EGLNativeDisplayType;
-typedef Pixmap EGLNativePixmapType;
-typedef Window EGLNativeWindowType;
-
-#endif /* MESA_EGL_NO_X11_HEADERS */
-
-#else
-#error "Platform not recognized"
-#endif
-
-/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
-typedef EGLNativeDisplayType NativeDisplayType;
-typedef EGLNativePixmapType NativePixmapType;
-typedef EGLNativeWindowType NativeWindowType;
-
-
-/* Define EGLint. This must be a signed integral type large enough to contain
- * all legal attribute names and values passed into and out of EGL, whether
- * their type is boolean, bitmask, enumerant (symbolic constant), integer,
- * handle, or other. While in general a 32-bit integer will suffice, if
- * handles are 64 bit types, then EGLint should be defined as a signed 64-bit
- * integer type.
- */
-typedef khronos_int32_t EGLint;
-
-#endif /* __eglplatform_h */
+#ifndef __eglplatform_h_ +#define __eglplatform_h_ + +/* +** Copyright (c) 2007-2009 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Platform-specific types and definitions for egl.h + * $Revision$ on $Date: 2009-12-02 02:05:33 -0800 (Wed, 02 Dec 2009) $ + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "EGL" component "Registry". + */ + +#include <KHR/khrplatform.h> + +/* Macros used in EGL function prototype declarations. + * + * EGL functions should be prototyped as: + * + * EGLAPI return-type EGLAPIENTRY eglFunction(arguments); + * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments); + * + * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h + */ + +#ifndef EGLAPI +#define EGLAPI KHRONOS_APICALL +#endif + +#ifndef EGLAPIENTRY +#define EGLAPIENTRY KHRONOS_APIENTRY +#endif +#define EGLAPIENTRYP EGLAPIENTRY* + +/* The types NativeDisplayType, NativeWindowType, and NativePixmapType + * are aliases of window-system-dependent types, such as X Display * or + * Windows Device Context. They must be defined in platform-specific + * code below. The EGL-prefixed versions of Native*Type are the same + * types, renamed in EGL 1.3 so all types in the API start with "EGL". + */ + +#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include <windows.h> + +typedef HDC EGLNativeDisplayType; +typedef HBITMAP EGLNativePixmapType; +typedef HWND EGLNativeWindowType; + +#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ + +typedef int EGLNativeDisplayType; +typedef void *EGLNativeWindowType; +typedef void *EGLNativePixmapType; + +#elif defined(WL_EGL_PLATFORM) + +typedef struct wl_egl_display *EGLNativeDisplayType; +typedef struct wl_egl_pixmap *EGLNativePixmapType; +typedef struct wl_egl_window *EGLNativeWindowType; + +#elif defined(__unix__) || defined(__unix) + +#ifdef MESA_EGL_NO_X11_HEADERS + +typedef void *EGLNativeDisplayType; +typedef khronos_uint32_t EGLNativePixmapType; +typedef khronos_uint32_t EGLNativeWindowType; + +#else + +/* X11 (tentative) */ +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +typedef Display *EGLNativeDisplayType; +typedef Pixmap EGLNativePixmapType; +typedef Window EGLNativeWindowType; + +#endif /* MESA_EGL_NO_X11_HEADERS */ + +#else +#error "Platform not recognized" +#endif + +/* EGL 1.2 types, renamed for consistency in EGL 1.3 */ +typedef EGLNativeDisplayType NativeDisplayType; +typedef EGLNativePixmapType NativePixmapType; +typedef EGLNativeWindowType NativeWindowType; + + +/* Define EGLint. This must be a signed integral type large enough to contain + * all legal attribute names and values passed into and out of EGL, whether + * their type is boolean, bitmask, enumerant (symbolic constant), integer, + * handle, or other. While in general a 32-bit integer will suffice, if + * handles are 64 bit types, then EGLint should be defined as a signed 64-bit + * integer type. + */ +typedef khronos_int32_t EGLint; + +#endif /* __eglplatform_h */ diff --git a/mesalib/scons/gallium.py b/mesalib/scons/gallium.py index df060f01a..c4144273a 100644 --- a/mesalib/scons/gallium.py +++ b/mesalib/scons/gallium.py @@ -402,13 +402,19 @@ def generate(env): '/Od', # disable optimizations '/Oi', # enable intrinsic functions '/Oy-', # disable frame pointer omission - '/GL-', # disable whole program optimization ] else: ccflags += [ '/O2', # optimize for speed + ] + if env['build'] == 'release': + ccflags += [ '/GL', # enable whole program optimization ] + else: + ccflags += [ + '/GL-', # disable whole program optimization + ] ccflags += [ '/fp:fast', # fast floating point '/W3', # warning level @@ -498,7 +504,7 @@ def generate(env): else: env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group' if msvc: - if env['build'] != 'debug': + if env['build'] == 'release': # enable Link-time Code Generation linkflags += ['/LTCG'] env.Append(ARFLAGS = ['/LTCG']) diff --git a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c index 3ba690200..76386fe01 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c @@ -1,180 +1,182 @@ -/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- * Brian Paul
- */
-
-#include "st_context.h"
-#include "st_atom.h"
-#include "st_cb_fbo.h"
-#include "st_texture.h"
-#include "pipe/p_context.h"
-#include "cso_cache/cso_context.h"
-#include "util/u_math.h"
-#include "util/u_inlines.h"
-
-
-
-/**
- * When doing GL render to texture, we have to be sure that finalize_texture()
- * didn't yank out the pipe_resource that we earlier created a surface for.
- * Check for that here and create a new surface if needed.
- */
-static void
-update_renderbuffer_surface(struct st_context *st,
- struct st_renderbuffer *strb)
-{
- struct pipe_context *pipe = st->pipe;
- struct pipe_resource *resource = strb->rtt->pt;
- int rtt_width = strb->Base.Width;
- int rtt_height = strb->Base.Height;
-
- if (!strb->surface ||
- strb->surface->texture != resource ||
- strb->surface->width != rtt_width ||
- strb->surface->height != rtt_height) {
- GLuint level;
- /* find matching mipmap level size */
- for (level = 0; level <= resource->last_level; level++) {
- if (u_minify(resource->width0, level) == rtt_width &&
- u_minify(resource->height0, level) == rtt_height) {
- struct pipe_surface surf_tmpl;
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- surf_tmpl.format = resource->format;
- surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
- surf_tmpl.u.tex.level = level;
- surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
- surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
-
- pipe_surface_reference(&strb->surface, NULL);
-
- strb->surface = pipe->create_surface(pipe,
- resource,
- &surf_tmpl);
-#if 0
- printf("-- alloc new surface %d x %d into tex %p\n",
- strb->surface->width, strb->surface->height,
- texture);
-#endif
- break;
- }
- }
- }
-}
-
-
-/**
- * Update framebuffer state (color, depth, stencil, etc. buffers)
- */
-static void
-update_framebuffer_state( struct st_context *st )
-{
- struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer;
- struct gl_framebuffer *fb = st->ctx->DrawBuffer;
- struct st_renderbuffer *strb;
- GLuint i;
-
- framebuffer->width = fb->Width;
- framebuffer->height = fb->Height;
-
- /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/
-
- /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
- * to determine which surfaces to draw to
- */
- framebuffer->nr_cbufs = 0;
- for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
- strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);
-
- if (strb) {
- /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/
- if (strb->rtt) {
- /* rendering to a GL texture, may have to update surface */
- update_renderbuffer_surface(st, strb);
- }
-
- if (strb->surface) {
- pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs],
- strb->surface);
- framebuffer->nr_cbufs++;
- }
- strb->defined = GL_TRUE; /* we'll be drawing something */
- }
- }
- for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
- pipe_surface_reference(&framebuffer->cbufs[i], NULL);
- }
-
- /*
- * Depth/Stencil renderbuffer/surface.
- */
- strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
- if (strb) {
- strb = st_renderbuffer(strb->Base.Wrapped);
- if (strb->rtt) {
- /* rendering to a GL texture, may have to update surface */
- update_renderbuffer_surface(st, strb);
- }
- pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
- }
- else {
- strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
- if (strb) {
- strb = st_renderbuffer(strb->Base.Wrapped);
- assert(strb->surface);
- pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
- }
- else
- pipe_surface_reference(&framebuffer->zsbuf, NULL);
- }
-
-#ifdef DEBUG
- /* Make sure the resource binding flags were set properly */
- for (i = 0; i < framebuffer->nr_cbufs; i++) {
- assert(framebuffer->cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET);
- }
- if (framebuffer->zsbuf) {
- assert(framebuffer->zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL);
- }
-#endif
-
- cso_set_framebuffer(st->cso_context, framebuffer);
-}
-
-
-const struct st_tracked_state st_update_framebuffer = {
- "st_update_framebuffer", /* name */
- { /* dirty */
- _NEW_BUFFERS, /* mesa */
- ST_NEW_FRAMEBUFFER, /* st */
- },
- update_framebuffer_state /* update */
-};
-
+/************************************************************************** + * + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Brian Paul + */ + +#include "st_context.h" +#include "st_atom.h" +#include "st_cb_fbo.h" +#include "st_texture.h" +#include "pipe/p_context.h" +#include "cso_cache/cso_context.h" +#include "util/u_math.h" +#include "util/u_inlines.h" +#include "util/u_format.h" + + +/** + * When doing GL render to texture, we have to be sure that finalize_texture() + * didn't yank out the pipe_resource that we earlier created a surface for. + * Check for that here and create a new surface if needed. + */ +static void +update_renderbuffer_surface(struct st_context *st, + struct st_renderbuffer *strb) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_resource *resource = strb->rtt->pt; + int rtt_width = strb->Base.Width; + int rtt_height = strb->Base.Height; + enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format); + + if (!strb->surface || + strb->surface->format != format || + strb->surface->texture != resource || + strb->surface->width != rtt_width || + strb->surface->height != rtt_height) { + GLuint level; + /* find matching mipmap level size */ + for (level = 0; level <= resource->last_level; level++) { + if (u_minify(resource->width0, level) == rtt_width && + u_minify(resource->height0, level) == rtt_height) { + struct pipe_surface surf_tmpl; + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = format; + surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; + surf_tmpl.u.tex.level = level; + surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; + surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; + + pipe_surface_reference(&strb->surface, NULL); + + strb->surface = pipe->create_surface(pipe, + resource, + &surf_tmpl); +#if 0 + printf("-- alloc new surface %d x %d into tex %p\n", + strb->surface->width, strb->surface->height, + texture); +#endif + break; + } + } + } +} + + +/** + * Update framebuffer state (color, depth, stencil, etc. buffers) + */ +static void +update_framebuffer_state( struct st_context *st ) +{ + struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer; + struct gl_framebuffer *fb = st->ctx->DrawBuffer; + struct st_renderbuffer *strb; + GLuint i; + + framebuffer->width = fb->Width; + framebuffer->height = fb->Height; + + /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/ + + /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state + * to determine which surfaces to draw to + */ + framebuffer->nr_cbufs = 0; + for (i = 0; i < fb->_NumColorDrawBuffers; i++) { + strb = st_renderbuffer(fb->_ColorDrawBuffers[i]); + + if (strb) { + /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/ + if (strb->rtt) { + /* rendering to a GL texture, may have to update surface */ + update_renderbuffer_surface(st, strb); + } + + if (strb->surface) { + pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs], + strb->surface); + framebuffer->nr_cbufs++; + } + strb->defined = GL_TRUE; /* we'll be drawing something */ + } + } + for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) { + pipe_surface_reference(&framebuffer->cbufs[i], NULL); + } + + /* + * Depth/Stencil renderbuffer/surface. + */ + strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); + if (strb) { + strb = st_renderbuffer(strb->Base.Wrapped); + if (strb->rtt) { + /* rendering to a GL texture, may have to update surface */ + update_renderbuffer_surface(st, strb); + } + pipe_surface_reference(&framebuffer->zsbuf, strb->surface); + } + else { + strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); + if (strb) { + strb = st_renderbuffer(strb->Base.Wrapped); + assert(strb->surface); + pipe_surface_reference(&framebuffer->zsbuf, strb->surface); + } + else + pipe_surface_reference(&framebuffer->zsbuf, NULL); + } + +#ifdef DEBUG + /* Make sure the resource binding flags were set properly */ + for (i = 0; i < framebuffer->nr_cbufs; i++) { + assert(framebuffer->cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET); + } + if (framebuffer->zsbuf) { + assert(framebuffer->zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL); + } +#endif + + cso_set_framebuffer(st->cso_context, framebuffer); +} + + +const struct st_tracked_state st_update_framebuffer = { + "st_update_framebuffer", /* name */ + { /* dirty */ + _NEW_BUFFERS, /* mesa */ + ST_NEW_FRAMEBUFFER, /* st */ + }, + update_framebuffer_state /* update */ +}; + diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index 3c73c24c5..398e32a34 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -1,620 +1,620 @@ -/**************************************************************************
- *
- * 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/macros.h"
-#include "main/mfeatures.h"
-#include "main/renderbuffer.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_screen.h"
-#include "st_context.h"
-#include "st_cb_fbo.h"
-#include "st_cb_flush.h"
-#include "st_format.h"
-#include "st_texture.h"
-#include "st_manager.h"
-
-#include "util/u_format.h"
-#include "util/u_inlines.h"
-#include "util/u_surface.h"
-
-
-/**
- * gl_renderbuffer::AllocStorage()
- * This is called to allocate the original drawing surface, and
- * during window resize.
- */
-static GLboolean
-st_renderbuffer_alloc_storage(struct gl_context * ctx,
- struct gl_renderbuffer *rb,
- GLenum internalFormat,
- GLuint width, GLuint height)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct pipe_screen *screen = st->pipe->screen;
- struct st_renderbuffer *strb = st_renderbuffer(rb);
- enum pipe_format format;
- struct pipe_surface surf_tmpl;
-
- if (strb->format != PIPE_FORMAT_NONE)
- format = strb->format;
- else
- format = st_choose_renderbuffer_format(screen, internalFormat,
- rb->NumSamples);
-
- /* init renderbuffer fields */
- strb->Base.Width = width;
- strb->Base.Height = height;
- strb->Base.Format = st_pipe_format_to_mesa_format(format);
- strb->Base.DataType = st_format_datatype(format);
-
- strb->defined = GL_FALSE; /* undefined contents now */
-
- if (strb->software) {
- size_t size;
-
- free(strb->data);
-
- assert(strb->format != PIPE_FORMAT_NONE);
-
- strb->stride = util_format_get_stride(strb->format, width);
- size = util_format_get_2d_size(strb->format, strb->stride, height);
-
- strb->data = malloc(size);
-
- return strb->data != NULL;
- }
- else {
- struct pipe_resource template;
-
- /* Free the old surface and texture
- */
- pipe_surface_reference( &strb->surface, NULL );
- pipe_resource_reference( &strb->texture, NULL );
- pipe_sampler_view_reference(&strb->sampler_view, NULL);
-
- /* Setup new texture template.
- */
- memset(&template, 0, sizeof(template));
- template.target = st->internal_target;
- template.format = format;
- template.width0 = width;
- template.height0 = height;
- template.depth0 = 1;
- template.array_size = 1;
- template.last_level = 0;
- template.nr_samples = rb->NumSamples;
- if (util_format_is_depth_or_stencil(format)) {
- template.bind = PIPE_BIND_DEPTH_STENCIL;
- }
- else {
- template.bind = (PIPE_BIND_DISPLAY_TARGET |
- PIPE_BIND_RENDER_TARGET);
- }
-
- strb->texture = screen->resource_create(screen, &template);
-
- if (!strb->texture)
- return FALSE;
-
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
- strb->surface = pipe->create_surface(pipe,
- strb->texture,
- &surf_tmpl);
- if (strb->surface) {
- assert(strb->surface->texture);
- assert(strb->surface->format);
- assert(strb->surface->width == width);
- assert(strb->surface->height == height);
- }
-
- return strb->surface != NULL;
- }
-}
-
-
-/**
- * gl_renderbuffer::Delete()
- */
-static void
-st_renderbuffer_delete(struct gl_renderbuffer *rb)
-{
- struct st_renderbuffer *strb = st_renderbuffer(rb);
- ASSERT(strb);
- pipe_surface_reference(&strb->surface, NULL);
- pipe_resource_reference(&strb->texture, NULL);
- pipe_sampler_view_reference(&strb->sampler_view, NULL);
- free(strb->data);
- free(strb);
-}
-
-
-/**
- * gl_renderbuffer::GetPointer()
- */
-static void *
-null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
- GLint x, GLint y)
-{
- /* By returning NULL we force all software rendering to go through
- * the span routines.
- */
-#if 0
- assert(0); /* Should never get called with softpipe */
-#endif
- return NULL;
-}
-
-
-/**
- * Called via ctx->Driver.NewFramebuffer()
- */
-static struct gl_framebuffer *
-st_new_framebuffer(struct gl_context *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(struct gl_context *ctx, GLuint name)
-{
- struct st_renderbuffer *strb = ST_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;
- strb->format = PIPE_FORMAT_NONE;
- return &strb->Base;
- }
- return NULL;
-}
-
-
-/**
- * Allocate a renderbuffer for a an on-screen window (not a user-created
- * renderbuffer). The window system code determines the format.
- */
-struct gl_renderbuffer *
-st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
-{
- struct st_renderbuffer *strb;
-
- strb = ST_CALLOC_STRUCT(st_renderbuffer);
- if (!strb) {
- _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
- return NULL;
- }
-
- _mesa_init_renderbuffer(&strb->Base, 0);
- strb->Base.ClassID = 0x4242; /* just a unique value */
- strb->Base.NumSamples = samples;
- strb->Base.Format = st_pipe_format_to_mesa_format(format);
- strb->Base.DataType = st_format_datatype(format);
- strb->format = format;
- strb->software = sw;
-
- switch (format) {
- case PIPE_FORMAT_R8G8B8A8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_R8G8B8X8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_B5G5R5A1_UNORM:
- case PIPE_FORMAT_B4G4R4A4_UNORM:
- case PIPE_FORMAT_B5G6R5_UNORM:
- strb->Base.InternalFormat = GL_RGBA;
- break;
- case PIPE_FORMAT_Z16_UNORM:
- strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
- break;
- case PIPE_FORMAT_Z32_UNORM:
- strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
- break;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_Z24X8_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
- strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
- break;
- case PIPE_FORMAT_S8_USCALED:
- strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
- break;
- case PIPE_FORMAT_R16G16B16A16_SNORM:
- strb->Base.InternalFormat = GL_RGBA16;
- break;
- case PIPE_FORMAT_R8_UNORM:
- strb->Base.InternalFormat = GL_R8;
- break;
- case PIPE_FORMAT_R8G8_UNORM:
- strb->Base.InternalFormat = GL_RG8;
- break;
- case PIPE_FORMAT_R16_UNORM:
- strb->Base.InternalFormat = GL_R16;
- break;
- case PIPE_FORMAT_R16G16_UNORM:
- strb->Base.InternalFormat = GL_RG16;
- break;
- default:
- _mesa_problem(NULL,
- "Unexpected format in st_new_renderbuffer_fb");
- free(strb);
- return NULL;
- }
-
- /* st-specific methods */
- strb->Base.Delete = st_renderbuffer_delete;
- strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
- strb->Base.GetPointer = null_get_pointer;
-
- /* surface is allocated in st_renderbuffer_alloc_storage() */
- strb->surface = NULL;
-
- return &strb->Base;
-}
-
-
-
-
-/**
- * Called via ctx->Driver.BindFramebufferEXT().
- */
-static void
-st_bind_framebuffer(struct gl_context *ctx, GLenum target,
- struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
-{
-
-}
-
-/**
- * Called by ctx->Driver.FramebufferRenderbuffer
- */
-static void
-st_framebuffer_renderbuffer(struct gl_context *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(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- struct gl_renderbuffer_attachment *att)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct st_renderbuffer *strb;
- struct gl_renderbuffer *rb;
- struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
- struct st_texture_object *stObj;
- const struct gl_texture_image *texImage;
- struct pipe_surface surf_tmpl;
-
- /* When would this fail? Perhaps assert? */
- if (!pt)
- return;
-
- /* get pointer to texture image we're rendeing to */
- texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
-
- /* create new renderbuffer which wraps the texture image */
- rb = st_new_renderbuffer(ctx, 0);
- if (!rb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
- return;
- }
-
- _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
- assert(rb->RefCount == 1);
- rb->AllocStorage = NULL; /* should not get called */
- strb = st_renderbuffer(rb);
-
- assert(strb->Base.RefCount > 0);
-
- /* get the texture for the texture object */
- stObj = st_texture_object(att->Texture);
-
- /* point renderbuffer at texobject */
- strb->rtt = stObj;
- strb->rtt_level = att->TextureLevel;
- strb->rtt_face = att->CubeMapFace;
- strb->rtt_slice = att->Zoffset;
-
- rb->Width = texImage->Width2;
- rb->Height = texImage->Height2;
- rb->_BaseFormat = texImage->_BaseFormat;
- /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
-
- /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/
-
- pipe_resource_reference( &strb->texture, pt );
-
- pipe_surface_reference(&strb->surface, NULL);
-
- pipe_sampler_view_reference(&strb->sampler_view,
- st_get_texture_sampler_view(stObj, pipe));
-
- assert(strb->rtt_level <= strb->texture->last_level);
-
- /* new surface for rendering into the texture */
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- surf_tmpl.format = util_format_linear(strb->texture->format);
- surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
- surf_tmpl.u.tex.level = strb->rtt_level;
- surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
- surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
- strb->surface = pipe->create_surface(pipe,
- strb->texture,
- &surf_tmpl);
-
- strb->format = pt->format;
-
- strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
- strb->Base.DataType = st_format_datatype(pt->format);
-
- /*
- printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p %d x %d\n",
- att->Texture, pt, strb->surface, rb->Width, rb->Height);
- */
-
- /* Invalidate buffer state so that the pipe's framebuffer state
- * gets updated.
- * That's where the new renderbuffer (which we just created) gets
- * passed to the pipe as a (color/depth) render target.
- */
- st_invalidate_state(ctx, _NEW_BUFFERS);
-}
-
-
-/**
- * Called via ctx->Driver.FinishRenderTexture.
- */
-static void
-st_finish_render_texture(struct gl_context *ctx,
- struct gl_renderbuffer_attachment *att)
-{
- struct st_context *st = st_context(ctx);
- struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
-
- if (!strb)
- return;
-
- st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
-
- strb->rtt = NULL;
-
- /*
- printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
- */
-
- /* restore previous framebuffer state */
- st_invalidate_state(ctx, _NEW_BUFFERS);
-}
-
-
-/**
- * Validate a renderbuffer attachment for a particular set of bindings.
- */
-static GLboolean
-st_validate_attachment(struct pipe_screen *screen,
- const struct gl_renderbuffer_attachment *att,
- unsigned bindings)
-{
- const struct st_texture_object *stObj = st_texture_object(att->Texture);
-
- /* Only validate texture attachments for now, since
- * st_renderbuffer_alloc_storage makes sure that
- * the format is supported.
- */
- if (att->Type != GL_TEXTURE)
- return GL_TRUE;
-
- if (!stObj)
- return GL_FALSE;
-
- return screen->is_format_supported(screen, stObj->pt->format,
- PIPE_TEXTURE_2D,
- stObj->pt->nr_samples, bindings, 0);
-}
-
-
-/**
- * Check if two renderbuffer attachments name a combined depth/stencil
- * renderbuffer.
- */
-GLboolean
-st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
- const struct gl_renderbuffer_attachment *stencil)
-{
- assert(depth && stencil);
-
- if (depth->Type == stencil->Type) {
- if (depth->Type == GL_RENDERBUFFER_EXT &&
- depth->Renderbuffer == stencil->Renderbuffer)
- return GL_TRUE;
-
- if (depth->Type == GL_TEXTURE &&
- depth->Texture == stencil->Texture)
- return GL_TRUE;
- }
-
- return GL_FALSE;
-}
-
-
-/**
- * Check that the framebuffer configuration is valid in terms of what
- * the driver can support.
- *
- * For Gallium we only supports combined Z+stencil, not separate buffers.
- */
-static void
-st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_screen *screen = st->pipe->screen;
- const struct gl_renderbuffer_attachment *depth =
- &fb->Attachment[BUFFER_DEPTH];
- const struct gl_renderbuffer_attachment *stencil =
- &fb->Attachment[BUFFER_STENCIL];
- GLuint i;
-
- if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- if (depth->Type == GL_RENDERBUFFER_EXT &&
- stencil->Type == GL_RENDERBUFFER_EXT &&
- depth->Renderbuffer != stencil->Renderbuffer) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- if (depth->Type == GL_TEXTURE &&
- stencil->Type == GL_TEXTURE &&
- depth->Texture != stencil->Texture) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
-
- if (!st_validate_attachment(screen,
- depth,
- PIPE_BIND_DEPTH_STENCIL)) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- if (!st_validate_attachment(screen,
- stencil,
- PIPE_BIND_DEPTH_STENCIL)) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
- if (!st_validate_attachment(screen,
- &fb->Attachment[BUFFER_COLOR0 + i],
- PIPE_BIND_RENDER_TARGET)) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- }
-}
-
-
-/**
- * Called via glDrawBuffer.
- */
-static void
-st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
-{
- struct st_context *st = st_context(ctx);
- struct gl_framebuffer *fb = ctx->DrawBuffer;
- GLuint i;
-
- (void) count;
- (void) buffers;
-
- /* add the renderbuffers on demand */
- for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
- gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
- st_manager_add_color_renderbuffer(st, fb, idx);
- }
-}
-
-
-/**
- * Called via glReadBuffer.
- */
-static void
-st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
-{
- struct st_context *st = st_context(ctx);
- struct gl_framebuffer *fb = ctx->ReadBuffer;
-
- (void) buffer;
-
- /* add the renderbuffer on demand */
- st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
-}
-
-
-void st_init_fbo_functions(struct dd_function_table *functions)
-{
-#if FEATURE_EXT_framebuffer_object
- 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;
- functions->ValidateFramebuffer = st_validate_framebuffer;
-#endif
- /* no longer needed by core Mesa, drivers handle resizes...
- functions->ResizeBuffers = st_resize_buffers;
- */
-
- functions->DrawBuffers = st_DrawBuffers;
- functions->ReadBuffer = st_ReadBuffer;
-}
-
-/* XXX unused ? */
-struct pipe_sampler_view *
-st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
- struct pipe_context *pipe)
-{
- if (!rb->sampler_view) {
- rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture);
- }
-
- return rb->sampler_view;
-}
+/************************************************************************** + * + * 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/macros.h" +#include "main/mfeatures.h" +#include "main/renderbuffer.h" + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "st_context.h" +#include "st_cb_fbo.h" +#include "st_cb_flush.h" +#include "st_format.h" +#include "st_texture.h" +#include "st_manager.h" + +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_surface.h" + + +/** + * gl_renderbuffer::AllocStorage() + * This is called to allocate the original drawing surface, and + * during window resize. + */ +static GLboolean +st_renderbuffer_alloc_storage(struct gl_context * ctx, + struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = st->pipe->screen; + struct st_renderbuffer *strb = st_renderbuffer(rb); + enum pipe_format format; + struct pipe_surface surf_tmpl; + + if (strb->format != PIPE_FORMAT_NONE) + format = strb->format; + else + format = st_choose_renderbuffer_format(screen, internalFormat, + rb->NumSamples); + + /* init renderbuffer fields */ + strb->Base.Width = width; + strb->Base.Height = height; + strb->Base.Format = st_pipe_format_to_mesa_format(format); + strb->Base.DataType = st_format_datatype(format); + + strb->defined = GL_FALSE; /* undefined contents now */ + + if (strb->software) { + size_t size; + + free(strb->data); + + assert(strb->format != PIPE_FORMAT_NONE); + + strb->stride = util_format_get_stride(strb->format, width); + size = util_format_get_2d_size(strb->format, strb->stride, height); + + strb->data = malloc(size); + + return strb->data != NULL; + } + else { + struct pipe_resource template; + + /* Free the old surface and texture + */ + pipe_surface_reference( &strb->surface, NULL ); + pipe_resource_reference( &strb->texture, NULL ); + pipe_sampler_view_reference(&strb->sampler_view, NULL); + + /* Setup new texture template. + */ + memset(&template, 0, sizeof(template)); + template.target = st->internal_target; + template.format = format; + template.width0 = width; + template.height0 = height; + template.depth0 = 1; + template.array_size = 1; + template.last_level = 0; + template.nr_samples = rb->NumSamples; + if (util_format_is_depth_or_stencil(format)) { + template.bind = PIPE_BIND_DEPTH_STENCIL; + } + else { + template.bind = (PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_RENDER_TARGET); + } + + strb->texture = screen->resource_create(screen, &template); + + if (!strb->texture) + return FALSE; + + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + u_surface_default_template(&surf_tmpl, strb->texture, template.bind); + strb->surface = pipe->create_surface(pipe, + strb->texture, + &surf_tmpl); + if (strb->surface) { + assert(strb->surface->texture); + assert(strb->surface->format); + assert(strb->surface->width == width); + assert(strb->surface->height == height); + } + + return strb->surface != NULL; + } +} + + +/** + * gl_renderbuffer::Delete() + */ +static void +st_renderbuffer_delete(struct gl_renderbuffer *rb) +{ + struct st_renderbuffer *strb = st_renderbuffer(rb); + ASSERT(strb); + pipe_surface_reference(&strb->surface, NULL); + pipe_resource_reference(&strb->texture, NULL); + pipe_sampler_view_reference(&strb->sampler_view, NULL); + free(strb->data); + free(strb); +} + + +/** + * gl_renderbuffer::GetPointer() + */ +static void * +null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb, + GLint x, GLint y) +{ + /* By returning NULL we force all software rendering to go through + * the span routines. + */ +#if 0 + assert(0); /* Should never get called with softpipe */ +#endif + return NULL; +} + + +/** + * Called via ctx->Driver.NewFramebuffer() + */ +static struct gl_framebuffer * +st_new_framebuffer(struct gl_context *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(struct gl_context *ctx, GLuint name) +{ + struct st_renderbuffer *strb = ST_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; + strb->format = PIPE_FORMAT_NONE; + return &strb->Base; + } + return NULL; +} + + +/** + * Allocate a renderbuffer for a an on-screen window (not a user-created + * renderbuffer). The window system code determines the format. + */ +struct gl_renderbuffer * +st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) +{ + struct st_renderbuffer *strb; + + strb = ST_CALLOC_STRUCT(st_renderbuffer); + if (!strb) { + _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); + return NULL; + } + + _mesa_init_renderbuffer(&strb->Base, 0); + strb->Base.ClassID = 0x4242; /* just a unique value */ + strb->Base.NumSamples = samples; + strb->Base.Format = st_pipe_format_to_mesa_format(format); + strb->Base.DataType = st_format_datatype(format); + strb->format = format; + strb->software = sw; + + switch (format) { + case PIPE_FORMAT_R8G8B8A8_UNORM: + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8X8_UNORM: + case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_X8R8G8B8_UNORM: + case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B4G4R4A4_UNORM: + case PIPE_FORMAT_B5G6R5_UNORM: + strb->Base.InternalFormat = GL_RGBA; + break; + case PIPE_FORMAT_Z16_UNORM: + strb->Base.InternalFormat = GL_DEPTH_COMPONENT16; + break; + case PIPE_FORMAT_Z32_UNORM: + strb->Base.InternalFormat = GL_DEPTH_COMPONENT32; + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT; + break; + case PIPE_FORMAT_S8_USCALED: + strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT; + break; + case PIPE_FORMAT_R16G16B16A16_SNORM: + strb->Base.InternalFormat = GL_RGBA16; + break; + case PIPE_FORMAT_R8_UNORM: + strb->Base.InternalFormat = GL_R8; + break; + case PIPE_FORMAT_R8G8_UNORM: + strb->Base.InternalFormat = GL_RG8; + break; + case PIPE_FORMAT_R16_UNORM: + strb->Base.InternalFormat = GL_R16; + break; + case PIPE_FORMAT_R16G16_UNORM: + strb->Base.InternalFormat = GL_RG16; + break; + default: + _mesa_problem(NULL, + "Unexpected format in st_new_renderbuffer_fb"); + free(strb); + return NULL; + } + + /* st-specific methods */ + strb->Base.Delete = st_renderbuffer_delete; + strb->Base.AllocStorage = st_renderbuffer_alloc_storage; + strb->Base.GetPointer = null_get_pointer; + + /* surface is allocated in st_renderbuffer_alloc_storage() */ + strb->surface = NULL; + + return &strb->Base; +} + + + + +/** + * Called via ctx->Driver.BindFramebufferEXT(). + */ +static void +st_bind_framebuffer(struct gl_context *ctx, GLenum target, + struct gl_framebuffer *fb, struct gl_framebuffer *fbread) +{ + +} + +/** + * Called by ctx->Driver.FramebufferRenderbuffer + */ +static void +st_framebuffer_renderbuffer(struct gl_context *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(struct gl_context *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct st_renderbuffer *strb; + struct gl_renderbuffer *rb; + struct pipe_resource *pt = st_get_texobj_resource(att->Texture); + struct st_texture_object *stObj; + const struct gl_texture_image *texImage; + struct pipe_surface surf_tmpl; + + /* When would this fail? Perhaps assert? */ + if (!pt) + return; + + /* get pointer to texture image we're rendeing to */ + texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; + + /* create new renderbuffer which wraps the texture image */ + rb = st_new_renderbuffer(ctx, 0); + if (!rb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()"); + return; + } + + _mesa_reference_renderbuffer(&att->Renderbuffer, rb); + assert(rb->RefCount == 1); + rb->AllocStorage = NULL; /* should not get called */ + strb = st_renderbuffer(rb); + + assert(strb->Base.RefCount > 0); + + /* get the texture for the texture object */ + stObj = st_texture_object(att->Texture); + + /* point renderbuffer at texobject */ + strb->rtt = stObj; + strb->rtt_level = att->TextureLevel; + strb->rtt_face = att->CubeMapFace; + strb->rtt_slice = att->Zoffset; + + rb->Width = texImage->Width2; + rb->Height = texImage->Height2; + rb->_BaseFormat = texImage->_BaseFormat; + /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/ + + /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/ + + pipe_resource_reference( &strb->texture, pt ); + + pipe_surface_reference(&strb->surface, NULL); + + pipe_sampler_view_reference(&strb->sampler_view, + st_get_texture_sampler_view(stObj, pipe)); + + assert(strb->rtt_level <= strb->texture->last_level); + + /* new surface for rendering into the texture */ + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); + surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; + surf_tmpl.u.tex.level = strb->rtt_level; + surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; + surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; + strb->surface = pipe->create_surface(pipe, + strb->texture, + &surf_tmpl); + + strb->format = pt->format; + + strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); + strb->Base.DataType = st_format_datatype(pt->format); + + /* + printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p %d x %d\n", + att->Texture, pt, strb->surface, rb->Width, rb->Height); + */ + + /* Invalidate buffer state so that the pipe's framebuffer state + * gets updated. + * That's where the new renderbuffer (which we just created) gets + * passed to the pipe as a (color/depth) render target. + */ + st_invalidate_state(ctx, _NEW_BUFFERS); +} + + +/** + * Called via ctx->Driver.FinishRenderTexture. + */ +static void +st_finish_render_texture(struct gl_context *ctx, + struct gl_renderbuffer_attachment *att) +{ + struct st_context *st = st_context(ctx); + struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer); + + if (!strb) + return; + + st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL); + + strb->rtt = NULL; + + /* + printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface); + */ + + /* restore previous framebuffer state */ + st_invalidate_state(ctx, _NEW_BUFFERS); +} + + +/** + * Validate a renderbuffer attachment for a particular set of bindings. + */ +static GLboolean +st_validate_attachment(struct pipe_screen *screen, + const struct gl_renderbuffer_attachment *att, + unsigned bindings) +{ + const struct st_texture_object *stObj = st_texture_object(att->Texture); + + /* Only validate texture attachments for now, since + * st_renderbuffer_alloc_storage makes sure that + * the format is supported. + */ + if (att->Type != GL_TEXTURE) + return GL_TRUE; + + if (!stObj) + return GL_FALSE; + + return screen->is_format_supported(screen, stObj->pt->format, + PIPE_TEXTURE_2D, + stObj->pt->nr_samples, bindings, 0); +} + + +/** + * Check if two renderbuffer attachments name a combined depth/stencil + * renderbuffer. + */ +GLboolean +st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth, + const struct gl_renderbuffer_attachment *stencil) +{ + assert(depth && stencil); + + if (depth->Type == stencil->Type) { + if (depth->Type == GL_RENDERBUFFER_EXT && + depth->Renderbuffer == stencil->Renderbuffer) + return GL_TRUE; + + if (depth->Type == GL_TEXTURE && + depth->Texture == stencil->Texture) + return GL_TRUE; + } + + return GL_FALSE; +} + + +/** + * Check that the framebuffer configuration is valid in terms of what + * the driver can support. + * + * For Gallium we only supports combined Z+stencil, not separate buffers. + */ +static void +st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + struct st_context *st = st_context(ctx); + struct pipe_screen *screen = st->pipe->screen; + const struct gl_renderbuffer_attachment *depth = + &fb->Attachment[BUFFER_DEPTH]; + const struct gl_renderbuffer_attachment *stencil = + &fb->Attachment[BUFFER_STENCIL]; + GLuint i; + + if (depth->Type && stencil->Type && depth->Type != stencil->Type) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + if (depth->Type == GL_RENDERBUFFER_EXT && + stencil->Type == GL_RENDERBUFFER_EXT && + depth->Renderbuffer != stencil->Renderbuffer) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + if (depth->Type == GL_TEXTURE && + stencil->Type == GL_TEXTURE && + depth->Texture != stencil->Texture) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + + if (!st_validate_attachment(screen, + depth, + PIPE_BIND_DEPTH_STENCIL)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + if (!st_validate_attachment(screen, + stencil, + PIPE_BIND_DEPTH_STENCIL)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { + if (!st_validate_attachment(screen, + &fb->Attachment[BUFFER_COLOR0 + i], + PIPE_BIND_RENDER_TARGET)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + } +} + + +/** + * Called via glDrawBuffer. + */ +static void +st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers) +{ + struct st_context *st = st_context(ctx); + struct gl_framebuffer *fb = ctx->DrawBuffer; + GLuint i; + + (void) count; + (void) buffers; + + /* add the renderbuffers on demand */ + for (i = 0; i < fb->_NumColorDrawBuffers; i++) { + gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i]; + st_manager_add_color_renderbuffer(st, fb, idx); + } +} + + +/** + * Called via glReadBuffer. + */ +static void +st_ReadBuffer(struct gl_context *ctx, GLenum buffer) +{ + struct st_context *st = st_context(ctx); + struct gl_framebuffer *fb = ctx->ReadBuffer; + + (void) buffer; + + /* add the renderbuffer on demand */ + st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex); +} + + +void st_init_fbo_functions(struct dd_function_table *functions) +{ +#if FEATURE_EXT_framebuffer_object + 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; + functions->ValidateFramebuffer = st_validate_framebuffer; +#endif + /* no longer needed by core Mesa, drivers handle resizes... + functions->ResizeBuffers = st_resize_buffers; + */ + + functions->DrawBuffers = st_DrawBuffers; + functions->ReadBuffer = st_ReadBuffer; +} + +/* XXX unused ? */ +struct pipe_sampler_view * +st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb, + struct pipe_context *pipe) +{ + if (!rb->sampler_view) { + rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture); + } + + return rb->sampler_view; +} diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c index c11c7696e..545b32d75 100644 --- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c +++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c @@ -220,7 +220,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, break; default: assert(0); - return; + goto out_unref_vertex; } if (bufobj && bufobj->Name) { @@ -256,15 +256,6 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* * unmap vertex/index buffers */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (draw->pt.vertex_buffer[i].buffer) { - pipe_buffer_unmap(pipe, vb_transfer[i]); - pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL); - draw_set_mapped_vertex_buffer(draw, i, NULL); - pipe_resource_reference(&vbuffers[i].buffer, NULL); - } - } - if (ib) { draw_set_mapped_index_buffer(draw, NULL); draw_set_index_buffer(draw, NULL); @@ -273,6 +264,14 @@ st_feedback_draw_vbo(struct gl_context *ctx, pipe_buffer_unmap(pipe, ib_transfer); pipe_resource_reference(&ibuffer.buffer, NULL); } + + out_unref_vertex: + for (attr = 0; attr < vp->num_inputs; attr++) { + pipe_buffer_unmap(pipe, vb_transfer[attr]); + draw_set_mapped_vertex_buffer(draw, attr, NULL); + pipe_resource_reference(&vbuffers[attr].buffer, NULL); + } + draw_set_vertex_buffers(draw, 0, NULL); } #endif /* FEATURE_feedback || FEATURE_rastpos */ diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index a81cbe85d..d600edc48 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -390,6 +390,15 @@ void st_init_extensions(struct st_context *st) PIPE_BIND_SAMPLER_VIEW, 0)) { ctx->Extensions.EXT_texture_sRGB = GL_TRUE; ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE; + if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET, 0) || + screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET, 0)) { + ctx->Extensions.EXT_framebuffer_sRGB = GL_TRUE; + ctx->Const.sRGBCapable = GL_TRUE; + } } if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM, |