mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 22:08:26 +02:00
Merge remote branch 'origin/gallium-st-api'
This commit is contained in:
commit
9d3a873f42
38 changed files with 2807 additions and 798 deletions
407
src/gallium/include/state_tracker/st_api.h
Normal file
407
src/gallium/include/state_tracker/st_api.h
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
/**********************************************************
|
||||
* Copyright 2010 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 "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, 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 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
|
||||
* 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************/
|
||||
|
||||
|
||||
#ifndef _ST_API_H_
|
||||
#define _ST_API_H_
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_format.h"
|
||||
|
||||
/**
|
||||
* \file API for communication between state trackers and state tracker
|
||||
* managers.
|
||||
*
|
||||
* While both are state tackers, we use the term state tracker for rendering
|
||||
* APIs such as OpenGL or OpenVG, and state tracker manager for window system
|
||||
* APIs such as EGL or GLX in this file.
|
||||
*
|
||||
* This file defines an API to be implemented by both state trackers and state
|
||||
* tracker managers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The entry points of the state trackers.
|
||||
*/
|
||||
#define ST_MODULE_OPENGL_SYMBOL "st_module_OpenGL"
|
||||
#define ST_MODULE_OPENGL_ES1_SYMBOL "st_module_OpenGL_ES1"
|
||||
#define ST_MODULE_OPENGL_ES2_SYMBOL "st_module_OpenGL_ES2"
|
||||
#define ST_MODULE_OPENVG_SYMBOL "st_module_OpenVG"
|
||||
|
||||
/**
|
||||
* The supported rendering API of a state tracker.
|
||||
*/
|
||||
enum st_api_type {
|
||||
ST_API_OPENGL,
|
||||
ST_API_OPENGL_ES1,
|
||||
ST_API_OPENGL_ES2,
|
||||
ST_API_OPENVG,
|
||||
|
||||
ST_API_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Used in st_context_iface->teximage.
|
||||
*/
|
||||
enum st_texture_type {
|
||||
ST_TEXTURE_1D,
|
||||
ST_TEXTURE_2D,
|
||||
ST_TEXTURE_3D,
|
||||
ST_TEXTURE_RECT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Available attachments of framebuffer.
|
||||
*/
|
||||
enum st_attachment_type {
|
||||
ST_ATTACHMENT_FRONT_LEFT,
|
||||
ST_ATTACHMENT_BACK_LEFT,
|
||||
ST_ATTACHMENT_FRONT_RIGHT,
|
||||
ST_ATTACHMENT_BACK_RIGHT,
|
||||
ST_ATTACHMENT_DEPTH_STENCIL,
|
||||
ST_ATTACHMENT_ACCUM,
|
||||
ST_ATTACHMENT_SAMPLE,
|
||||
|
||||
ST_ATTACHMENT_COUNT,
|
||||
ST_ATTACHMENT_INVALID = -1
|
||||
};
|
||||
|
||||
/* for buffer_mask in st_visual */
|
||||
#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT)
|
||||
#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT)
|
||||
#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT)
|
||||
#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT)
|
||||
#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL)
|
||||
#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM)
|
||||
#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE)
|
||||
|
||||
/**
|
||||
* Enumerations of state tracker context resources.
|
||||
*/
|
||||
enum st_context_resource_type {
|
||||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D,
|
||||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D,
|
||||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
||||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||
ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER,
|
||||
ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE,
|
||||
};
|
||||
|
||||
/**
|
||||
* The return type of st_api->get_proc_address.
|
||||
*/
|
||||
typedef void (*st_proc_t)(void);
|
||||
|
||||
struct pipe_context;
|
||||
struct pipe_texture;
|
||||
struct pipe_fence_handle;
|
||||
|
||||
/**
|
||||
* Used in st_context_iface->get_resource_for_egl_image.
|
||||
*/
|
||||
struct st_context_resource
|
||||
{
|
||||
/* these fields are filled by the caller */
|
||||
enum st_context_resource_type type;
|
||||
void *resource;
|
||||
|
||||
/* this is owned by the caller */
|
||||
struct pipe_texture *texture;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used in st_manager_iface->get_egl_image.
|
||||
*/
|
||||
struct st_egl_image
|
||||
{
|
||||
/* these fields are filled by the caller */
|
||||
struct st_context_iface *stctxi;
|
||||
void *egl_image;
|
||||
|
||||
/* this is owned by the caller */
|
||||
struct pipe_texture *texture;
|
||||
|
||||
unsigned face;
|
||||
unsigned level;
|
||||
unsigned zslice;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represent the visual of a framebuffer.
|
||||
*/
|
||||
struct st_visual
|
||||
{
|
||||
/**
|
||||
* Available buffers. Tested with ST_FRAMEBUFFER_*_MASK.
|
||||
*/
|
||||
unsigned buffer_mask;
|
||||
|
||||
/**
|
||||
* Buffer formats. The formats are always set even when the buffer is
|
||||
* not available.
|
||||
*/
|
||||
enum pipe_format color_format;
|
||||
enum pipe_format depth_stencil_format;
|
||||
enum pipe_format accum_format;
|
||||
int samples;
|
||||
|
||||
/**
|
||||
* Desired render buffer.
|
||||
*/
|
||||
enum st_attachment_type render_buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represent a windowing system drawable.
|
||||
*
|
||||
* The framebuffer is implemented by the state tracker manager and
|
||||
* used by the state trackers.
|
||||
*
|
||||
* Instead of the winsys pokeing into the API context to figure
|
||||
* out what buffers that might be needed in the future by the API
|
||||
* context, it calls into the framebuffer to get the textures.
|
||||
*
|
||||
* This structure along with the notify_invalid_framebuffer
|
||||
* allows framebuffers to be shared between different threads
|
||||
* but at the same make the API context free from thread
|
||||
* syncronisation primitves, with the exception of a small
|
||||
* atomic flag used for notification of framebuffer dirty status.
|
||||
*
|
||||
* The thread syncronisation is put inside the framebuffer
|
||||
* and only called once the framebuffer has become dirty.
|
||||
*/
|
||||
struct st_framebuffer_iface
|
||||
{
|
||||
/**
|
||||
* Available for the state tracker manager to use.
|
||||
*/
|
||||
void *st_manager_private;
|
||||
|
||||
/**
|
||||
* The visual of a framebuffer.
|
||||
*/
|
||||
const struct st_visual *visual;
|
||||
|
||||
/**
|
||||
* Flush the front buffer.
|
||||
*
|
||||
* On some window systems, changes to the front buffers are not immediately
|
||||
* visible. They need to be flushed.
|
||||
*
|
||||
* @att is one of the front buffer attachments.
|
||||
*/
|
||||
boolean (*flush_front)(struct st_framebuffer_iface *stfbi,
|
||||
enum st_attachment_type statt);
|
||||
|
||||
/**
|
||||
* The state tracker asks for the textures it needs.
|
||||
*
|
||||
* It should try to only ask for attachments that it currently renders
|
||||
* to, thus allowing the winsys to delay the allocation of textures not
|
||||
* needed. For example front buffer attachments are not needed if you
|
||||
* only do back buffer rendering.
|
||||
*
|
||||
* The implementor of this function needs to also ensure
|
||||
* thread safty as this call might be done from multiple threads.
|
||||
*
|
||||
* The returned textures are owned by the caller. They should be
|
||||
* unreferenced when no longer used. If this function is called multiple
|
||||
* times with different sets of attachments, those buffers not included in
|
||||
* the last call might be destroyed. This behavior might change in the
|
||||
* future.
|
||||
*/
|
||||
boolean (*validate)(struct st_framebuffer_iface *stfbi,
|
||||
const enum st_attachment_type *statts,
|
||||
unsigned count,
|
||||
struct pipe_texture **out);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represent a rendering context.
|
||||
*
|
||||
* This entity is created from st_api and used by the state tracker manager.
|
||||
*/
|
||||
struct st_context_iface
|
||||
{
|
||||
/**
|
||||
* Available for the state tracker and the manager to use.
|
||||
*/
|
||||
void *st_context_private;
|
||||
void *st_manager_private;
|
||||
|
||||
/**
|
||||
* Destroy the context.
|
||||
*/
|
||||
void (*destroy)(struct st_context_iface *stctxi);
|
||||
|
||||
/**
|
||||
* Invalidate the current textures that was taken from a framebuffer.
|
||||
*
|
||||
* The state tracker manager calls this function to let the rendering
|
||||
* context know that it should update the textures it got from
|
||||
* st_framebuffer_iface::validate. It should do so at the latest time possible.
|
||||
* Possible right before sending triangles to the pipe context.
|
||||
*
|
||||
* For certain platforms this function might be called from a thread other
|
||||
* than the thread that the context is currently bound in, and must
|
||||
* therefore be thread safe. But it is the state tracker manager's
|
||||
* responsibility to make sure that the framebuffer is bound to the context
|
||||
* and the API context is current for the duration of this call.
|
||||
*
|
||||
* Thus reducing the sync primitive needed to a single atomic flag.
|
||||
*/
|
||||
void (*notify_invalid_framebuffer)(struct st_context_iface *stctxi,
|
||||
struct st_framebuffer_iface *stfbi);
|
||||
|
||||
/**
|
||||
* Flush all drawing from context to the pipe also flushes the pipe.
|
||||
*/
|
||||
void (*flush)(struct st_context_iface *stctxi, unsigned flags,
|
||||
struct pipe_fence_handle **fence);
|
||||
|
||||
/**
|
||||
* Replace the texture image of a texture object at the specified level.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
boolean (*teximage)(struct st_context_iface *stctxi, enum st_texture_type target,
|
||||
int level, enum pipe_format internal_format,
|
||||
struct pipe_texture *tex, boolean mipmap);
|
||||
|
||||
/**
|
||||
* Used to implement glXCopyContext.
|
||||
*/
|
||||
void (*copy)(struct st_context_iface *stctxi,
|
||||
struct st_context_iface *stsrci, unsigned mask);
|
||||
|
||||
/**
|
||||
* Look up and return the info of a resource for EGLImage.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
boolean (*get_resource_for_egl_image)(struct st_context_iface *stctxi,
|
||||
struct st_context_resource *stres);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Represent a state tracker manager.
|
||||
*
|
||||
* This interface is implemented by the state tracker manager. It corresponds
|
||||
* to a "display" in the window system.
|
||||
*/
|
||||
struct st_manager
|
||||
{
|
||||
struct pipe_screen *screen;
|
||||
|
||||
/**
|
||||
* Look up and return the info of an EGLImage.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
boolean (*get_egl_image)(struct st_manager *smapi,
|
||||
struct st_egl_image *stimg);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represent a rendering API such as OpenGL or OpenVG.
|
||||
*
|
||||
* Implemented by the state tracker and used by the state tracker manager.
|
||||
*/
|
||||
struct st_api
|
||||
{
|
||||
/**
|
||||
* Destroy the API.
|
||||
*/
|
||||
void (*destroy)(struct st_api *stapi);
|
||||
|
||||
/**
|
||||
* Return an API entry point.
|
||||
*
|
||||
* For GL this is the same as _glapi_get_proc_address.
|
||||
*/
|
||||
st_proc_t (*get_proc_address)(struct st_api *stapi, const char *procname);
|
||||
|
||||
/**
|
||||
* Return true if the visual is supported by the state tracker.
|
||||
*/
|
||||
boolean (*is_visual_supported)(struct st_api *stapi,
|
||||
const struct st_visual *visual);
|
||||
|
||||
/**
|
||||
* Create a rendering context.
|
||||
*/
|
||||
struct st_context_iface *(*create_context)(struct st_api *stapi,
|
||||
struct st_manager *smapi,
|
||||
const struct st_visual *visual,
|
||||
struct st_context_iface *stsharei);
|
||||
|
||||
/**
|
||||
* Bind the context to the calling thread with draw and read as drawables.
|
||||
*
|
||||
* The framebuffers might have different visuals than the context does.
|
||||
*/
|
||||
boolean (*make_current)(struct st_api *stapi,
|
||||
struct st_context_iface *stctxi,
|
||||
struct st_framebuffer_iface *stdrawi,
|
||||
struct st_framebuffer_iface *streadi);
|
||||
|
||||
/**
|
||||
* Get the currently bound context in the calling thread.
|
||||
*/
|
||||
struct st_context_iface *(*get_current)(struct st_api *stapi);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represent a state tracker.
|
||||
*
|
||||
* This is the entry point of a state tracker.
|
||||
*/
|
||||
struct st_module
|
||||
{
|
||||
enum st_api_type api;
|
||||
struct st_api *(*create_api)(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if the visual has the specified buffers.
|
||||
*/
|
||||
static INLINE boolean
|
||||
st_visual_have_buffers(const struct st_visual *visual, unsigned mask)
|
||||
{
|
||||
return ((visual->buffer_mask & mask) == mask);
|
||||
}
|
||||
|
||||
/* these symbols may need to be dynamically lookup up */
|
||||
extern PUBLIC const struct st_module st_module_OpenGL;
|
||||
extern PUBLIC const struct st_module st_module_OpenGL_ES1;
|
||||
extern PUBLIC const struct st_module st_module_OpenGL_ES2;
|
||||
extern PUBLIC const struct st_module st_module_OpenVG;
|
||||
|
||||
#endif /* _ST_API_H_ */
|
||||
|
|
@ -35,7 +35,6 @@
|
|||
#include "state_tracker/drm_api.h"
|
||||
#include "state_tracker/dri1_api.h"
|
||||
#include "state_tracker/st_public.h"
|
||||
#include "state_tracker/st_context.h"
|
||||
#include "pipe/p_context.h"
|
||||
|
||||
#include "dri_context.h"
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@
|
|||
#include "main/renderbuffer.h"
|
||||
#include "state_tracker/drm_api.h"
|
||||
#include "state_tracker/dri1_api.h"
|
||||
#include "state_tracker/st_public.h"
|
||||
#include "state_tracker/st_context.h"
|
||||
#include "state_tracker/st_public.h"
|
||||
#include "state_tracker/st_cb_fbo.h"
|
||||
|
||||
#include "util/u_format.h"
|
||||
|
|
|
|||
|
|
@ -36,234 +36,27 @@
|
|||
|
||||
#include "native.h"
|
||||
#include "egl_g3d.h"
|
||||
#include "egl_g3d_st.h"
|
||||
#include "egl_g3d_image.h"
|
||||
#include "egl_st.h"
|
||||
|
||||
/**
|
||||
* Validate the draw/read surfaces of the context.
|
||||
*/
|
||||
static void
|
||||
egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
||||
{
|
||||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||
struct pipe_screen *screen = gdpy->native->screen;
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
|
||||
ST_SURFACE_FRONT_LEFT,
|
||||
ST_SURFACE_BACK_LEFT,
|
||||
ST_SURFACE_FRONT_RIGHT,
|
||||
ST_SURFACE_BACK_RIGHT,
|
||||
};
|
||||
EGLint num_surfaces, s;
|
||||
|
||||
/* validate draw and/or read buffers */
|
||||
num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
|
||||
for (s = 0; s < num_surfaces; s++) {
|
||||
struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
|
||||
struct egl_g3d_surface *gsurf;
|
||||
struct egl_g3d_buffer *gbuf;
|
||||
EGLint att;
|
||||
|
||||
if (s == 0) {
|
||||
gsurf = egl_g3d_surface(gctx->base.DrawSurface);
|
||||
gbuf = &gctx->draw;
|
||||
}
|
||||
else {
|
||||
gsurf = egl_g3d_surface(gctx->base.ReadSurface);
|
||||
gbuf = &gctx->read;
|
||||
}
|
||||
|
||||
if (!gctx->force_validate) {
|
||||
unsigned int seq_num;
|
||||
|
||||
gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
|
||||
&seq_num, NULL, NULL, NULL);
|
||||
/* skip validation */
|
||||
if (gsurf->sequence_number == seq_num)
|
||||
continue;
|
||||
}
|
||||
|
||||
pipe_surface_reference(&gsurf->render_surface, NULL);
|
||||
memset(textures, 0, sizeof(textures));
|
||||
|
||||
gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
|
||||
&gsurf->sequence_number, textures,
|
||||
&gsurf->base.Width, &gsurf->base.Height);
|
||||
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
|
||||
struct pipe_texture *pt = textures[att];
|
||||
struct pipe_surface *ps;
|
||||
|
||||
if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) {
|
||||
ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
|
||||
PIPE_BUFFER_USAGE_GPU_READ |
|
||||
PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||
gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
|
||||
st_att_map[att], ps);
|
||||
|
||||
if (gsurf->render_att == att)
|
||||
pipe_surface_reference(&gsurf->render_surface, ps);
|
||||
|
||||
pipe_surface_reference(&ps, NULL);
|
||||
pipe_texture_reference(&pt, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gctx->stapi->st_resize_framebuffer(gbuf->st_fb,
|
||||
gsurf->base.Width, gsurf->base.Height);
|
||||
}
|
||||
|
||||
gctx->force_validate = EGL_FALSE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a st_framebuffer.
|
||||
*/
|
||||
static struct st_framebuffer *
|
||||
create_framebuffer(_EGLContext *ctx, _EGLSurface *surf)
|
||||
{
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||
struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
|
||||
|
||||
return gctx->stapi->st_create_framebuffer(&gconf->native->mode,
|
||||
gconf->native->color_format, gconf->native->depth_format,
|
||||
gconf->native->stencil_format,
|
||||
gsurf->base.Width, gsurf->base.Height, &gsurf->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the attachments of draw/read surfaces.
|
||||
*/
|
||||
static void
|
||||
egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
||||
{
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
EGLint s;
|
||||
|
||||
/* route draw and read buffers' attachments */
|
||||
for (s = 0; s < 2; s++) {
|
||||
struct egl_g3d_surface *gsurf;
|
||||
struct egl_g3d_buffer *gbuf;
|
||||
|
||||
if (s == 0) {
|
||||
gsurf = egl_g3d_surface(gctx->base.DrawSurface);
|
||||
gbuf = &gctx->draw;
|
||||
}
|
||||
else {
|
||||
gsurf = egl_g3d_surface(gctx->base.ReadSurface);
|
||||
gbuf = &gctx->read;
|
||||
}
|
||||
|
||||
gbuf->attachment_mask = (1 << gsurf->render_att);
|
||||
|
||||
/* FIXME OpenGL defaults to draw the front or back buffer when the
|
||||
* context is single-buffered or double-buffered respectively. In EGL,
|
||||
* however, the buffer to be drawn is determined by the surface, instead
|
||||
* of the context. As a result, rendering to a pixmap surface with a
|
||||
* double-buffered context does not work as expected.
|
||||
*
|
||||
* gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
|
||||
* NATIVE_ATTACHMENT_FRONT_LEFT);
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIXME If the back buffer is asked for here, and the front buffer is
|
||||
* later needed by the client API (e.g. glDrawBuffer is called to draw
|
||||
* the front buffer), it will create a new pipe texture and draw there.
|
||||
* One fix is to ask for both buffers here, but it would be a waste if
|
||||
* the front buffer is never used. A better fix is to add a callback to
|
||||
* the pipe screen with context private (just like flush_frontbuffer).
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocate the context's framebuffers after draw/read surfaces change.
|
||||
*/
|
||||
static EGLBoolean
|
||||
egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
||||
{
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface);
|
||||
struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface);
|
||||
|
||||
/* unreference the old framebuffers */
|
||||
if (gctx->draw.st_fb) {
|
||||
EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb);
|
||||
void *priv;
|
||||
|
||||
priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb);
|
||||
if (!gdraw || priv != (void *) &gdraw->base) {
|
||||
gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
|
||||
gctx->draw.st_fb = NULL;
|
||||
gctx->draw.attachment_mask = 0x0;
|
||||
}
|
||||
|
||||
if (is_equal) {
|
||||
gctx->read.st_fb = NULL;
|
||||
gctx->draw.attachment_mask = 0x0;
|
||||
}
|
||||
else {
|
||||
priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
|
||||
if (!gread || priv != (void *) &gread->base) {
|
||||
gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
|
||||
gctx->read.st_fb = NULL;
|
||||
gctx->draw.attachment_mask = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gdraw)
|
||||
return EGL_TRUE;
|
||||
|
||||
/* create the draw fb */
|
||||
if (!gctx->draw.st_fb) {
|
||||
gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base);
|
||||
if (!gctx->draw.st_fb)
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
/* create the read fb */
|
||||
if (!gctx->read.st_fb) {
|
||||
if (gread != gdraw) {
|
||||
gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base);
|
||||
if (!gctx->read.st_fb) {
|
||||
gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
|
||||
gctx->draw.st_fb = NULL;
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* there is no st_reference_framebuffer... */
|
||||
gctx->read.st_fb = gctx->draw.st_fb;
|
||||
}
|
||||
}
|
||||
|
||||
egl_g3d_route_context(dpy, &gctx->base);
|
||||
gctx->force_validate = EGL_TRUE;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the state tracker for the given context.
|
||||
*/
|
||||
static const struct egl_g3d_st *
|
||||
static struct st_api *
|
||||
egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
|
||||
{
|
||||
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
||||
const struct egl_g3d_st *stapi;
|
||||
struct st_api *stapi;
|
||||
EGLint idx = -1;
|
||||
|
||||
switch (ctx->ClientAPI) {
|
||||
case EGL_OPENGL_ES_API:
|
||||
switch (ctx->ClientVersion) {
|
||||
case 1:
|
||||
idx = EGL_G3D_ST_OPENGL_ES;
|
||||
idx = ST_API_OPENGL_ES1;
|
||||
break;
|
||||
case 2:
|
||||
idx = EGL_G3D_ST_OPENGL_ES2;
|
||||
idx = ST_API_OPENGL_ES2;
|
||||
break;
|
||||
default:
|
||||
_eglLog(_EGL_WARNING, "unknown client version %d",
|
||||
|
|
@ -272,10 +65,10 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
|
|||
}
|
||||
break;
|
||||
case EGL_OPENVG_API:
|
||||
idx = EGL_G3D_ST_OPENVG;
|
||||
idx = ST_API_OPENVG;
|
||||
break;
|
||||
case EGL_OPENGL_API:
|
||||
idx = EGL_G3D_ST_OPENGL;
|
||||
idx = ST_API_OPENGL;
|
||||
break;
|
||||
default:
|
||||
_eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
|
||||
|
|
@ -299,10 +92,10 @@ egl_g3d_init_st(_EGLDriver *drv)
|
|||
if (gdrv->api_mask)
|
||||
return;
|
||||
|
||||
for (i = 0; i < NUM_EGL_G3D_STS; i++) {
|
||||
gdrv->stapis[i] = egl_g3d_get_st(i);
|
||||
for (i = 0; i < ST_API_COUNT; i++) {
|
||||
gdrv->stapis[i] = egl_g3d_create_st_api(i);
|
||||
if (gdrv->stapis[i])
|
||||
gdrv->api_mask |= gdrv->stapis[i]->api_bit;
|
||||
gdrv->api_mask |= egl_g3d_st_api_bit(i);
|
||||
}
|
||||
|
||||
if (gdrv->api_mask)
|
||||
|
|
@ -351,35 +144,6 @@ egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an API mask that consists of the state trackers that supports the
|
||||
* given mode.
|
||||
*
|
||||
* FIXME add st_is_mode_supported()?
|
||||
*/
|
||||
static EGLint
|
||||
get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask)
|
||||
{
|
||||
EGLint check;
|
||||
|
||||
/* OpenGL ES 1.x and 2.x are checked together */
|
||||
check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
|
||||
if (api_mask & check) {
|
||||
/* this is required by EGL, not by OpenGL ES */
|
||||
if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode)
|
||||
api_mask &= ~check;
|
||||
}
|
||||
|
||||
check = EGL_OPENVG_BIT;
|
||||
if (api_mask & check) {
|
||||
/* vega st needs the depth/stencil rb */
|
||||
if (!mode->depthBits && !mode->stencilBits)
|
||||
api_mask &= ~check;
|
||||
}
|
||||
|
||||
return api_mask;
|
||||
}
|
||||
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
|
||||
static void
|
||||
|
|
@ -443,19 +207,89 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
|
|||
|
||||
#endif /* EGL_MESA_screen_surface */
|
||||
|
||||
/**
|
||||
* Initialize an EGL config from the native config.
|
||||
*/
|
||||
static EGLBoolean
|
||||
egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
_EGLConfig *conf, const struct native_config *nconf)
|
||||
{
|
||||
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
||||
struct egl_g3d_config *gconf = egl_g3d_config(conf);
|
||||
const __GLcontextModes *mode = &nconf->mode;
|
||||
EGLint buffer_mask, api_mask;
|
||||
EGLBoolean valid;
|
||||
EGLint i;
|
||||
|
||||
buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
|
||||
if (mode->doubleBufferMode)
|
||||
buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
|
||||
if (mode->stereoMode) {
|
||||
buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
|
||||
if (mode->doubleBufferMode)
|
||||
buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
|
||||
}
|
||||
|
||||
gconf->stvis.buffer_mask = buffer_mask;
|
||||
gconf->stvis.color_format = nconf->color_format;
|
||||
gconf->stvis.depth_stencil_format = nconf->depth_format;
|
||||
gconf->stvis.accum_format = PIPE_FORMAT_NONE;
|
||||
gconf->stvis.samples = 0;
|
||||
|
||||
gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT) ?
|
||||
ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
|
||||
|
||||
api_mask = 0;
|
||||
for (i = 0; i < ST_API_COUNT; i++) {
|
||||
struct st_api *stapi = gdrv->stapis[i];
|
||||
if (stapi) {
|
||||
if (stapi->is_visual_supported(stapi, &gconf->stvis))
|
||||
api_mask |= egl_g3d_st_api_bit(i);
|
||||
}
|
||||
}
|
||||
/* this is required by EGL, not by OpenGL ES */
|
||||
if ((mode->drawableType & GLX_WINDOW_BIT) && !mode->doubleBufferMode)
|
||||
api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
|
||||
|
||||
if (!api_mask) {
|
||||
_eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
|
||||
mode->visualID);
|
||||
}
|
||||
|
||||
valid = _eglConfigFromContextModesRec(&gconf->base,
|
||||
mode, api_mask, api_mask);
|
||||
if (valid) {
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
/* check if scanout surface bit is set */
|
||||
if (nconf->scanout_bit) {
|
||||
EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE);
|
||||
val |= EGL_SCREEN_BIT_MESA;
|
||||
SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val);
|
||||
}
|
||||
#endif
|
||||
valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
|
||||
}
|
||||
if (!valid) {
|
||||
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x", mode->visualID);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
gconf->native = nconf;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add configs to display and return the next config ID.
|
||||
*/
|
||||
static EGLint
|
||||
egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
|
||||
{
|
||||
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
||||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||
const struct native_config **native_configs;
|
||||
int num_configs, i;
|
||||
|
||||
native_configs = gdpy->native->get_configs(gdpy->native,
|
||||
&num_configs);
|
||||
native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
|
||||
if (!num_configs) {
|
||||
if (native_configs)
|
||||
free(native_configs);
|
||||
|
|
@ -463,61 +297,25 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
|
|||
}
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
EGLint api_mask;
|
||||
struct egl_g3d_config *gconf;
|
||||
EGLBoolean valid;
|
||||
|
||||
gconf = CALLOC_STRUCT(egl_g3d_config);
|
||||
if (!gconf)
|
||||
continue;
|
||||
|
||||
_eglInitConfig(&gconf->base, dpy, id);
|
||||
|
||||
api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask);
|
||||
if (!api_mask) {
|
||||
_eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
|
||||
native_configs[i]->mode.visualID);
|
||||
}
|
||||
|
||||
valid = _eglConfigFromContextModesRec(&gconf->base,
|
||||
&native_configs[i]->mode, api_mask, api_mask);
|
||||
if (valid) {
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
/* check if scanout surface bit is set */
|
||||
if (native_configs[i]->scanout_bit) {
|
||||
EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE);
|
||||
val |= EGL_SCREEN_BIT_MESA;
|
||||
SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val);
|
||||
if (gconf) {
|
||||
_eglInitConfig(&gconf->base, dpy, id);
|
||||
if (!egl_g3d_init_config(drv, dpy, &gconf->base, native_configs[i])) {
|
||||
free(gconf);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
|
||||
}
|
||||
if (!valid) {
|
||||
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x",
|
||||
native_configs[i]->mode.visualID);
|
||||
free(gconf);
|
||||
continue;
|
||||
}
|
||||
|
||||
gconf->native = native_configs[i];
|
||||
_eglAddConfig(dpy, &gconf->base);
|
||||
id++;
|
||||
_eglAddConfig(dpy, &gconf->base);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
free(native_configs);
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-validate the context.
|
||||
*/
|
||||
static void
|
||||
egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
|
||||
{
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(context_private);
|
||||
egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base);
|
||||
}
|
||||
|
||||
static void
|
||||
egl_g3d_invalid_surface(struct native_display *ndpy,
|
||||
struct native_surface *nsurf,
|
||||
|
|
@ -525,11 +323,15 @@ egl_g3d_invalid_surface(struct native_display *ndpy,
|
|||
{
|
||||
/* XXX not thread safe? */
|
||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(gsurf->base.CurrentContext);
|
||||
|
||||
/* set force_validate to skip an unnecessary check */
|
||||
struct egl_g3d_context *gctx;
|
||||
|
||||
/*
|
||||
* Some functions such as egl_g3d_copy_buffers create a temporary native
|
||||
* surface. There is no gsurf associated with it.
|
||||
*/
|
||||
gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
|
||||
if (gctx)
|
||||
gctx->force_validate = TRUE;
|
||||
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
|
||||
}
|
||||
|
||||
static struct native_event_handler egl_g3d_native_event_handler = {
|
||||
|
|
@ -545,6 +347,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
|
|||
_eglReleaseDisplayResources(drv, dpy);
|
||||
_eglCleanupDisplay(dpy);
|
||||
|
||||
if (gdpy->pipe)
|
||||
gdpy->pipe->destroy(gdpy->pipe);
|
||||
|
||||
if (dpy->Screens) {
|
||||
for (i = 0; i < dpy->NumScreens; i++) {
|
||||
struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
|
||||
|
|
@ -554,6 +359,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
|
|||
free(dpy->Screens);
|
||||
}
|
||||
|
||||
if (gdpy->smapi)
|
||||
egl_g3d_destroy_st_manager(gdpy->smapi);
|
||||
|
||||
if (gdpy->native)
|
||||
gdpy->native->destroy(gdpy->native);
|
||||
|
||||
|
|
@ -588,11 +396,17 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
|
|||
}
|
||||
|
||||
gdpy->native->user_data = (void *) dpy;
|
||||
gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
|
||||
|
||||
egl_g3d_init_st(&gdrv->base);
|
||||
dpy->ClientAPIsMask = gdrv->api_mask;
|
||||
|
||||
gdpy->smapi = egl_g3d_create_st_manager(dpy);
|
||||
if (!gdpy->smapi) {
|
||||
_eglError(EGL_NOT_INITIALIZED,
|
||||
"eglInitialize(failed to create st manager)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
/* enable MESA_screen_surface before adding (and validating) configs */
|
||||
if (gdpy->native->modeset) {
|
||||
|
|
@ -629,7 +443,6 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
|
|||
struct egl_g3d_context *gshare = egl_g3d_context(share);
|
||||
struct egl_g3d_config *gconf = egl_g3d_config(conf);
|
||||
struct egl_g3d_context *gctx;
|
||||
const __GLcontextModes *mode;
|
||||
|
||||
gctx = CALLOC_STRUCT(egl_g3d_context);
|
||||
if (!gctx) {
|
||||
|
|
@ -648,24 +461,14 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
mode = &gconf->native->mode;
|
||||
|
||||
gctx->pipe = gdpy->native->screen->context_create(
|
||||
gdpy->native->screen,
|
||||
(void *) &gctx->base);
|
||||
|
||||
if (!gctx->pipe) {
|
||||
gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi,
|
||||
&gconf->stvis, (gshare) ? gshare->stctxi : NULL);
|
||||
if (!gctx->stctxi) {
|
||||
free(gctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
|
||||
(gshare) ? gshare->st_ctx : NULL);
|
||||
if (!gctx->st_ctx) {
|
||||
gctx->pipe->destroy(gctx->pipe);
|
||||
free(gctx);
|
||||
return NULL;
|
||||
}
|
||||
gctx->stctxi->st_manager_private = (void *) &gctx->base;
|
||||
|
||||
return &gctx->base;
|
||||
}
|
||||
|
|
@ -682,9 +485,7 @@ destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
|
|||
if (!dpy->Initialized)
|
||||
_eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
|
||||
|
||||
egl_g3d_realloc_context(dpy, &gctx->base);
|
||||
/* it will destroy the associated pipe context */
|
||||
gctx->stapi->st_destroy_context(gctx->st_ctx);
|
||||
gctx->stctxi->destroy(gctx->stctxi);
|
||||
|
||||
free(gctx);
|
||||
}
|
||||
|
|
@ -786,14 +587,20 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
gsurf->stvis = gconf->stvis;
|
||||
if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER)
|
||||
gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT;
|
||||
|
||||
gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base);
|
||||
if (!gsurf->stfbi) {
|
||||
gsurf->native->destroy(gsurf->native);
|
||||
free(gsurf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsurf->user_data = &gsurf->base;
|
||||
gsurf->native = nsurf;
|
||||
|
||||
gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ?
|
||||
NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
|
||||
if (!gconf->native->mode.doubleBufferMode)
|
||||
gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
|
||||
|
||||
return &gsurf->base;
|
||||
}
|
||||
|
||||
|
|
@ -849,7 +656,8 @@ destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
|
|||
if (!dpy->Initialized)
|
||||
_eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
|
||||
|
||||
pipe_surface_reference(&gsurf->render_surface, NULL);
|
||||
pipe_texture_reference(&gsurf->render_texture, NULL);
|
||||
egl_g3d_destroy_st_framebuffer(gsurf->stfbi);
|
||||
gsurf->native->destroy(gsurf->native);
|
||||
free(gsurf);
|
||||
}
|
||||
|
|
@ -868,6 +676,7 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
|
|||
{
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
|
||||
struct egl_g3d_surface *gread = egl_g3d_surface(read);
|
||||
struct egl_g3d_context *old_gctx;
|
||||
EGLBoolean ok = EGL_TRUE;
|
||||
|
||||
|
|
@ -878,39 +687,29 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
|
|||
|
||||
if (old_gctx) {
|
||||
/* flush old context */
|
||||
old_gctx->stapi->st_flush(old_gctx->st_ctx,
|
||||
old_gctx->stctxi->flush(old_gctx->stctxi,
|
||||
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
||||
|
||||
/*
|
||||
* The old context is no longer current, and egl_g3d_realloc_context()
|
||||
* should be called to destroy the framebuffers. However, it is possible
|
||||
* that it will be made current again with the same draw/read surfaces.
|
||||
* It might be better to keep it around.
|
||||
*/
|
||||
}
|
||||
|
||||
if (gctx) {
|
||||
ok = egl_g3d_realloc_context(dpy, &gctx->base);
|
||||
ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi,
|
||||
(gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL);
|
||||
if (ok) {
|
||||
/* XXX: need to pass the winsys argument for
|
||||
* flush_frontbuffer in the fourth parameter here:
|
||||
*/
|
||||
ok = gctx->stapi->st_make_current(gctx->st_ctx,
|
||||
gctx->draw.st_fb,
|
||||
gctx->read.st_fb,
|
||||
NULL);
|
||||
if (ok) {
|
||||
egl_g3d_validate_context(dpy, &gctx->base);
|
||||
if (gdraw->base.Type == EGL_WINDOW_BIT) {
|
||||
gctx->base.WindowRenderBuffer =
|
||||
(gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
|
||||
EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
|
||||
}
|
||||
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi);
|
||||
if (gread != gdraw) {
|
||||
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi,
|
||||
gread->stfbi);
|
||||
}
|
||||
|
||||
if (gdraw->base.Type == EGL_WINDOW_BIT) {
|
||||
gctx->base.WindowRenderBuffer =
|
||||
(gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
|
||||
EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (old_gctx) {
|
||||
ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL, NULL);
|
||||
ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL);
|
||||
old_gctx->base.WindowRenderBuffer = EGL_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -937,15 +736,17 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
|
|||
return EGL_TRUE;
|
||||
|
||||
/* or when the surface is single-buffered */
|
||||
if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
|
||||
if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT)
|
||||
return EGL_TRUE;
|
||||
|
||||
if (ctx && ctx->DrawSurface == surf)
|
||||
gctx = egl_g3d_context(ctx);
|
||||
|
||||
/* flush if the surface is current */
|
||||
if (gctx)
|
||||
gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
|
||||
if (gctx) {
|
||||
gctx->stctxi->flush(gctx->stctxi,
|
||||
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
||||
}
|
||||
|
||||
return gsurf->native->swap_buffers(gsurf->native);
|
||||
}
|
||||
|
|
@ -985,7 +786,7 @@ get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf,
|
|||
return NULL;
|
||||
|
||||
psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt],
|
||||
0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||
pipe_texture_reference(&textures[natt], NULL);
|
||||
|
||||
return psurf;
|
||||
|
|
@ -1003,7 +804,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
|||
struct pipe_screen *screen = gdpy->native->screen;
|
||||
struct pipe_surface *psurf;
|
||||
|
||||
if (!gsurf->render_surface)
|
||||
if (!gsurf->render_texture)
|
||||
return EGL_TRUE;
|
||||
|
||||
gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target));
|
||||
|
|
@ -1018,26 +819,33 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
|||
/* flush if the surface is current */
|
||||
if (ctx && ctx->DrawSurface == &gsurf->base) {
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
gctx->stapi->st_flush(gctx->st_ctx,
|
||||
gctx->stctxi->flush(gctx->stctxi,
|
||||
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
||||
}
|
||||
|
||||
/* create a pipe context to copy surfaces */
|
||||
if (!gdpy->pipe) {
|
||||
gdpy->pipe =
|
||||
gdpy->native->screen->context_create(gdpy->native->screen, NULL);
|
||||
if (!gdpy->pipe)
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
|
||||
if (psurf) {
|
||||
struct pipe_context pipe;
|
||||
struct pipe_surface *psrc;
|
||||
|
||||
/**
|
||||
* XXX This is hacky. If we might allow the EGLDisplay to create a pipe
|
||||
* context of its own and use the blitter context for this.
|
||||
*/
|
||||
memset(&pipe, 0, sizeof(pipe));
|
||||
pipe.screen = screen;
|
||||
psrc = screen->get_tex_surface(screen, gsurf->render_texture,
|
||||
0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
|
||||
if (psrc) {
|
||||
gdpy->pipe->surface_copy(gdpy->pipe, psurf, 0, 0,
|
||||
psrc, 0, 0, psurf->width, psurf->height);
|
||||
pipe_surface_reference(&psrc, NULL);
|
||||
|
||||
util_surface_copy(&pipe, FALSE, psurf, 0, 0,
|
||||
gsurf->render_surface, 0, 0, psurf->width, psurf->height);
|
||||
nsurf->flush_frontbuffer(nsurf);
|
||||
}
|
||||
|
||||
pipe_surface_reference(&psurf, NULL);
|
||||
nsurf->flush_frontbuffer(nsurf);
|
||||
}
|
||||
|
||||
nsurf->destroy(nsurf);
|
||||
|
|
@ -1048,8 +856,16 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
|||
static EGLBoolean
|
||||
egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
|
||||
{
|
||||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
gctx->stapi->st_finish(gctx->st_ctx);
|
||||
struct pipe_screen *screen = gdpy->native->screen;
|
||||
struct pipe_fence_handle *fence = NULL;
|
||||
|
||||
gctx->stctxi->flush(gctx->stctxi,
|
||||
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
|
||||
screen->fence_finish(screen, fence, 0);
|
||||
screen->fence_reference(screen, &fence, NULL);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1079,10 +895,10 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
|
|||
/* in case this is called before a display is initialized */
|
||||
egl_g3d_init_st(&gdrv->base);
|
||||
|
||||
for (i = 0; i < NUM_EGL_G3D_STS; i++) {
|
||||
const struct egl_g3d_st *stapi = gdrv->stapis[i];
|
||||
for (i = 0; i < ST_API_COUNT; i++) {
|
||||
struct st_api *stapi = gdrv->stapis[i];
|
||||
if (stapi) {
|
||||
proc = (_EGLProc) stapi->st_get_proc_address(procname);
|
||||
proc = (_EGLProc) stapi->get_proc_address(stapi, procname);
|
||||
if (proc)
|
||||
return proc;
|
||||
}
|
||||
|
|
@ -1098,8 +914,8 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
|||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||
_EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
|
||||
struct egl_g3d_context *gctx;
|
||||
enum pipe_format target_format;
|
||||
int target;
|
||||
enum pipe_format internal_format;
|
||||
enum st_texture_type target;
|
||||
|
||||
if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
|
||||
return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
|
||||
|
|
@ -1110,10 +926,10 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
|||
|
||||
switch (gsurf->base.TextureFormat) {
|
||||
case EGL_TEXTURE_RGB:
|
||||
target_format = PIPE_FORMAT_R8G8B8_UNORM;
|
||||
internal_format = PIPE_FORMAT_R8G8B8_UNORM;
|
||||
break;
|
||||
case EGL_TEXTURE_RGBA:
|
||||
target_format = PIPE_FORMAT_B8G8R8A8_UNORM;
|
||||
internal_format = PIPE_FORMAT_B8G8R8A8_UNORM;
|
||||
break;
|
||||
default:
|
||||
return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
|
||||
|
|
@ -1129,21 +945,24 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
|||
|
||||
if (!es1)
|
||||
return EGL_TRUE;
|
||||
if (!gsurf->render_surface)
|
||||
if (!gsurf->render_texture)
|
||||
return EGL_FALSE;
|
||||
|
||||
/* flush properly if the surface is bound */
|
||||
if (gsurf->base.CurrentContext) {
|
||||
gctx = egl_g3d_context(gsurf->base.CurrentContext);
|
||||
gctx->stapi->st_flush(gctx->st_ctx,
|
||||
gctx->stctxi->flush(gctx->stctxi,
|
||||
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
|
||||
}
|
||||
|
||||
gctx = egl_g3d_context(es1);
|
||||
gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
|
||||
target, gsurf->base.MipmapLevel, target_format);
|
||||
|
||||
gsurf->base.BoundToTexture = EGL_TRUE;
|
||||
if (gctx->stctxi->teximage) {
|
||||
if (!gctx->stctxi->teximage(gctx->stctxi, target,
|
||||
gsurf->base.MipmapLevel, internal_format,
|
||||
gsurf->render_texture, gsurf->base.MipmapTexture))
|
||||
return EGL_FALSE;
|
||||
gsurf->base.BoundToTexture = EGL_TRUE;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
|
@ -1160,14 +979,15 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
|||
if (buffer != EGL_BACK_BUFFER)
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
|
||||
|
||||
if (gsurf->render_surface) {
|
||||
if (gsurf->render_texture) {
|
||||
_EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
|
||||
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
|
||||
|
||||
/* what if the context the surface binds to is no longer current? */
|
||||
if (gctx)
|
||||
gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
|
||||
ST_TEXTURE_2D, gsurf->base.MipmapLevel);
|
||||
if (gctx) {
|
||||
gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D,
|
||||
gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
gsurf->base.BoundToTexture = EGL_FALSE;
|
||||
|
|
@ -1279,6 +1099,12 @@ static void
|
|||
egl_g3d_unload(_EGLDriver *drv)
|
||||
{
|
||||
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
|
||||
EGLint i;
|
||||
|
||||
for (i = 0; i < ST_API_COUNT; i++) {
|
||||
if (gdrv->stapis[i])
|
||||
gdrv->stapis[i]->destroy(gdrv->stapis[i]);
|
||||
}
|
||||
|
||||
egl_g3d_destroy_probe(drv, NULL);
|
||||
free(gdrv);
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@
|
|||
#include "eglmode.h"
|
||||
|
||||
#include "native.h"
|
||||
#include "egl_st.h"
|
||||
#include "egl_g3d_st.h"
|
||||
|
||||
struct egl_g3d_driver {
|
||||
_EGLDriver base;
|
||||
const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS];
|
||||
struct st_api *stapis[ST_API_COUNT];
|
||||
EGLint api_mask;
|
||||
|
||||
EGLint probe_key;
|
||||
|
|
@ -51,35 +51,34 @@ struct egl_g3d_driver {
|
|||
|
||||
struct egl_g3d_display {
|
||||
struct native_display *native;
|
||||
};
|
||||
|
||||
struct egl_g3d_buffer {
|
||||
struct st_framebuffer *st_fb;
|
||||
uint attachment_mask;
|
||||
struct st_manager *smapi;
|
||||
struct pipe_context *pipe;
|
||||
};
|
||||
|
||||
struct egl_g3d_context {
|
||||
_EGLContext base;
|
||||
|
||||
const struct egl_g3d_st *stapi;
|
||||
struct pipe_context *pipe;
|
||||
struct st_api *stapi;
|
||||
|
||||
struct st_context *st_ctx;
|
||||
EGLBoolean force_validate;
|
||||
struct egl_g3d_buffer draw, read;
|
||||
struct st_context_iface *stctxi;
|
||||
};
|
||||
|
||||
struct egl_g3d_surface {
|
||||
_EGLSurface base;
|
||||
|
||||
struct st_visual stvis;
|
||||
struct st_framebuffer_iface *stfbi;
|
||||
|
||||
struct native_surface *native;
|
||||
enum native_attachment render_att;
|
||||
struct pipe_surface *render_surface;
|
||||
struct pipe_texture *render_texture;
|
||||
unsigned int sequence_number;
|
||||
};
|
||||
|
||||
struct egl_g3d_config {
|
||||
_EGLConfig base;
|
||||
const struct native_config *native;
|
||||
struct st_visual stvis;
|
||||
};
|
||||
|
||||
struct egl_g3d_image {
|
||||
|
|
|
|||
227
src/gallium/state_trackers/egl/common/egl_g3d_st.c
Normal file
227
src/gallium/state_trackers/egl/common/egl_g3d_st.c
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL 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:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_dl.h"
|
||||
#include "eglimage.h"
|
||||
#include "eglmutex.h"
|
||||
|
||||
#include "egl_g3d.h"
|
||||
#include "egl_g3d_st.h"
|
||||
|
||||
struct egl_g3d_st_manager {
|
||||
struct st_manager base;
|
||||
_EGLDisplay *display;
|
||||
};
|
||||
|
||||
static INLINE struct egl_g3d_st_manager *
|
||||
egl_g3d_st_manager(struct st_manager *smapi)
|
||||
{
|
||||
return (struct egl_g3d_st_manager *) smapi;
|
||||
}
|
||||
|
||||
struct st_api *
|
||||
egl_g3d_create_st_api(enum st_api_type api)
|
||||
{
|
||||
const char *stmod_name;
|
||||
struct util_dl_library *lib;
|
||||
const struct st_module *mod;
|
||||
|
||||
switch (api) {
|
||||
case ST_API_OPENGL:
|
||||
stmod_name = ST_MODULE_OPENGL_SYMBOL;
|
||||
break;
|
||||
case ST_API_OPENGL_ES1:
|
||||
stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL;
|
||||
break;
|
||||
case ST_API_OPENGL_ES2:
|
||||
stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL;
|
||||
break;
|
||||
case ST_API_OPENVG:
|
||||
stmod_name = ST_MODULE_OPENVG_SYMBOL;
|
||||
break;
|
||||
default:
|
||||
stmod_name = NULL;
|
||||
break;
|
||||
}
|
||||
if (!stmod_name)
|
||||
return NULL;
|
||||
|
||||
mod = NULL;
|
||||
lib = util_dl_open(NULL);
|
||||
if (lib) {
|
||||
mod = (const struct st_module *)
|
||||
util_dl_get_proc_address(lib, stmod_name);
|
||||
util_dl_close(lib);
|
||||
}
|
||||
if (!mod || mod->api != api)
|
||||
return NULL;
|
||||
|
||||
return mod->create_api();
|
||||
}
|
||||
|
||||
struct st_manager *
|
||||
egl_g3d_create_st_manager(_EGLDisplay *dpy)
|
||||
{
|
||||
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
|
||||
struct egl_g3d_st_manager *gsmapi;
|
||||
|
||||
gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
|
||||
if (gsmapi) {
|
||||
gsmapi->display = dpy;
|
||||
|
||||
gsmapi->base.screen = gdpy->native->screen;
|
||||
}
|
||||
|
||||
return &gsmapi->base;;
|
||||
}
|
||||
|
||||
void
|
||||
egl_g3d_destroy_st_manager(struct st_manager *smapi)
|
||||
{
|
||||
struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
|
||||
free(gsmapi);
|
||||
}
|
||||
|
||||
static boolean
|
||||
egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
|
||||
enum st_attachment_type statt)
|
||||
{
|
||||
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
|
||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||
|
||||
return gsurf->native->flush_frontbuffer(gsurf->native);
|
||||
}
|
||||
|
||||
static boolean
|
||||
egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
|
||||
const enum st_attachment_type *statts,
|
||||
unsigned count,
|
||||
struct pipe_texture **out)
|
||||
{
|
||||
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
|
||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||
struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
|
||||
uint attachment_mask = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
int natt;
|
||||
|
||||
switch (statts[i]) {
|
||||
case ST_ATTACHMENT_FRONT_LEFT:
|
||||
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_LEFT:
|
||||
natt = NATIVE_ATTACHMENT_BACK_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||
natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_RIGHT:
|
||||
natt = NATIVE_ATTACHMENT_BACK_RIGHT;
|
||||
default:
|
||||
natt = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (natt >= 0)
|
||||
attachment_mask |= 1 << natt;
|
||||
}
|
||||
|
||||
if (!gsurf->native->validate(gsurf->native, attachment_mask,
|
||||
&gsurf->sequence_number, textures, &gsurf->base.Width,
|
||||
&gsurf->base.Height))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct pipe_texture *tex;
|
||||
int natt;
|
||||
|
||||
switch (statts[i]) {
|
||||
case ST_ATTACHMENT_FRONT_LEFT:
|
||||
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_LEFT:
|
||||
natt = NATIVE_ATTACHMENT_BACK_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||
natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_RIGHT:
|
||||
natt = NATIVE_ATTACHMENT_BACK_RIGHT;
|
||||
break;
|
||||
default:
|
||||
natt = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (natt >= 0) {
|
||||
tex = textures[natt];
|
||||
|
||||
if (statts[i] == stfbi->visual->render_buffer)
|
||||
pipe_texture_reference(&gsurf->render_texture, tex);
|
||||
|
||||
if (attachment_mask & (1 << natt)) {
|
||||
/* transfer the ownership to the caller */
|
||||
out[i] = tex;
|
||||
attachment_mask &= ~(1 << natt);
|
||||
}
|
||||
else {
|
||||
/* the attachment is listed more than once */
|
||||
pipe_texture_reference(&out[i], tex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct st_framebuffer_iface *
|
||||
egl_g3d_create_st_framebuffer(_EGLSurface *surf)
|
||||
{
|
||||
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
|
||||
struct st_framebuffer_iface *stfbi;
|
||||
|
||||
stfbi = CALLOC_STRUCT(st_framebuffer_iface);
|
||||
if (!stfbi)
|
||||
return NULL;
|
||||
|
||||
stfbi->visual = &gsurf->stvis;
|
||||
stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
|
||||
stfbi->validate = egl_g3d_st_framebuffer_validate;
|
||||
stfbi->st_manager_private = (void *) &gsurf->base;
|
||||
|
||||
return stfbi;
|
||||
}
|
||||
|
||||
void
|
||||
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
free(stfbi);
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.8
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
|
@ -20,54 +20,60 @@
|
|||
* BRIAN PAUL 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:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#ifndef _EGL_ST_H_
|
||||
#define _EGL_ST_H_
|
||||
|
||||
#include "GL/gl.h" /* for GL types */
|
||||
#include "GL/internal/glcore.h" /* for __GLcontextModes */
|
||||
#ifndef _EGL_G3D_ST_H_
|
||||
#define _EGL_G3D_ST_H_
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_format.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "state_tracker/st_api.h"
|
||||
#include "egltypedefs.h"
|
||||
|
||||
/* avoid calling st functions directly */
|
||||
#if 1
|
||||
struct st_api *
|
||||
egl_g3d_create_st_api(enum st_api_type api);
|
||||
|
||||
#define ST_SURFACE_FRONT_LEFT 0
|
||||
#define ST_SURFACE_BACK_LEFT 1
|
||||
#define ST_SURFACE_FRONT_RIGHT 2
|
||||
#define ST_SURFACE_BACK_RIGHT 3
|
||||
struct st_manager *
|
||||
egl_g3d_create_st_manager(_EGLDisplay *dpy);
|
||||
|
||||
#define ST_TEXTURE_2D 0x2
|
||||
void
|
||||
egl_g3d_destroy_st_manager(struct st_manager *smapi);
|
||||
|
||||
struct st_context;
|
||||
struct st_framebuffer;
|
||||
typedef void (*st_proc)();
|
||||
struct st_framebuffer_iface *
|
||||
egl_g3d_create_st_framebuffer(_EGLSurface *surf);
|
||||
|
||||
#else
|
||||
#include "state_tracker/st_public.h"
|
||||
#endif
|
||||
void
|
||||
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
|
||||
|
||||
/* remember to update egl_g3d_get_st() when update the enums */
|
||||
enum egl_g3d_st_api {
|
||||
EGL_G3D_ST_OPENGL_ES = 0,
|
||||
EGL_G3D_ST_OPENVG,
|
||||
EGL_G3D_ST_OPENGL_ES2,
|
||||
EGL_G3D_ST_OPENGL,
|
||||
/**
|
||||
* Return the EGL_<api>_BIT of the st api.
|
||||
*/
|
||||
static INLINE int
|
||||
egl_g3d_st_api_bit(enum st_api_type api)
|
||||
{
|
||||
int bit;
|
||||
|
||||
NUM_EGL_G3D_STS
|
||||
};
|
||||
switch (api) {
|
||||
case ST_API_OPENGL:
|
||||
bit = EGL_OPENGL_BIT;
|
||||
break;
|
||||
case ST_API_OPENGL_ES1:
|
||||
bit = EGL_OPENGL_ES_BIT;
|
||||
break;
|
||||
case ST_API_OPENGL_ES2:
|
||||
bit = EGL_OPENGL_ES2_BIT;
|
||||
break;
|
||||
case ST_API_OPENVG:
|
||||
bit = EGL_OPENVG_BIT;
|
||||
break;
|
||||
default:
|
||||
bit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
struct egl_g3d_st {
|
||||
#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__);
|
||||
#include "st_public_tmp.h"
|
||||
/* fields must be added here */
|
||||
EGLint api_bit;
|
||||
};
|
||||
return bit;
|
||||
}
|
||||
|
||||
const struct egl_g3d_st *
|
||||
egl_g3d_get_st(enum egl_g3d_st_api api);
|
||||
|
||||
#endif /* _EGL_ST_H_ */
|
||||
#endif /* _EGL_G3D_ST_H_ */
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.8
|
||||
*
|
||||
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL 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.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "egllog.h"
|
||||
#include "EGL/egl.h" /* for EGL_api_BIT */
|
||||
|
||||
#include "egl_st.h"
|
||||
|
||||
#ifndef HAVE_DLADDR
|
||||
#define HAVE_DLADDR 1
|
||||
#endif
|
||||
|
||||
#if HAVE_DLADDR
|
||||
|
||||
static const char *
|
||||
egl_g3d_st_names[] = {
|
||||
#define ST_PUBLIC(name, ...) #name,
|
||||
#include "st_public_tmp.h"
|
||||
NULL
|
||||
};
|
||||
|
||||
static boolean
|
||||
egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
|
||||
{
|
||||
st_proc *procs = (st_proc *) stapi;
|
||||
void *handle;
|
||||
Dl_info info;
|
||||
const char **name;
|
||||
|
||||
if (!dladdr(sym, &info))
|
||||
return FALSE;
|
||||
handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
|
||||
if (!handle)
|
||||
return FALSE;
|
||||
|
||||
for (name = egl_g3d_st_names; *name; name++) {
|
||||
st_proc proc = (st_proc) dlsym(handle, *name);
|
||||
if (!proc) {
|
||||
_eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname);
|
||||
memset(stapi, 0, sizeof(*stapi));
|
||||
dlclose(handle);
|
||||
return FALSE;
|
||||
}
|
||||
*procs++ = proc;
|
||||
}
|
||||
|
||||
dlclose(handle);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else /* HAVE_DLADDR */
|
||||
|
||||
static boolean
|
||||
egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
|
||||
{
|
||||
#define ST_PUBLIC(name, ...) stapi->name = name;
|
||||
#include "st_public_tmp.h"
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DLADDR */
|
||||
|
||||
static boolean
|
||||
egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api)
|
||||
{
|
||||
void *handle, *sym;
|
||||
boolean res = FALSE;
|
||||
|
||||
/* already initialized */
|
||||
if (stapi->st_notify_swapbuffers != NULL)
|
||||
return TRUE;
|
||||
|
||||
handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!handle)
|
||||
return FALSE;
|
||||
|
||||
sym = dlsym(handle, api);
|
||||
if (sym && egl_g3d_fill_st(stapi, sym))
|
||||
res = TRUE;
|
||||
|
||||
dlclose(handle);
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *symbol;
|
||||
EGLint api_bit;
|
||||
} egl_g3d_st_info[NUM_EGL_G3D_STS] = {
|
||||
{ "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT },
|
||||
{ "st_api_OpenVG", EGL_OPENVG_BIT },
|
||||
{ "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT },
|
||||
{ "st_api_OpenGL", EGL_OPENGL_BIT },
|
||||
};
|
||||
|
||||
const struct egl_g3d_st *
|
||||
egl_g3d_get_st(enum egl_g3d_st_api api)
|
||||
{
|
||||
static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS];
|
||||
|
||||
if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) {
|
||||
all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit;
|
||||
return &all_trackers[api];
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share)
|
||||
ST_PUBLIC(st_destroy_context, void, struct st_context *st)
|
||||
ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask)
|
||||
ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData)
|
||||
ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height)
|
||||
ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf)
|
||||
ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height)
|
||||
ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
|
||||
ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
|
||||
ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb)
|
||||
ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb)
|
||||
ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read, void *winsys_drawable_handle)
|
||||
ST_PUBLIC(st_get_current, struct st_context *, void)
|
||||
ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence)
|
||||
ST_PUBLIC(st_finish, void, struct st_context *st)
|
||||
ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb)
|
||||
ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format)
|
||||
ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level)
|
||||
ST_PUBLIC(st_get_proc_address, st_proc, const char *procname)
|
||||
#undef ST_PUBLIC
|
||||
|
|
@ -38,6 +38,7 @@ SYS_LIBS = -lm -pthread
|
|||
|
||||
|
||||
INCLUDE_DIRS = \
|
||||
-I$(TOP)/src/mesa \
|
||||
-I$(TOP)/src/gallium/include
|
||||
|
||||
.c.o:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
#include "pipe/p_compiler.h"
|
||||
#include "state_tracker/st_manager.h"
|
||||
|
||||
PUBLIC const int st_api_OpenGL_ES1 = 1;
|
||||
|
||||
PUBLIC const struct st_module st_module_OpenGL_ES1 = {
|
||||
.api = ST_API_OPENGL_ES1,
|
||||
.create_api = st_manager_create_api
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
#include "pipe/p_compiler.h"
|
||||
#include "state_tracker/st_manager.h"
|
||||
|
||||
PUBLIC const int st_api_OpenGL_ES2 = 1;
|
||||
|
||||
PUBLIC const struct st_module st_module_OpenGL_ES2 = {
|
||||
.api = ST_API_OPENGL_ES2,
|
||||
.create_api = st_manager_create_api
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ C_SOURCES = \
|
|||
glx_api.c \
|
||||
glx_getproc.c \
|
||||
glx_usefont.c \
|
||||
xm_api.c
|
||||
xm_api.c \
|
||||
xm_st.c
|
||||
|
||||
include ../../../Makefile.template
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ if env['platform'] == 'linux' \
|
|||
'glx_getproc.c',
|
||||
'glx_usefont.c',
|
||||
'xm_api.c',
|
||||
'xm_st.c',
|
||||
]
|
||||
)
|
||||
Export('st_xlib')
|
||||
|
|
|
|||
|
|
@ -35,12 +35,9 @@
|
|||
|
||||
#include "xm_api.h"
|
||||
#include "main/context.h"
|
||||
#include "main/config.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/imports.h"
|
||||
#include "main/version.h"
|
||||
#include "state_tracker/st_context.h"
|
||||
#include "state_tracker/st_public.h"
|
||||
|
||||
|
||||
/* This indicates the client-side GLX API and GLX encoder version. */
|
||||
|
|
@ -1304,7 +1301,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
|
|||
if (MakeCurrent_PrevContext == src) {
|
||||
_mesa_Flush();
|
||||
}
|
||||
st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask );
|
||||
XMesaCopyContext(xm_src, xm_dst, mask);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -54,11 +54,9 @@
|
|||
#endif
|
||||
|
||||
#include "xm_api.h"
|
||||
#include "main/context.h"
|
||||
#include "main/framebuffer.h"
|
||||
#include "xm_st.h"
|
||||
|
||||
#include "state_tracker/st_public.h"
|
||||
#include "state_tracker/st_context.h"
|
||||
#include "main/context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_screen.h"
|
||||
#include "pipe/p_context.h"
|
||||
|
|
@ -72,19 +70,56 @@
|
|||
* global.
|
||||
*/
|
||||
static struct xm_driver driver;
|
||||
static struct st_api *stapi;
|
||||
|
||||
void xmesa_set_driver( const struct xm_driver *templ )
|
||||
{
|
||||
driver = *templ;
|
||||
stapi = driver.create_st_api();
|
||||
}
|
||||
|
||||
/**
|
||||
* Global X driver lock
|
||||
*/
|
||||
pipe_mutex _xmesa_lock;
|
||||
static XMesaDisplay
|
||||
xmesa_init_display( Display *display )
|
||||
{
|
||||
pipe_static_mutex(init_mutex);
|
||||
static struct xmesa_display xm_display;
|
||||
XMesaDisplay xmdpy;
|
||||
|
||||
pipe_mutex_lock(init_mutex);
|
||||
|
||||
static struct pipe_screen *screen = NULL;
|
||||
/* TODO support for multiple displays */
|
||||
xmdpy = &xm_display;
|
||||
|
||||
if (!xmdpy->display && display) {
|
||||
xmdpy->display = display;
|
||||
xmdpy->screen = driver.create_pipe_screen(display);
|
||||
xmdpy->smapi = CALLOC_STRUCT(st_manager);
|
||||
if (xmdpy->smapi)
|
||||
xmdpy->smapi->screen = xmdpy->screen;
|
||||
|
||||
if (xmdpy->screen && xmdpy->smapi) {
|
||||
pipe_mutex_init(xmdpy->mutex);
|
||||
}
|
||||
else {
|
||||
if (xmdpy->screen) {
|
||||
xmdpy->screen->destroy(xmdpy->screen);
|
||||
xmdpy->screen = NULL;
|
||||
}
|
||||
if (xmdpy->smapi) {
|
||||
FREE(xmdpy->smapi);
|
||||
xmdpy->smapi = NULL;
|
||||
}
|
||||
|
||||
xmdpy->display = NULL;
|
||||
}
|
||||
}
|
||||
if (!xmdpy->display || xmdpy->display != display)
|
||||
xmdpy = NULL;
|
||||
|
||||
pipe_mutex_unlock(init_mutex);
|
||||
|
||||
return xmdpy;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/***** X Utility Functions *****/
|
||||
|
|
@ -194,12 +229,13 @@ void
|
|||
xmesa_get_window_size(Display *dpy, XMesaBuffer b,
|
||||
GLuint *width, GLuint *height)
|
||||
{
|
||||
XMesaDisplay xmdpy = xmesa_init_display(dpy);
|
||||
Status stat;
|
||||
|
||||
pipe_mutex_lock(_xmesa_lock);
|
||||
pipe_mutex_lock(xmdpy->mutex);
|
||||
XSync(b->xm_visual->display, 0); /* added for Chromium */
|
||||
stat = get_drawable_size(dpy, b->ws.drawable, width, height);
|
||||
pipe_mutex_unlock(_xmesa_lock);
|
||||
pipe_mutex_unlock(xmdpy->mutex);
|
||||
|
||||
if (!stat) {
|
||||
/* probably querying a window that's recently been destroyed */
|
||||
|
|
@ -273,49 +309,43 @@ choose_pixel_format(XMesaVisual v)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Query the default gallium screen for a Z/Stencil format that
|
||||
* at least matches the given depthBits and stencilBits.
|
||||
* Choose a depth/stencil format that is "better" than the given depth and
|
||||
* stencil sizes.
|
||||
*/
|
||||
static void
|
||||
xmesa_choose_z_stencil_format(int depthBits, int stencilBits,
|
||||
enum pipe_format *depthFormat,
|
||||
enum pipe_format *stencilFormat)
|
||||
static enum pipe_format
|
||||
choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil)
|
||||
{
|
||||
const enum pipe_texture_target target = PIPE_TEXTURE_2D;
|
||||
const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
|
||||
const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE |
|
||||
PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO);
|
||||
static enum pipe_format formats[] = {
|
||||
PIPE_FORMAT_S8Z24_UNORM,
|
||||
PIPE_FORMAT_Z24S8_UNORM,
|
||||
PIPE_FORMAT_Z16_UNORM,
|
||||
PIPE_FORMAT_Z32_UNORM
|
||||
};
|
||||
int i;
|
||||
enum pipe_format formats[8], fmt;
|
||||
int count, i;
|
||||
|
||||
assert(screen);
|
||||
count = 0;
|
||||
if (depth <= 24 && stencil <= 8) {
|
||||
formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
|
||||
formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
|
||||
}
|
||||
|
||||
*depthFormat = *stencilFormat = PIPE_FORMAT_NONE;
|
||||
if (!stencil) {
|
||||
if (depth <= 16)
|
||||
formats[count++] = PIPE_FORMAT_Z16_UNORM;
|
||||
if (depth <= 32)
|
||||
formats[count++] = PIPE_FORMAT_Z32_UNORM;
|
||||
}
|
||||
|
||||
/* search for supported format */
|
||||
for (i = 0; i < Elements(formats); i++) {
|
||||
if (screen->is_format_supported(screen, formats[i],
|
||||
fmt = PIPE_FORMAT_NONE;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
|
||||
target, tex_usage, geom_flags)) {
|
||||
*depthFormat = formats[i];
|
||||
fmt = formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stencilBits) {
|
||||
*stencilFormat = *depthFormat;
|
||||
}
|
||||
|
||||
/* XXX we should check that he chosen format has at least as many bits
|
||||
* as what was requested.
|
||||
*/
|
||||
return fmt;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -324,7 +354,7 @@ xmesa_choose_z_stencil_format(int depthBits, int stencilBits,
|
|||
/***** Linked list of XMesaBuffers *****/
|
||||
/**********************************************************************/
|
||||
|
||||
XMesaBuffer XMesaBufferList = NULL;
|
||||
static XMesaBuffer XMesaBufferList = NULL;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -342,13 +372,15 @@ static XMesaBuffer
|
|||
create_xmesa_buffer(Drawable d, BufferType type,
|
||||
XMesaVisual vis, Colormap cmap)
|
||||
{
|
||||
XMesaDisplay xmdpy = xmesa_init_display(vis->display);
|
||||
XMesaBuffer b;
|
||||
GLframebuffer *fb;
|
||||
enum pipe_format colorFormat, depthFormat, stencilFormat;
|
||||
uint width, height;
|
||||
|
||||
ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
|
||||
|
||||
if (!xmdpy)
|
||||
return NULL;
|
||||
|
||||
b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
|
||||
if (!b)
|
||||
return NULL;
|
||||
|
|
@ -361,24 +393,12 @@ create_xmesa_buffer(Drawable d, BufferType type,
|
|||
b->type = type;
|
||||
b->cmap = cmap;
|
||||
|
||||
/* determine PIPE_FORMATs for buffers */
|
||||
colorFormat = choose_pixel_format(vis);
|
||||
|
||||
xmesa_choose_z_stencil_format(vis->mesa_visual.depthBits,
|
||||
vis->mesa_visual.stencilBits,
|
||||
&depthFormat, &stencilFormat);
|
||||
|
||||
|
||||
get_drawable_size(vis->display, d, &width, &height);
|
||||
|
||||
/*
|
||||
* Create framebuffer, but we'll plug in our own renderbuffers below.
|
||||
*/
|
||||
b->stfb = st_create_framebuffer(&vis->mesa_visual,
|
||||
colorFormat, depthFormat, stencilFormat,
|
||||
width, height,
|
||||
(void *) b);
|
||||
fb = &b->stfb->Base;
|
||||
b->stfb = xmesa_create_st_framebuffer(xmdpy, b);
|
||||
|
||||
/* GLX_EXT_texture_from_pixmap */
|
||||
b->TextureTarget = 0;
|
||||
|
|
@ -422,24 +442,21 @@ xmesa_free_buffer(XMesaBuffer buffer)
|
|||
|
||||
for (b = XMesaBufferList; b; b = b->Next) {
|
||||
if (b == buffer) {
|
||||
struct gl_framebuffer *fb = &buffer->stfb->Base;
|
||||
|
||||
/* unlink buffer from list */
|
||||
if (prev)
|
||||
prev->Next = buffer->Next;
|
||||
else
|
||||
XMesaBufferList = buffer->Next;
|
||||
|
||||
/* mark as delete pending */
|
||||
fb->DeletePending = GL_TRUE;
|
||||
|
||||
/* Since the X window for the XMesaBuffer is going away, we don't
|
||||
* want to dereference this pointer in the future.
|
||||
*/
|
||||
b->ws.drawable = 0;
|
||||
|
||||
/* Unreference. If count = zero we'll really delete the buffer */
|
||||
_mesa_reference_framebuffer(&fb, NULL);
|
||||
/* XXX we should move the buffer to a delete-pending list and destroy
|
||||
* the buffer until it is no longer current.
|
||||
*/
|
||||
xmesa_destroy_st_framebuffer(buffer->stfb);
|
||||
|
||||
free(buffer);
|
||||
|
||||
|
|
@ -596,10 +613,12 @@ XMesaVisual XMesaCreateVisual( Display *display,
|
|||
GLint level,
|
||||
GLint visualCaveat )
|
||||
{
|
||||
XMesaDisplay xmdpy = xmesa_init_display(display);
|
||||
XMesaVisual v;
|
||||
GLint red_bits, green_bits, blue_bits, alpha_bits;
|
||||
|
||||
xmesa_init( display );
|
||||
if (!xmdpy)
|
||||
return NULL;
|
||||
|
||||
/* For debugging only */
|
||||
if (_mesa_getenv("MESA_XSYNC")) {
|
||||
|
|
@ -681,6 +700,26 @@ XMesaVisual XMesaCreateVisual( Display *display,
|
|||
accum_blue_size, accum_alpha_size,
|
||||
0 );
|
||||
|
||||
v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
|
||||
if (db_flag)
|
||||
v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
|
||||
if (stereo_flag) {
|
||||
v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
|
||||
if (db_flag)
|
||||
v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
|
||||
}
|
||||
|
||||
v->stvis.color_format = choose_pixel_format(v);
|
||||
v->stvis.depth_stencil_format =
|
||||
choose_depth_stencil_format(xmdpy, depth_size, stencil_size);
|
||||
|
||||
v->stvis.accum_format = (accum_red_size +
|
||||
accum_green_size + accum_blue_size + accum_alpha_size) ?
|
||||
PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
|
||||
|
||||
v->stvis.samples = num_samples;
|
||||
v->stvis.render_buffer = ST_ATTACHMENT_INVALID;
|
||||
|
||||
/* XXX minor hack */
|
||||
v->mesa_visual.level = level;
|
||||
return v;
|
||||
|
|
@ -696,17 +735,12 @@ void XMesaDestroyVisual( XMesaVisual v )
|
|||
|
||||
|
||||
/**
|
||||
* Do one-time initializations.
|
||||
* Do per-display initializations.
|
||||
*/
|
||||
void
|
||||
xmesa_init( Display *display )
|
||||
{
|
||||
static GLboolean firstTime = GL_TRUE;
|
||||
if (firstTime) {
|
||||
pipe_mutex_init(_xmesa_lock);
|
||||
screen = driver.create_pipe_screen( display );
|
||||
firstTime = GL_FALSE;
|
||||
}
|
||||
xmesa_init_display(display);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -720,51 +754,33 @@ xmesa_init( Display *display )
|
|||
PUBLIC
|
||||
XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
|
||||
{
|
||||
struct pipe_context *pipe = NULL;
|
||||
XMesaDisplay xmdpy = xmesa_init_display(v->display);
|
||||
XMesaContext c;
|
||||
GLcontext *mesaCtx;
|
||||
uint pf;
|
||||
|
||||
xmesa_init( v->display );
|
||||
if (!xmdpy)
|
||||
return NULL;
|
||||
|
||||
/* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
|
||||
c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
|
||||
if (!c)
|
||||
return NULL;
|
||||
|
||||
pf = choose_pixel_format(v);
|
||||
assert(pf);
|
||||
|
||||
c->xm_visual = v;
|
||||
c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
|
||||
c->xm_read_buffer = NULL;
|
||||
|
||||
if (screen == NULL)
|
||||
goto fail;
|
||||
|
||||
/* Trace screen knows how to properly wrap context creation in the
|
||||
* wrapped screen, so nothing special to do here:
|
||||
*/
|
||||
pipe = screen->context_create(screen, (void *) c);
|
||||
if (pipe == NULL)
|
||||
goto fail;
|
||||
|
||||
c->st = st_create_context(pipe,
|
||||
&v->mesa_visual,
|
||||
share_list ? share_list->st : NULL);
|
||||
c->st = stapi->create_context(stapi, xmdpy->smapi,
|
||||
&v->stvis, (share_list) ? share_list->st : NULL);
|
||||
if (c->st == NULL)
|
||||
goto fail;
|
||||
|
||||
mesaCtx = c->st->ctx;
|
||||
c->st->ctx->DriverCtx = c;
|
||||
c->st->st_manager_private = (void *) c;
|
||||
|
||||
return c;
|
||||
|
||||
fail:
|
||||
if (c->st)
|
||||
st_destroy_context(c->st);
|
||||
else if (pipe)
|
||||
pipe->destroy(pipe);
|
||||
c->st->destroy(c->st);
|
||||
|
||||
free(c);
|
||||
return NULL;
|
||||
|
|
@ -775,7 +791,7 @@ fail:
|
|||
PUBLIC
|
||||
void XMesaDestroyContext( XMesaContext c )
|
||||
{
|
||||
st_destroy_context(c->st);
|
||||
c->st->destroy(c->st);
|
||||
|
||||
/* FIXME: We should destroy the screen here, but if we do so, surfaces may
|
||||
* outlive it, causing segfaults
|
||||
|
|
@ -881,7 +897,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
|
|||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
XMesaBuffer b;
|
||||
GLuint width, height;
|
||||
|
||||
assert(v);
|
||||
|
||||
|
|
@ -889,19 +904,18 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
|
|||
if (!b)
|
||||
return NULL;
|
||||
|
||||
/* get pixmap size, update framebuffer/renderbuffer dims */
|
||||
xmesa_get_window_size(v->display, b, &width, &height);
|
||||
_mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
|
||||
/* get pixmap size */
|
||||
xmesa_get_window_size(v->display, b, &b->width, &b->height);
|
||||
|
||||
if (target == 0) {
|
||||
/* examine dims */
|
||||
if (ctx->Extensions.ARB_texture_non_power_of_two) {
|
||||
target = GLX_TEXTURE_2D_EXT;
|
||||
}
|
||||
else if ( _mesa_bitcount(width) == 1
|
||||
&& _mesa_bitcount(height) == 1) {
|
||||
else if ( _mesa_bitcount(b->width) == 1
|
||||
&& _mesa_bitcount(b->height) == 1) {
|
||||
/* power of two size */
|
||||
if (height == 1) {
|
||||
if (b->height == 1) {
|
||||
target = GLX_TEXTURE_1D_EXT;
|
||||
}
|
||||
else {
|
||||
|
|
@ -974,25 +988,22 @@ XMesaDestroyBuffer(XMesaBuffer b)
|
|||
|
||||
|
||||
/**
|
||||
* Query the current window size and update the corresponding GLframebuffer
|
||||
* and all attached renderbuffers.
|
||||
* Called when:
|
||||
* 1. the first time a buffer is bound to a context.
|
||||
* 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too...
|
||||
* Note: it's possible (and legal) for xmctx to be NULL. That can happen
|
||||
* when resizing a buffer when no rendering context is bound.
|
||||
* Query the current drawable size and notify the binding context.
|
||||
*/
|
||||
void
|
||||
xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
|
||||
xmesa_check_buffer_size(XMesaBuffer b)
|
||||
{
|
||||
GLuint width, height;
|
||||
xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
|
||||
st_resize_framebuffer(drawBuffer->stfb, width, height);
|
||||
XMesaContext xmctx = XMesaGetCurrentContext();
|
||||
|
||||
if (b->type == PBUFFER)
|
||||
return;
|
||||
|
||||
xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height);
|
||||
if (xmctx && xmctx->xm_buffer == b)
|
||||
xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Bind buffer b to context c and make c the current rendering context.
|
||||
*/
|
||||
|
|
@ -1017,22 +1028,21 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
|
|||
c->xm_read_buffer == readBuffer)
|
||||
return GL_TRUE;
|
||||
|
||||
xmesa_check_buffer_size(drawBuffer);
|
||||
if (readBuffer != drawBuffer)
|
||||
xmesa_check_buffer_size(readBuffer);
|
||||
|
||||
c->xm_buffer = drawBuffer;
|
||||
c->xm_read_buffer = readBuffer;
|
||||
|
||||
st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb,
|
||||
&drawBuffer->ws);
|
||||
|
||||
xmesa_check_and_update_buffer_size(c, drawBuffer);
|
||||
if (readBuffer != drawBuffer)
|
||||
xmesa_check_and_update_buffer_size(c, readBuffer);
|
||||
stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb);
|
||||
|
||||
/* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
|
||||
drawBuffer->wasCurrent = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
/* Detach */
|
||||
st_make_current( NULL, NULL, NULL, NULL );
|
||||
stapi->make_current(stapi, NULL, NULL, NULL);
|
||||
|
||||
}
|
||||
return GL_TRUE;
|
||||
|
|
@ -1051,14 +1061,8 @@ GLboolean XMesaUnbindContext( XMesaContext c )
|
|||
|
||||
XMesaContext XMesaGetCurrentContext( void )
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
if (ctx) {
|
||||
XMesaContext xmesa = xmesa_context(ctx);
|
||||
return xmesa;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
struct st_context_iface *st = stapi->get_current(stapi);
|
||||
return (XMesaContext) (st) ? st->st_manager_private : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1070,17 +1074,17 @@ XMesaContext XMesaGetCurrentContext( void )
|
|||
PUBLIC
|
||||
void XMesaSwapBuffers( XMesaBuffer b )
|
||||
{
|
||||
struct pipe_surface *frontLeftSurf;
|
||||
XMesaContext xmctx = XMesaGetCurrentContext();
|
||||
|
||||
st_swapbuffers(b->stfb, &frontLeftSurf, NULL);
|
||||
|
||||
if (frontLeftSurf) {
|
||||
screen->flush_frontbuffer( screen,
|
||||
frontLeftSurf,
|
||||
&b->ws );
|
||||
if (xmctx && xmctx->xm_buffer == b) {
|
||||
xmctx->st->flush( xmctx->st,
|
||||
PIPE_FLUSH_RENDER_CACHE |
|
||||
PIPE_FLUSH_SWAPBUFFERS |
|
||||
PIPE_FLUSH_FRAME,
|
||||
NULL);
|
||||
}
|
||||
|
||||
xmesa_check_and_update_buffer_size(NULL, b);
|
||||
xmesa_swap_st_framebuffer(b->stfb);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1090,21 +1094,9 @@ void XMesaSwapBuffers( XMesaBuffer b )
|
|||
*/
|
||||
void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
|
||||
{
|
||||
struct pipe_surface *surf_front;
|
||||
struct pipe_surface *surf_back;
|
||||
struct pipe_context *pipe = NULL; /* XXX fix */
|
||||
|
||||
st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front);
|
||||
st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back);
|
||||
|
||||
if (!surf_front || !surf_back)
|
||||
return;
|
||||
|
||||
assert(pipe);
|
||||
pipe->surface_copy(pipe,
|
||||
surf_front, x, y, /* dest */
|
||||
surf_back, x, y, /* src */
|
||||
width, height);
|
||||
xmesa_copy_st_framebuffer(b->stfb,
|
||||
ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT,
|
||||
x, y, width, height);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1112,7 +1104,14 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
|
|||
void XMesaFlush( XMesaContext c )
|
||||
{
|
||||
if (c && c->xm_visual->display) {
|
||||
st_finish(c->st);
|
||||
XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
|
||||
struct pipe_fence_handle *fence = NULL;
|
||||
|
||||
c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
|
||||
if (fence) {
|
||||
xmdpy->screen->fence_finish(xmdpy->screen, fence, 0);
|
||||
xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
|
||||
}
|
||||
XSync( c->xm_visual->display, False );
|
||||
}
|
||||
}
|
||||
|
|
@ -1186,3 +1185,10 @@ XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask)
|
||||
{
|
||||
if (dst->st->copy)
|
||||
dst->st->copy(dst->st, src->st, mask);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,7 @@ and create a window, you must do the following to use the X/Mesa interface:
|
|||
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "state_tracker/st_context.h"
|
||||
#include "state_tracker/st_public.h"
|
||||
#include "state_tracker/st_api.h"
|
||||
#include "os/os_thread.h"
|
||||
|
||||
#include "state_tracker/xlib_sw_winsys.h"
|
||||
|
|
@ -68,11 +67,22 @@ and create a window, you must do the following to use the X/Mesa interface:
|
|||
# include <X11/Xlibint.h>
|
||||
# include <X11/Xutil.h>
|
||||
|
||||
typedef struct xmesa_display *XMesaDisplay;
|
||||
typedef struct xmesa_buffer *XMesaBuffer;
|
||||
typedef struct xmesa_context *XMesaContext;
|
||||
typedef struct xmesa_visual *XMesaVisual;
|
||||
|
||||
|
||||
struct xmesa_display {
|
||||
pipe_mutex mutex;
|
||||
|
||||
Display *display;
|
||||
struct pipe_screen *screen;
|
||||
struct st_manager *smapi;
|
||||
|
||||
struct pipe_context *pipe;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Create a new X/Mesa visual.
|
||||
|
|
@ -258,16 +268,13 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
|
|||
int format, int target, int mipmap);
|
||||
|
||||
|
||||
extern void
|
||||
XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask);
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*/
|
||||
|
||||
extern pipe_mutex _xmesa_lock;
|
||||
|
||||
extern struct xmesa_buffer *XMesaBufferList;
|
||||
|
||||
|
||||
/**
|
||||
* Visual inforation, derived from GLvisual.
|
||||
* Basically corresponds to an XVisualInfo.
|
||||
|
|
@ -280,6 +287,8 @@ struct xmesa_visual {
|
|||
GLint BitsPerPixel; /* True bits per pixel for XImages */
|
||||
|
||||
GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */
|
||||
|
||||
struct st_visual stvis;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -288,7 +297,7 @@ struct xmesa_visual {
|
|||
* Basically corresponds to a GLXContext.
|
||||
*/
|
||||
struct xmesa_context {
|
||||
struct st_context *st;
|
||||
struct st_context_iface *st;
|
||||
XMesaVisual xm_visual; /** pixel format info */
|
||||
XMesaBuffer xm_buffer; /** current drawbuffer */
|
||||
XMesaBuffer xm_read_buffer; /** current readbuffer */
|
||||
|
|
@ -311,7 +320,7 @@ typedef enum {
|
|||
* Basically corresponds to a GLXDrawable.
|
||||
*/
|
||||
struct xmesa_buffer {
|
||||
struct st_framebuffer *stfb;
|
||||
struct st_framebuffer_iface *stfb;
|
||||
struct xlib_drawable ws;
|
||||
|
||||
GLboolean wasCurrent; /* was ever the current buffer? */
|
||||
|
|
@ -335,33 +344,15 @@ struct xmesa_buffer {
|
|||
GLint TextureMipmap; /** 0 or 1 */
|
||||
|
||||
struct xmesa_buffer *Next; /* Linked list pointer: */
|
||||
|
||||
unsigned width, height;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static INLINE XMesaContext
|
||||
xmesa_context(GLcontext *ctx)
|
||||
{
|
||||
return (XMesaContext) ctx->DriverCtx;
|
||||
}
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static INLINE XMesaBuffer
|
||||
xmesa_buffer(GLframebuffer *fb)
|
||||
{
|
||||
struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
|
||||
return (XMesaBuffer) st_framebuffer_private(stfb);
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
xmesa_init(Display *dpy);
|
||||
|
||||
extern void
|
||||
xmesa_delete_framebuffer(struct gl_framebuffer *fb);
|
||||
|
||||
extern XMesaBuffer
|
||||
xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis);
|
||||
|
||||
|
|
@ -370,7 +361,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b,
|
|||
GLuint *width, GLuint *height);
|
||||
|
||||
extern void
|
||||
xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer);
|
||||
xmesa_check_buffer_size(XMesaBuffer b);
|
||||
|
||||
extern void
|
||||
xmesa_destroy_buffers_on_display(Display *dpy);
|
||||
|
|
@ -378,13 +369,13 @@ xmesa_destroy_buffers_on_display(Display *dpy);
|
|||
static INLINE GLuint
|
||||
xmesa_buffer_width(XMesaBuffer b)
|
||||
{
|
||||
return b->stfb->Base.Width;
|
||||
return b->width;
|
||||
}
|
||||
|
||||
static INLINE GLuint
|
||||
xmesa_buffer_height(XMesaBuffer b)
|
||||
{
|
||||
return b->stfb->Base.Height;
|
||||
return b->height;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,19 +26,23 @@
|
|||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef XM_WINSYS_H
|
||||
#define XM_WINSYS_H
|
||||
#ifndef XM_PUBLIC_H
|
||||
#define XM_PUBLIC_H
|
||||
|
||||
struct xm_driver;
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
struct pipe_screen;
|
||||
struct st_api;
|
||||
|
||||
/* This is the driver interface required by the glx/xlib state tracker.
|
||||
*/
|
||||
struct xm_driver {
|
||||
struct pipe_screen *(*create_pipe_screen)( Display *display );
|
||||
struct st_api *(*create_st_api)( void );
|
||||
};
|
||||
|
||||
extern void
|
||||
xmesa_set_driver( const struct xm_driver *driver );
|
||||
|
||||
|
||||
#endif
|
||||
#endif /* XM_PUBLIC_H */
|
||||
|
|
|
|||
332
src/gallium/state_trackers/glx/xlib/xm_st.c
Normal file
332
src/gallium/state_trackers/glx/xlib/xm_st.c
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL 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:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
#include "xm_api.h"
|
||||
#include "xm_st.h"
|
||||
|
||||
struct xmesa_st_framebuffer {
|
||||
XMesaDisplay display;
|
||||
XMesaBuffer buffer;
|
||||
struct pipe_screen *screen;
|
||||
|
||||
struct st_visual stvis;
|
||||
|
||||
unsigned texture_width, texture_height, texture_mask;
|
||||
struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
|
||||
|
||||
struct pipe_surface *display_surface;
|
||||
};
|
||||
|
||||
static INLINE struct xmesa_st_framebuffer *
|
||||
xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
return (struct xmesa_st_framebuffer *) stfbi->st_manager_private;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an attachment to the xlib_drawable of the framebuffer.
|
||||
*/
|
||||
static boolean
|
||||
xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi,
|
||||
enum st_attachment_type statt)
|
||||
{
|
||||
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||
struct pipe_texture *ptex = xstfb->textures[statt];
|
||||
struct pipe_surface *psurf;
|
||||
|
||||
if (!ptex)
|
||||
return TRUE;
|
||||
|
||||
psurf = xstfb->display_surface;
|
||||
/* (re)allocate the surface for the texture to be displayed */
|
||||
if (!psurf || psurf->texture != ptex) {
|
||||
pipe_surface_reference(&xstfb->display_surface, NULL);
|
||||
|
||||
psurf = xstfb->screen->get_tex_surface(xstfb->screen,
|
||||
ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ);
|
||||
if (!psurf)
|
||||
return FALSE;
|
||||
|
||||
xstfb->display_surface = psurf;
|
||||
}
|
||||
|
||||
xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents between the attachments.
|
||||
*/
|
||||
static void
|
||||
xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi,
|
||||
enum st_attachment_type src_statt,
|
||||
enum st_attachment_type dst_statt,
|
||||
unsigned x, unsigned y,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||
struct pipe_texture *src_ptex = xstfb->textures[src_statt];
|
||||
struct pipe_texture *dst_ptex = xstfb->textures[dst_statt];
|
||||
struct pipe_surface *src, *dst;
|
||||
struct pipe_context *pipe;
|
||||
|
||||
if (!src_ptex || !dst_ptex)
|
||||
return;
|
||||
|
||||
pipe = xstfb->display->pipe;
|
||||
if (!pipe) {
|
||||
pipe = xstfb->screen->context_create(xstfb->screen, NULL);
|
||||
if (!pipe)
|
||||
return;
|
||||
xstfb->display->pipe = pipe;
|
||||
}
|
||||
|
||||
src = xstfb->screen->get_tex_surface(xstfb->screen,
|
||||
src_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
|
||||
dst = xstfb->screen->get_tex_surface(xstfb->screen,
|
||||
dst_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||
|
||||
if (src && dst)
|
||||
pipe->surface_copy(pipe, dst, x, y, src, x, y, width, height);
|
||||
|
||||
pipe_surface_reference(&src, NULL);
|
||||
pipe_surface_reference(&dst, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove outdated textures and create the requested ones.
|
||||
*/
|
||||
static void
|
||||
xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
|
||||
unsigned width, unsigned height,
|
||||
unsigned mask)
|
||||
{
|
||||
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||
struct pipe_texture templ;
|
||||
unsigned i;
|
||||
|
||||
/* remove outdated textures */
|
||||
if (xstfb->texture_width != width || xstfb->texture_height != height) {
|
||||
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
|
||||
pipe_texture_reference(&xstfb->textures[i], NULL);
|
||||
}
|
||||
|
||||
memset(&templ, 0, sizeof(templ));
|
||||
templ.target = PIPE_TEXTURE_2D;
|
||||
templ.width0 = width;
|
||||
templ.height0 = height;
|
||||
templ.depth0 = 1;
|
||||
templ.last_level = 0;
|
||||
|
||||
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
|
||||
enum pipe_format format;
|
||||
unsigned tex_usage;
|
||||
|
||||
/* the texture already exists or not requested */
|
||||
if (xstfb->textures[i] || !(mask & (1 << i))) {
|
||||
/* remember the texture */
|
||||
if (xstfb->textures[i])
|
||||
mask |= (1 << i);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
case ST_ATTACHMENT_FRONT_LEFT:
|
||||
case ST_ATTACHMENT_BACK_LEFT:
|
||||
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||
case ST_ATTACHMENT_BACK_RIGHT:
|
||||
format = xstfb->stvis.color_format;
|
||||
tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
|
||||
PIPE_TEXTURE_USAGE_RENDER_TARGET;
|
||||
break;
|
||||
case ST_ATTACHMENT_DEPTH_STENCIL:
|
||||
format = xstfb->stvis.depth_stencil_format;
|
||||
tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
|
||||
break;
|
||||
default:
|
||||
format = PIPE_FORMAT_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (format != PIPE_FORMAT_NONE) {
|
||||
templ.format = format;
|
||||
templ.tex_usage = tex_usage;
|
||||
|
||||
xstfb->textures[i] =
|
||||
xstfb->screen->texture_create(xstfb->screen, &templ);
|
||||
}
|
||||
}
|
||||
|
||||
xstfb->texture_width = width;
|
||||
xstfb->texture_height = height;
|
||||
xstfb->texture_mask = mask;
|
||||
}
|
||||
|
||||
static boolean
|
||||
xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
|
||||
const enum st_attachment_type *statts,
|
||||
unsigned count,
|
||||
struct pipe_texture **out)
|
||||
{
|
||||
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||
unsigned statt_mask, new_mask, i;
|
||||
boolean resized;
|
||||
|
||||
statt_mask = 0x0;
|
||||
for (i = 0; i < count; i++)
|
||||
statt_mask |= 1 << statts[i];
|
||||
/* record newly allocated textures */
|
||||
new_mask = statt_mask & ~xstfb->texture_mask;
|
||||
|
||||
resized = (xstfb->buffer->width != xstfb->texture_width ||
|
||||
xstfb->buffer->height != xstfb->texture_height);
|
||||
|
||||
/* revalidate textures */
|
||||
if (resized || new_mask) {
|
||||
xmesa_st_framebuffer_validate_textures(stfbi,
|
||||
xstfb->buffer->width, xstfb->buffer->height, statt_mask);
|
||||
|
||||
if (!resized) {
|
||||
enum st_attachment_type back, front;
|
||||
|
||||
back = ST_ATTACHMENT_BACK_LEFT;
|
||||
front = ST_ATTACHMENT_FRONT_LEFT;
|
||||
/* copy the contents if front is newly allocated and back is not */
|
||||
if ((statt_mask & (1 << back)) &&
|
||||
(new_mask & (1 << front)) &&
|
||||
!(new_mask & (1 << back))) {
|
||||
xmesa_st_framebuffer_copy_textures(stfbi, back, front,
|
||||
0, 0, xstfb->texture_width, xstfb->texture_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
out[i] = NULL;
|
||||
pipe_texture_reference(&out[i], xstfb->textures[statts[i]]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static boolean
|
||||
xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
|
||||
enum st_attachment_type statt)
|
||||
{
|
||||
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||
boolean ret;
|
||||
|
||||
ret = xmesa_st_framebuffer_display(stfbi, statt);
|
||||
if (ret)
|
||||
xmesa_check_buffer_size(xstfb->buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct st_framebuffer_iface *
|
||||
xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b)
|
||||
{
|
||||
struct st_framebuffer_iface *stfbi;
|
||||
struct xmesa_st_framebuffer *xstfb;
|
||||
|
||||
assert(xmdpy->display == b->xm_visual->display);
|
||||
|
||||
stfbi = CALLOC_STRUCT(st_framebuffer_iface);
|
||||
xstfb = CALLOC_STRUCT(xmesa_st_framebuffer);
|
||||
if (!stfbi || !xstfb) {
|
||||
if (stfbi)
|
||||
FREE(stfbi);
|
||||
if (xstfb)
|
||||
FREE(xstfb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xstfb->display = xmdpy;
|
||||
xstfb->buffer = b;
|
||||
xstfb->screen = xmdpy->screen;
|
||||
xstfb->stvis = b->xm_visual->stvis;
|
||||
|
||||
stfbi->visual = &xstfb->stvis;
|
||||
stfbi->flush_front = xmesa_st_framebuffer_flush_front;
|
||||
stfbi->validate = xmesa_st_framebuffer_validate;
|
||||
stfbi->st_manager_private = (void *) xstfb;
|
||||
|
||||
return stfbi;
|
||||
}
|
||||
|
||||
void
|
||||
xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||
int i;
|
||||
|
||||
pipe_surface_reference(&xstfb->display_surface, NULL);
|
||||
|
||||
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
|
||||
pipe_texture_reference(&xstfb->textures[i], NULL);
|
||||
|
||||
FREE(xstfb);
|
||||
FREE(stfbi);
|
||||
}
|
||||
|
||||
void
|
||||
xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
|
||||
boolean ret;
|
||||
|
||||
ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT);
|
||||
if (ret) {
|
||||
struct pipe_texture **front, **back, *tmp;
|
||||
|
||||
front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT];
|
||||
back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT];
|
||||
/* swap textures only if the front texture has been allocated */
|
||||
if (*front) {
|
||||
tmp = *front;
|
||||
*front = *back;
|
||||
*back = tmp;
|
||||
}
|
||||
|
||||
xmesa_check_buffer_size(xstfb->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
|
||||
enum st_attachment_type src,
|
||||
enum st_attachment_type dst,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h);
|
||||
if (dst == ST_ATTACHMENT_FRONT_LEFT)
|
||||
xmesa_st_framebuffer_display(stfbi, dst);
|
||||
}
|
||||
51
src/gallium/state_trackers/glx/xlib/xm_st.h
Normal file
51
src/gallium/state_trackers/glx/xlib/xm_st.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL 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:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#ifndef _XM_ST_H_
|
||||
#define _XM_ST_H_
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "state_tracker/st_api.h"
|
||||
|
||||
#include "xm_api.h"
|
||||
|
||||
struct st_framebuffer_iface *
|
||||
xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b);
|
||||
|
||||
void
|
||||
xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
|
||||
|
||||
void
|
||||
xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi);
|
||||
|
||||
void
|
||||
xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
|
||||
enum st_attachment_type src,
|
||||
enum st_attachment_type dst,
|
||||
int x, int y, int w, int h);
|
||||
|
||||
#endif /* _XM_ST_H_ */
|
||||
|
|
@ -25,6 +25,7 @@ VG_SOURCES = \
|
|||
api_transform.c \
|
||||
vgu.c \
|
||||
vg_context.c \
|
||||
vg_manager.c \
|
||||
vg_state.c \
|
||||
vg_tracker.c \
|
||||
vg_translate.c \
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "VG/openvg.h"
|
||||
|
||||
#include "vg_manager.h"
|
||||
#include "vg_context.h"
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
|
|
@ -55,6 +56,8 @@ void vgFlush(void)
|
|||
|
||||
pipe = ctx->pipe;
|
||||
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
|
||||
|
||||
vg_manager_flush_frontbuffer(ctx);
|
||||
}
|
||||
|
||||
void vgFinish(void)
|
||||
|
|
|
|||
|
|
@ -117,10 +117,6 @@ clear_with_quad(struct vg_context *st, float x0, float y0,
|
|||
x1, y1);
|
||||
*/
|
||||
|
||||
if (st->pipe->screen && st->pipe->screen->update_buffer)
|
||||
st->pipe->screen->update_buffer( st->pipe->screen,
|
||||
st->pipe->priv );
|
||||
|
||||
cso_save_blend(st->cso_context);
|
||||
cso_save_rasterizer(st->cso_context);
|
||||
cso_save_fragment_shader(st->cso_context);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "shader.h"
|
||||
#include "asm_util.h"
|
||||
#include "st_inlines.h"
|
||||
#include "vg_manager.h"
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
|
@ -305,6 +306,8 @@ static void update_clip_state(struct vg_context *ctx)
|
|||
|
||||
void vg_validate_state(struct vg_context *ctx)
|
||||
{
|
||||
vg_manager_validate_framebuffer(ctx);
|
||||
|
||||
if ((ctx->state.dirty & BLEND_DIRTY)) {
|
||||
struct pipe_blend_state *blend = &ctx->state.g3d.blend;
|
||||
memset(blend, 0, sizeof(struct pipe_blend_state));
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "pipe/p_state.h"
|
||||
#include "util/u_pointer.h"
|
||||
#include "util/u_math.h"
|
||||
#include "state_tracker/st_api.h"
|
||||
|
||||
#include "cso_cache/cso_hash.h"
|
||||
#include "cso_cache/cso_context.h"
|
||||
|
|
@ -58,6 +59,9 @@ struct st_framebuffer {
|
|||
|
||||
struct pipe_texture *blend_texture;
|
||||
|
||||
struct st_framebuffer_iface *iface;
|
||||
enum st_attachment_type strb_att;
|
||||
|
||||
void *privateData;
|
||||
};
|
||||
|
||||
|
|
@ -84,6 +88,8 @@ enum dirty_state {
|
|||
|
||||
struct vg_context
|
||||
{
|
||||
struct st_context_iface iface;
|
||||
|
||||
struct pipe_context *pipe;
|
||||
|
||||
struct {
|
||||
|
|
@ -101,6 +107,7 @@ struct vg_context
|
|||
VGErrorCode _error;
|
||||
|
||||
struct st_framebuffer *draw_buffer;
|
||||
int32_t draw_buffer_invalid;
|
||||
|
||||
struct cso_hash *owned_objects[VG_OBJECT_LAST];
|
||||
|
||||
|
|
|
|||
373
src/gallium/state_trackers/vega/vg_manager.c
Normal file
373
src/gallium/state_trackers/vega/vg_manager.c
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL 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:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#include "state_tracker/st_api.h"
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_screen.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
#include "vg_manager.h"
|
||||
#include "vg_context.h"
|
||||
#include "vg_tracker.h" /* for st_resize_framebuffer */
|
||||
#include "image.h"
|
||||
|
||||
/**
|
||||
* Flush the front buffer if the current context renders to the front buffer.
|
||||
*/
|
||||
void
|
||||
vg_manager_flush_frontbuffer(struct vg_context *ctx)
|
||||
{
|
||||
struct st_framebuffer *stfb = ctx->draw_buffer;
|
||||
|
||||
if (!stfb)
|
||||
return;
|
||||
|
||||
/* st_public.h is used */
|
||||
if (!stfb->iface) {
|
||||
struct pipe_screen *screen = ctx->pipe->screen;
|
||||
if (screen->flush_frontbuffer) {
|
||||
screen->flush_frontbuffer(screen,
|
||||
stfb->strb->surface, ctx->pipe->priv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (stfb->strb_att) {
|
||||
case ST_ATTACHMENT_FRONT_LEFT:
|
||||
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||
stfb->iface->flush_front(stfb->iface, stfb->strb_att);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-validate the framebuffer.
|
||||
*/
|
||||
void
|
||||
vg_manager_validate_framebuffer(struct vg_context *ctx)
|
||||
{
|
||||
struct pipe_screen *screen = ctx->pipe->screen;
|
||||
struct st_framebuffer *stfb = ctx->draw_buffer;
|
||||
struct st_renderbuffer *rb;
|
||||
struct pipe_texture *pt;
|
||||
|
||||
/* no binding surface */
|
||||
if (!stfb)
|
||||
return;
|
||||
|
||||
/* st_public.h is used */
|
||||
if (!stfb->iface) {
|
||||
struct pipe_screen *screen = ctx->pipe->screen;
|
||||
if (screen->update_buffer)
|
||||
screen->update_buffer(screen, ctx->pipe->priv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!p_atomic_read(&ctx->draw_buffer_invalid))
|
||||
return;
|
||||
|
||||
/* validate the fb */
|
||||
if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt)
|
||||
return;
|
||||
|
||||
rb = stfb->strb;
|
||||
if (rb->texture == pt) {
|
||||
pipe_texture_reference(&pt, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* unreference existing ones */
|
||||
pipe_surface_reference(&rb->surface, NULL);
|
||||
pipe_texture_reference(&rb->texture, NULL);
|
||||
|
||||
rb->texture = pt;
|
||||
rb->surface = screen->get_tex_surface(screen, rb->texture, 0, 0, 0,
|
||||
PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||
|
||||
rb->width = rb->surface->width;
|
||||
rb->height = rb->surface->height;
|
||||
|
||||
st_resize_framebuffer(stfb, rb->width, rb->height);
|
||||
|
||||
p_atomic_set(&ctx->draw_buffer_invalid, FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vg_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
|
||||
struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||
p_atomic_set(&ctx->draw_buffer_invalid, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
vg_context_flush(struct st_context_iface *stctxi, unsigned flags,
|
||||
struct pipe_fence_handle **fence)
|
||||
{
|
||||
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||
ctx->pipe->flush(ctx->pipe, flags, fence);
|
||||
if (flags & PIPE_FLUSH_RENDER_CACHE)
|
||||
vg_manager_flush_frontbuffer(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
vg_context_destroy(struct st_context_iface *stctxi)
|
||||
{
|
||||
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||
vg_destroy_context(ctx);
|
||||
}
|
||||
|
||||
static struct st_context_iface *
|
||||
vg_api_create_context(struct st_api *stapi, struct st_manager *smapi,
|
||||
const struct st_visual *visual,
|
||||
struct st_context_iface *shared_stctxi)
|
||||
{
|
||||
struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi;
|
||||
struct vg_context *ctx;
|
||||
struct pipe_context *pipe;
|
||||
|
||||
pipe = smapi->screen->context_create(smapi->screen, NULL);
|
||||
if (!pipe)
|
||||
return NULL;
|
||||
ctx = vg_create_context(pipe, NULL, shared_ctx);
|
||||
if (!ctx) {
|
||||
pipe->destroy(pipe);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iface.destroy = vg_context_destroy;
|
||||
|
||||
ctx->iface.notify_invalid_framebuffer =
|
||||
vg_context_notify_invalid_framebuffer;
|
||||
ctx->iface.flush = vg_context_flush;
|
||||
|
||||
ctx->iface.teximage = NULL;
|
||||
ctx->iface.copy = NULL;
|
||||
|
||||
ctx->iface.st_context_private = (void *) smapi;
|
||||
|
||||
return &ctx->iface;
|
||||
}
|
||||
|
||||
static struct st_renderbuffer *
|
||||
create_renderbuffer(enum pipe_format format)
|
||||
{
|
||||
struct st_renderbuffer *strb;
|
||||
|
||||
strb = CALLOC_STRUCT(st_renderbuffer);
|
||||
if (strb)
|
||||
strb->format = format;
|
||||
|
||||
return strb;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_renderbuffer(struct st_renderbuffer *strb)
|
||||
{
|
||||
pipe_surface_reference(&strb->surface, NULL);
|
||||
pipe_texture_reference(&strb->texture, NULL);
|
||||
free(strb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide the buffer to render to.
|
||||
*/
|
||||
static enum st_attachment_type
|
||||
choose_attachment(struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
enum st_attachment_type statt;
|
||||
|
||||
statt = stfbi->visual->render_buffer;
|
||||
if (statt != ST_ATTACHMENT_INVALID) {
|
||||
/* use the buffer given by the visual, unless it is unavailable */
|
||||
if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) {
|
||||
switch (statt) {
|
||||
case ST_ATTACHMENT_BACK_LEFT:
|
||||
statt = ST_ATTACHMENT_FRONT_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_RIGHT:
|
||||
statt = ST_ATTACHMENT_FRONT_RIGHT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!st_visual_have_buffers(stfbi->visual, 1 << statt))
|
||||
statt = ST_ATTACHMENT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return statt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the context to the given framebuffers.
|
||||
*/
|
||||
static boolean
|
||||
vg_context_bind_framebuffers(struct st_context_iface *stctxi,
|
||||
struct st_framebuffer_iface *stdrawi,
|
||||
struct st_framebuffer_iface *streadi)
|
||||
{
|
||||
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||
struct st_framebuffer *stfb;
|
||||
enum st_attachment_type strb_att;
|
||||
|
||||
/* the draw and read framebuffers must be the same */
|
||||
if (stdrawi != streadi)
|
||||
return FALSE;
|
||||
|
||||
p_atomic_set(&ctx->draw_buffer_invalid, TRUE);
|
||||
|
||||
strb_att = (stdrawi) ? choose_attachment(stdrawi) : ST_ATTACHMENT_INVALID;
|
||||
|
||||
if (ctx->draw_buffer) {
|
||||
stfb = ctx->draw_buffer;
|
||||
|
||||
/* free the existing fb */
|
||||
if (!stdrawi ||
|
||||
stfb->strb_att != strb_att ||
|
||||
stfb->strb->format != stdrawi->visual->color_format ||
|
||||
stfb->dsrb->format != stdrawi->visual->depth_stencil_format) {
|
||||
destroy_renderbuffer(stfb->strb);
|
||||
destroy_renderbuffer(stfb->dsrb);
|
||||
free(stfb);
|
||||
|
||||
ctx->draw_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stdrawi)
|
||||
return TRUE;
|
||||
|
||||
if (strb_att == ST_ATTACHMENT_INVALID)
|
||||
return FALSE;
|
||||
|
||||
/* create a new fb */
|
||||
if (!ctx->draw_buffer) {
|
||||
stfb = CALLOC_STRUCT(st_framebuffer);
|
||||
if (!stfb)
|
||||
return FALSE;
|
||||
|
||||
stfb->strb = create_renderbuffer(stdrawi->visual->color_format);
|
||||
if (!stfb->strb) {
|
||||
free(stfb);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
stfb->dsrb = create_renderbuffer(stdrawi->visual->depth_stencil_format);
|
||||
if (!stfb->dsrb) {
|
||||
free(stfb->strb);
|
||||
free(stfb);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
stfb->width = 0;
|
||||
stfb->height = 0;
|
||||
stfb->strb_att = strb_att;
|
||||
|
||||
ctx->draw_buffer = stfb;
|
||||
}
|
||||
|
||||
ctx->draw_buffer->iface = stdrawi;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static boolean
|
||||
vg_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
|
||||
struct st_framebuffer_iface *stdrawi,
|
||||
struct st_framebuffer_iface *streadi)
|
||||
{
|
||||
struct vg_context *ctx = (struct vg_context *) stctxi;
|
||||
|
||||
if (stctxi)
|
||||
vg_context_bind_framebuffers(stctxi, stdrawi, streadi);
|
||||
vg_set_current_context(ctx);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static struct st_context_iface *
|
||||
vg_api_get_current(struct st_api *stapi)
|
||||
{
|
||||
struct vg_context *ctx = vg_current_context();
|
||||
|
||||
return (ctx) ? &ctx->iface : NULL;
|
||||
}
|
||||
|
||||
static boolean
|
||||
vg_api_is_visual_supported(struct st_api *stapi,
|
||||
const struct st_visual *visual)
|
||||
{
|
||||
/* the impl requires a depth/stencil buffer */
|
||||
if (visual->depth_stencil_format == PIPE_FORMAT_NONE)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static st_proc_t
|
||||
vg_api_get_proc_address(struct st_api *stapi, const char *procname)
|
||||
{
|
||||
/* TODO */
|
||||
return (st_proc_t) NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
vg_api_destroy(struct st_api *stapi)
|
||||
{
|
||||
free(stapi);
|
||||
}
|
||||
|
||||
static struct st_api *
|
||||
vg_module_create_api(void)
|
||||
{
|
||||
struct st_api *stapi;
|
||||
|
||||
stapi = CALLOC_STRUCT(st_api);
|
||||
if (stapi) {
|
||||
stapi->destroy = vg_api_destroy;
|
||||
stapi->get_proc_address = vg_api_get_proc_address;
|
||||
stapi->is_visual_supported = vg_api_is_visual_supported;
|
||||
|
||||
stapi->create_context = vg_api_create_context;
|
||||
stapi->make_current = vg_api_make_current;
|
||||
stapi->get_current = vg_api_get_current;
|
||||
}
|
||||
|
||||
return stapi;
|
||||
}
|
||||
|
||||
PUBLIC const struct st_module st_module_OpenVG = {
|
||||
.api = ST_API_OPENVG,
|
||||
.create_api = vg_module_create_api,
|
||||
};
|
||||
40
src/gallium/state_trackers/vega/vg_manager.h
Normal file
40
src/gallium/state_trackers/vega/vg_manager.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL 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:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#ifndef VG_MANAGER_H
|
||||
#define VG_MANAGER_H
|
||||
|
||||
#include "state_tracker/st_api.h"
|
||||
#include "vg_context.h"
|
||||
|
||||
void
|
||||
vg_manager_flush_frontbuffer(struct vg_context *ctx);
|
||||
|
||||
void
|
||||
vg_manager_validate_framebuffer(struct vg_context *ctx);
|
||||
|
||||
#endif /* VG_MANAGER_H */
|
||||
|
|
@ -39,9 +39,15 @@
|
|||
#include "target-helpers/wrap_screen.h"
|
||||
#include "xm_public.h"
|
||||
|
||||
#include "state_tracker/st_manager.h"
|
||||
|
||||
/* advertise OpenGL support */
|
||||
PUBLIC const int st_api_OpenGL = 1;
|
||||
|
||||
PUBLIC const struct st_module st_module_OpenGL = {
|
||||
.api = ST_API_OPENGL,
|
||||
.create_api = st_manager_create_api
|
||||
};
|
||||
|
||||
/* Helper function to build a subset of a driver stack consisting of
|
||||
* one of the software rasterizers (cell, llvmpipe, softpipe) and the
|
||||
|
|
@ -100,9 +106,10 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct xm_driver xlib_driver =
|
||||
static struct xm_driver xlib_driver =
|
||||
{
|
||||
.create_pipe_screen = swrast_xlib_create_screen,
|
||||
.create_st_api = st_manager_create_api,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ if env['platform'] != 'winddk':
|
|||
'state_tracker/st_format.c',
|
||||
'state_tracker/st_framebuffer.c',
|
||||
'state_tracker/st_gen_mipmap.c',
|
||||
'state_tracker/st_manager.c',
|
||||
'state_tracker/st_mesa_to_tgsi.c',
|
||||
'state_tracker/st_program.c',
|
||||
'state_tracker/st_texture.c',
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ STATETRACKER_SOURCES = \
|
|||
state_tracker/st_format.c \
|
||||
state_tracker/st_framebuffer.c \
|
||||
state_tracker/st_gen_mipmap.c \
|
||||
state_tracker/st_manager.c \
|
||||
state_tracker/st_mesa_to_tgsi.c \
|
||||
state_tracker/st_program.c \
|
||||
state_tracker/st_texture.c
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "st_atom.h"
|
||||
#include "st_cb_bitmap.h"
|
||||
#include "st_program.h"
|
||||
#include "st_manager.h"
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
|
||||
|
|
@ -136,9 +137,7 @@ void st_validate_state( struct st_context *st )
|
|||
|
||||
check_program_state( st );
|
||||
|
||||
if (st->pipe->screen->update_buffer)
|
||||
st->pipe->screen->update_buffer(st->pipe->screen,
|
||||
st->pipe->priv);
|
||||
st_manager_validate_framebuffers(st);
|
||||
|
||||
if (state->st == 0)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "st_format.h"
|
||||
#include "st_public.h"
|
||||
#include "st_texture.h"
|
||||
#include "st_manager.h"
|
||||
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_rect.h"
|
||||
|
|
@ -614,8 +615,18 @@ check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
|
|||
static void
|
||||
st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
|
||||
{
|
||||
GLframebuffer *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(ctx->st, fb, idx);
|
||||
}
|
||||
|
||||
check_create_front_buffers(ctx, ctx->DrawBuffer);
|
||||
}
|
||||
|
||||
|
|
@ -626,8 +637,13 @@ st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
|
|||
static void
|
||||
st_ReadBuffer(GLcontext *ctx, GLenum buffer)
|
||||
{
|
||||
GLframebuffer *fb = ctx->ReadBuffer;
|
||||
|
||||
(void) buffer;
|
||||
check_create_front_buffers(ctx, ctx->ReadBuffer);
|
||||
|
||||
/* add the renderbuffer on demand */
|
||||
st_manager_add_color_renderbuffer(ctx->st, fb, fb->_ColorReadBufferIndex);
|
||||
check_create_front_buffers(ctx, fb);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "st_cb_clear.h"
|
||||
#include "st_cb_fbo.h"
|
||||
#include "st_public.h"
|
||||
#include "st_manager.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_screen.h"
|
||||
|
|
@ -74,12 +75,9 @@ display_front_buffer(struct st_context *st)
|
|||
= st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
|
||||
|
||||
if (strb) {
|
||||
struct pipe_surface *front_surf = strb->surface;
|
||||
|
||||
/* Hook for copying "fake" frontbuffer if necessary:
|
||||
*/
|
||||
st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf,
|
||||
st->winsys_drawable_handle );
|
||||
st_manager_flush_frontbuffer(st);
|
||||
|
||||
/*
|
||||
st->frontbuffer_status = FRONT_STATUS_UNDEFINED;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
#include "st_debug.h"
|
||||
#include "st_context.h"
|
||||
#include "st_atom.h"
|
||||
#include "st_cb_readpixels.h"
|
||||
#include "st_cb_fbo.h"
|
||||
#include "st_public.h"
|
||||
|
|
@ -350,6 +351,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
|
|||
/* XXX convolution not done yet */
|
||||
assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
|
||||
|
||||
st_validate_state(ctx->st);
|
||||
|
||||
/* Do all needed clipping here, so that we can forget about it later */
|
||||
if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
|
||||
/* The ReadPixels transfer is totally outside the window bounds */
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@
|
|||
#include "vbo/vbo.h"
|
||||
#include "shader/shader_api.h"
|
||||
#include "glapi/glapi.h"
|
||||
#include "st_context.h"
|
||||
#include "st_public.h"
|
||||
#include "st_debug.h"
|
||||
#include "st_context.h"
|
||||
#include "st_cb_accum.h"
|
||||
#include "st_cb_bitmap.h"
|
||||
#include "st_cb_blit.h"
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "main/mtypes.h"
|
||||
#include "shader/prog_cache.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "state_tracker/st_api.h"
|
||||
|
||||
|
||||
struct st_context;
|
||||
|
|
@ -73,6 +74,8 @@ struct st_tracked_state {
|
|||
|
||||
struct st_context
|
||||
{
|
||||
struct st_context_iface iface;
|
||||
|
||||
GLcontext *ctx;
|
||||
|
||||
struct pipe_context *pipe;
|
||||
|
|
@ -206,6 +209,11 @@ struct st_framebuffer
|
|||
GLframebuffer Base;
|
||||
void *Private;
|
||||
GLuint InitWidth, InitHeight;
|
||||
|
||||
struct st_framebuffer_iface *iface;
|
||||
enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
|
||||
unsigned num_statts;
|
||||
int32_t revalidate;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
799
src/mesa/state_tracker/st_manager.c
Normal file
799
src/mesa/state_tracker/st_manager.c
Normal file
|
|
@ -0,0 +1,799 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL 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:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#include "state_tracker/st_api.h"
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_screen.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_pointer.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_atomic.h"
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "main/context.h"
|
||||
#include "main/texobj.h"
|
||||
#include "main/teximage.h"
|
||||
#include "main/texstate.h"
|
||||
#include "main/texfetch.h"
|
||||
#include "main/fbobject.h"
|
||||
#include "main/framebuffer.h"
|
||||
#include "main/renderbuffer.h"
|
||||
#include "st_texture.h"
|
||||
|
||||
#include "st_context.h"
|
||||
#include "st_format.h"
|
||||
#include "st_cb_fbo.h"
|
||||
#include "st_manager.h"
|
||||
|
||||
/* these functions are defined in st_context.c */
|
||||
struct st_context *
|
||||
st_create_context(struct pipe_context *pipe,
|
||||
const __GLcontextModes *visual,
|
||||
struct st_context *share);
|
||||
void st_destroy_context(struct st_context *st);
|
||||
void st_flush(struct st_context *st, uint pipeFlushFlags,
|
||||
struct pipe_fence_handle **fence);
|
||||
|
||||
/**
|
||||
* Note that this function may fail.
|
||||
*/
|
||||
static INLINE struct st_framebuffer *
|
||||
st_framebuffer(GLframebuffer *fb)
|
||||
{
|
||||
/* FBO cannot be casted. See st_new_framebuffer */
|
||||
return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map an attachment to a buffer index.
|
||||
*/
|
||||
static INLINE gl_buffer_index
|
||||
attachment_to_buffer_index(enum st_attachment_type statt)
|
||||
{
|
||||
gl_buffer_index index;
|
||||
|
||||
switch (statt) {
|
||||
case ST_ATTACHMENT_FRONT_LEFT:
|
||||
index = BUFFER_FRONT_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_LEFT:
|
||||
index = BUFFER_BACK_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||
index = BUFFER_FRONT_RIGHT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_RIGHT:
|
||||
index = BUFFER_BACK_RIGHT;
|
||||
break;
|
||||
case ST_ATTACHMENT_DEPTH_STENCIL:
|
||||
index = BUFFER_DEPTH;
|
||||
break;
|
||||
case ST_ATTACHMENT_ACCUM:
|
||||
index = BUFFER_ACCUM;
|
||||
break;
|
||||
case ST_ATTACHMENT_SAMPLE:
|
||||
default:
|
||||
index = BUFFER_COUNT;
|
||||
break;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a buffer index to an attachment.
|
||||
*/
|
||||
static INLINE enum st_attachment_type
|
||||
buffer_index_to_attachment(gl_buffer_index index)
|
||||
{
|
||||
enum st_attachment_type statt;
|
||||
|
||||
switch (index) {
|
||||
case BUFFER_FRONT_LEFT:
|
||||
statt = ST_ATTACHMENT_FRONT_LEFT;
|
||||
break;
|
||||
case BUFFER_BACK_LEFT:
|
||||
statt = ST_ATTACHMENT_BACK_LEFT;
|
||||
break;
|
||||
case BUFFER_FRONT_RIGHT:
|
||||
statt = ST_ATTACHMENT_FRONT_RIGHT;
|
||||
break;
|
||||
case BUFFER_BACK_RIGHT:
|
||||
statt = ST_ATTACHMENT_BACK_RIGHT;
|
||||
break;
|
||||
case BUFFER_DEPTH:
|
||||
statt = ST_ATTACHMENT_DEPTH_STENCIL;
|
||||
break;
|
||||
case BUFFER_ACCUM:
|
||||
statt = ST_ATTACHMENT_ACCUM;
|
||||
break;
|
||||
default:
|
||||
statt = ST_ATTACHMENT_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
return statt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a framebuffer to make sure up-to-date pipe_textures are used.
|
||||
*/
|
||||
static void
|
||||
st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
|
||||
{
|
||||
struct pipe_screen *screen = st->pipe->screen;
|
||||
struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
|
||||
uint width, height;
|
||||
unsigned i;
|
||||
boolean changed = FALSE;
|
||||
|
||||
if (!p_atomic_read(&stfb->revalidate))
|
||||
return;
|
||||
|
||||
/* validate the fb */
|
||||
if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures))
|
||||
return;
|
||||
|
||||
width = stfb->Base.Width;
|
||||
height = stfb->Base.Height;
|
||||
|
||||
for (i = 0; i < stfb->num_statts; i++) {
|
||||
struct st_renderbuffer *strb;
|
||||
struct pipe_surface *ps;
|
||||
gl_buffer_index idx;
|
||||
|
||||
if (!textures[i])
|
||||
continue;
|
||||
|
||||
idx = attachment_to_buffer_index(stfb->statts[i]);
|
||||
if (idx >= BUFFER_COUNT) {
|
||||
pipe_texture_reference(&textures[i], NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
|
||||
assert(strb);
|
||||
if (strb->texture == textures[i]) {
|
||||
pipe_texture_reference(&textures[i], NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0,
|
||||
PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE);
|
||||
if (ps) {
|
||||
pipe_surface_reference(&strb->surface, ps);
|
||||
pipe_texture_reference(&strb->texture, ps->texture);
|
||||
/* ownership transfered */
|
||||
pipe_surface_reference(&ps, NULL);
|
||||
|
||||
changed = TRUE;
|
||||
|
||||
strb->Base.Width = strb->surface->width;
|
||||
strb->Base.Height = strb->surface->height;
|
||||
|
||||
width = strb->Base.Width;
|
||||
height = strb->Base.Height;
|
||||
}
|
||||
|
||||
pipe_texture_reference(&textures[i], NULL);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
st->dirty.st |= ST_NEW_FRAMEBUFFER;
|
||||
_mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
|
||||
|
||||
assert(stfb->Base.Width == width);
|
||||
assert(stfb->Base.Height == height);
|
||||
}
|
||||
|
||||
p_atomic_set(&stfb->revalidate, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the attachments to validate by looping the existing renderbuffers.
|
||||
*/
|
||||
static void
|
||||
st_framebuffer_update_attachments(struct st_framebuffer *stfb)
|
||||
{
|
||||
gl_buffer_index idx;
|
||||
|
||||
stfb->num_statts = 0;
|
||||
for (idx = 0; idx < BUFFER_COUNT; idx++) {
|
||||
struct st_renderbuffer *strb;
|
||||
enum st_attachment_type statt;
|
||||
|
||||
strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
|
||||
if (!strb || strb->software)
|
||||
continue;
|
||||
|
||||
statt = buffer_index_to_attachment(idx);
|
||||
if (statt != ST_ATTACHMENT_INVALID &&
|
||||
st_visual_have_buffers(stfb->iface->visual, 1 << statt))
|
||||
stfb->statts[stfb->num_statts++] = statt;
|
||||
}
|
||||
|
||||
p_atomic_set(&stfb->revalidate, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a renderbuffer to the framebuffer.
|
||||
*/
|
||||
static boolean
|
||||
st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
|
||||
gl_buffer_index idx)
|
||||
{
|
||||
struct gl_renderbuffer *rb;
|
||||
enum pipe_format format;
|
||||
int samples;
|
||||
boolean sw;
|
||||
|
||||
/* do not distinguish depth/stencil buffers */
|
||||
if (idx == BUFFER_STENCIL)
|
||||
idx = BUFFER_DEPTH;
|
||||
|
||||
switch (idx) {
|
||||
case BUFFER_DEPTH:
|
||||
format = stfb->iface->visual->depth_stencil_format;
|
||||
sw = FALSE;
|
||||
break;
|
||||
case BUFFER_ACCUM:
|
||||
format = stfb->iface->visual->accum_format;
|
||||
sw = TRUE;
|
||||
break;
|
||||
default:
|
||||
format = stfb->iface->visual->color_format;
|
||||
sw = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (format == PIPE_FORMAT_NONE)
|
||||
return FALSE;
|
||||
|
||||
samples = stfb->iface->visual->samples;
|
||||
if (!samples)
|
||||
samples = st_get_msaa();
|
||||
|
||||
rb = st_new_renderbuffer_fb(format, samples, sw);
|
||||
if (!rb)
|
||||
return FALSE;
|
||||
|
||||
if (idx != BUFFER_DEPTH) {
|
||||
_mesa_add_renderbuffer(&stfb->Base, idx, rb);
|
||||
}
|
||||
else {
|
||||
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0))
|
||||
_mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb);
|
||||
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1))
|
||||
_mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intialize a __GLcontextModes from a visual.
|
||||
*/
|
||||
static void
|
||||
st_visual_to_context_mode(const struct st_visual *visual,
|
||||
__GLcontextModes *mode)
|
||||
{
|
||||
memset(mode, 0, sizeof(*mode));
|
||||
|
||||
if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK))
|
||||
mode->doubleBufferMode = GL_TRUE;
|
||||
if (st_visual_have_buffers(visual,
|
||||
ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK))
|
||||
mode->stereoMode = GL_TRUE;
|
||||
|
||||
if (visual->color_format != PIPE_FORMAT_NONE) {
|
||||
mode->rgbMode = GL_TRUE;
|
||||
|
||||
mode->redBits =
|
||||
util_format_get_component_bits(visual->color_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 0);
|
||||
mode->greenBits =
|
||||
util_format_get_component_bits(visual->color_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 1);
|
||||
mode->blueBits =
|
||||
util_format_get_component_bits(visual->color_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 2);
|
||||
mode->alphaBits =
|
||||
util_format_get_component_bits(visual->color_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 3);
|
||||
|
||||
mode->rgbBits = mode->redBits +
|
||||
mode->greenBits + mode->blueBits + mode->alphaBits;
|
||||
}
|
||||
|
||||
if (visual->depth_stencil_format != PIPE_FORMAT_NONE) {
|
||||
mode->haveDepthBuffer = GL_TRUE;
|
||||
mode->haveStencilBuffer = GL_TRUE;
|
||||
|
||||
mode->depthBits =
|
||||
util_format_get_component_bits(visual->depth_stencil_format,
|
||||
UTIL_FORMAT_COLORSPACE_ZS, 0);
|
||||
mode->stencilBits =
|
||||
util_format_get_component_bits(visual->depth_stencil_format,
|
||||
UTIL_FORMAT_COLORSPACE_ZS, 1);
|
||||
}
|
||||
|
||||
if (visual->accum_format != PIPE_FORMAT_NONE) {
|
||||
mode->haveAccumBuffer = GL_TRUE;
|
||||
|
||||
mode->accumRedBits =
|
||||
util_format_get_component_bits(visual->accum_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 0);
|
||||
mode->accumGreenBits =
|
||||
util_format_get_component_bits(visual->accum_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 1);
|
||||
mode->accumBlueBits =
|
||||
util_format_get_component_bits(visual->accum_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 2);
|
||||
mode->accumAlphaBits =
|
||||
util_format_get_component_bits(visual->accum_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 3);
|
||||
}
|
||||
|
||||
if (visual->samples) {
|
||||
mode->sampleBuffers = 1;
|
||||
mode->samples = visual->samples;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the default draw or read buffer from a visual.
|
||||
*/
|
||||
static void
|
||||
st_visual_to_default_buffer(const struct st_visual *visual,
|
||||
GLenum *buffer, GLint *index)
|
||||
{
|
||||
enum st_attachment_type statt;
|
||||
GLenum buf;
|
||||
gl_buffer_index idx;
|
||||
|
||||
statt = visual->render_buffer;
|
||||
/* do nothing if an invalid render buffer is specified */
|
||||
if (statt == ST_ATTACHMENT_INVALID ||
|
||||
!st_visual_have_buffers(visual, 1 << statt))
|
||||
return;
|
||||
|
||||
switch (statt) {
|
||||
case ST_ATTACHMENT_FRONT_LEFT:
|
||||
buf = GL_FRONT_LEFT;
|
||||
idx = BUFFER_FRONT_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_LEFT:
|
||||
buf = GL_BACK_LEFT;
|
||||
idx = BUFFER_BACK_LEFT;
|
||||
break;
|
||||
case ST_ATTACHMENT_FRONT_RIGHT:
|
||||
buf = GL_FRONT_RIGHT;
|
||||
idx = BUFFER_FRONT_RIGHT;
|
||||
break;
|
||||
case ST_ATTACHMENT_BACK_RIGHT:
|
||||
buf = GL_BACK_RIGHT;
|
||||
idx = BUFFER_BACK_RIGHT;
|
||||
break;
|
||||
default:
|
||||
buf = GL_NONE;
|
||||
idx = BUFFER_COUNT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf != GL_NONE) {
|
||||
if (buffer)
|
||||
*buffer = buf;
|
||||
if (index)
|
||||
*index = idx;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a framebuffer from a manager interface.
|
||||
*/
|
||||
static struct st_framebuffer *
|
||||
st_framebuffer_create(struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
struct st_framebuffer *stfb;
|
||||
__GLcontextModes mode;
|
||||
gl_buffer_index idx;
|
||||
|
||||
stfb = CALLOC_STRUCT(st_framebuffer);
|
||||
if (!stfb)
|
||||
return NULL;
|
||||
|
||||
st_visual_to_context_mode(stfbi->visual, &mode);
|
||||
_mesa_initialize_window_framebuffer(&stfb->Base, &mode);
|
||||
|
||||
/* modify the draw/read buffers of the fb */
|
||||
st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0],
|
||||
&stfb->Base._ColorDrawBufferIndexes[0]);
|
||||
st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer,
|
||||
&stfb->Base._ColorReadBufferIndex);
|
||||
|
||||
stfb->iface = stfbi;
|
||||
|
||||
/* add the color buffer */
|
||||
idx = stfb->Base._ColorDrawBufferIndexes[0];
|
||||
if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
|
||||
FREE(stfb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
|
||||
st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
|
||||
|
||||
st_framebuffer_update_attachments(stfb);
|
||||
|
||||
stfb->Base.Initialized = GL_TRUE;
|
||||
|
||||
return stfb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference a framebuffer.
|
||||
*/
|
||||
static void
|
||||
st_framebuffer_reference(struct st_framebuffer **ptr,
|
||||
struct st_framebuffer *stfb)
|
||||
{
|
||||
GLframebuffer *fb = &stfb->Base;
|
||||
_mesa_reference_framebuffer((GLframebuffer **) ptr, fb);
|
||||
}
|
||||
|
||||
static void
|
||||
st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
|
||||
struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
struct st_context *st = (struct st_context *) stctxi;
|
||||
struct st_framebuffer *stfb;
|
||||
|
||||
/* either draw or read winsys fb */
|
||||
stfb = st_framebuffer(st->ctx->WinSysDrawBuffer);
|
||||
if (!stfb || stfb->iface != stfbi)
|
||||
stfb = st_framebuffer(st->ctx->WinSysReadBuffer);
|
||||
assert(stfb && stfb->iface == stfbi);
|
||||
|
||||
p_atomic_set(&stfb->revalidate, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
st_context_flush(struct st_context_iface *stctxi, unsigned flags,
|
||||
struct pipe_fence_handle **fence)
|
||||
{
|
||||
struct st_context *st = (struct st_context *) stctxi;
|
||||
st_flush(st, flags, fence);
|
||||
if (flags & PIPE_FLUSH_RENDER_CACHE)
|
||||
st_manager_flush_frontbuffer(st);
|
||||
}
|
||||
|
||||
static boolean
|
||||
st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target,
|
||||
int level, enum pipe_format internal_format,
|
||||
struct pipe_texture *tex, boolean mipmap)
|
||||
{
|
||||
struct st_context *st = (struct st_context *) stctxi;
|
||||
GLcontext *ctx = st->ctx;
|
||||
struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
|
||||
struct gl_texture_object *texObj;
|
||||
struct gl_texture_image *texImage;
|
||||
struct st_texture_object *stObj;
|
||||
struct st_texture_image *stImage;
|
||||
GLenum internalFormat;
|
||||
|
||||
switch (target) {
|
||||
case ST_TEXTURE_1D:
|
||||
target = GL_TEXTURE_1D;
|
||||
break;
|
||||
case ST_TEXTURE_2D:
|
||||
target = GL_TEXTURE_2D;
|
||||
break;
|
||||
case ST_TEXTURE_3D:
|
||||
target = GL_TEXTURE_3D;
|
||||
break;
|
||||
case ST_TEXTURE_RECT:
|
||||
target = GL_TEXTURE_RECTANGLE_ARB;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (util_format_get_component_bits(internal_format,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
|
||||
internalFormat = GL_RGBA;
|
||||
else
|
||||
internalFormat = GL_RGB;
|
||||
|
||||
texObj = _mesa_select_tex_object(ctx, texUnit, target);
|
||||
_mesa_lock_texture(ctx, texObj);
|
||||
|
||||
stObj = st_texture_object(texObj);
|
||||
/* switch to surface based */
|
||||
if (!stObj->surface_based) {
|
||||
_mesa_clear_texture_object(ctx, texObj);
|
||||
stObj->surface_based = GL_TRUE;
|
||||
}
|
||||
|
||||
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
|
||||
stImage = st_texture_image(texImage);
|
||||
if (tex) {
|
||||
_mesa_init_teximage_fields(ctx, target, texImage,
|
||||
tex->width0, tex->height0, 1, 0, internalFormat);
|
||||
texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
_mesa_set_fetch_functions(texImage, 2);
|
||||
}
|
||||
else {
|
||||
_mesa_clear_texture_image(ctx, texImage);
|
||||
}
|
||||
|
||||
pipe_texture_reference(&stImage->pt, tex);
|
||||
|
||||
_mesa_dirty_texobj(ctx, texObj, GL_TRUE);
|
||||
_mesa_unlock_texture(ctx, texObj);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
st_context_destroy(struct st_context_iface *stctxi)
|
||||
{
|
||||
struct st_context *st = (struct st_context *) stctxi;
|
||||
st_destroy_context(st);
|
||||
}
|
||||
|
||||
static struct st_context_iface *
|
||||
st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
|
||||
const struct st_visual *visual,
|
||||
struct st_context_iface *shared_stctxi)
|
||||
{
|
||||
struct st_context *shared_ctx = (struct st_context *) shared_stctxi;
|
||||
struct st_context *st;
|
||||
struct pipe_context *pipe;
|
||||
__GLcontextModes mode;
|
||||
|
||||
pipe = smapi->screen->context_create(smapi->screen, NULL);
|
||||
if (!pipe)
|
||||
return NULL;
|
||||
|
||||
st_visual_to_context_mode(visual, &mode);
|
||||
st = st_create_context(pipe, &mode, shared_ctx);
|
||||
if (!st) {
|
||||
pipe->destroy(pipe);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
st->iface.destroy = st_context_destroy;
|
||||
|
||||
st->iface.notify_invalid_framebuffer =
|
||||
st_context_notify_invalid_framebuffer;
|
||||
st->iface.flush = st_context_flush;
|
||||
|
||||
st->iface.teximage = st_context_teximage;
|
||||
st->iface.copy = NULL;
|
||||
|
||||
st->iface.st_context_private = (void *) smapi;
|
||||
|
||||
return &st->iface;
|
||||
}
|
||||
|
||||
static boolean
|
||||
st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
|
||||
struct st_framebuffer_iface *stdrawi,
|
||||
struct st_framebuffer_iface *streadi)
|
||||
{
|
||||
struct st_context *st = (struct st_context *) stctxi;
|
||||
struct st_framebuffer *stdraw, *stread, *stfb;
|
||||
boolean ret;
|
||||
|
||||
_glapi_check_multithread();
|
||||
|
||||
if (st) {
|
||||
/* reuse/create the draw fb */
|
||||
stfb = st_framebuffer(st->ctx->WinSysDrawBuffer);
|
||||
if (stfb && stfb->iface == stdrawi) {
|
||||
stdraw = NULL;
|
||||
st_framebuffer_reference(&stdraw, stfb);
|
||||
}
|
||||
else {
|
||||
stdraw = st_framebuffer_create(stdrawi);
|
||||
}
|
||||
|
||||
/* reuse/create the read fb */
|
||||
stfb = st_framebuffer(st->ctx->WinSysReadBuffer);
|
||||
if (!stfb || stfb->iface != streadi)
|
||||
stfb = stdraw;
|
||||
if (stfb && stfb->iface == streadi) {
|
||||
stread = NULL;
|
||||
st_framebuffer_reference(&stread, stfb);
|
||||
}
|
||||
else {
|
||||
stread = st_framebuffer_create(streadi);
|
||||
}
|
||||
|
||||
if (stdraw && stread) {
|
||||
st_framebuffer_validate(stdraw, st);
|
||||
if (stread != stdraw)
|
||||
st_framebuffer_validate(stread, st);
|
||||
|
||||
/* modify the draw/read buffers of the context */
|
||||
st_visual_to_default_buffer(stdraw->iface->visual,
|
||||
&st->ctx->Color.DrawBuffer[0], NULL);
|
||||
st_visual_to_default_buffer(stread->iface->visual,
|
||||
&st->ctx->Pixel.ReadBuffer, NULL);
|
||||
|
||||
ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
|
||||
}
|
||||
else {
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
st_framebuffer_reference(&stdraw, NULL);
|
||||
st_framebuffer_reference(&stread, NULL);
|
||||
}
|
||||
else {
|
||||
ret = _mesa_make_current(NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct st_context_iface *
|
||||
st_api_get_current(struct st_api *stapi)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct st_context *st = (ctx) ? ctx->st : NULL;
|
||||
|
||||
return (st) ? &st->iface : NULL;
|
||||
}
|
||||
|
||||
static boolean
|
||||
st_api_is_visual_supported(struct st_api *stapi,
|
||||
const struct st_visual *visual)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static st_proc_t
|
||||
st_api_get_proc_address(struct st_api *stapi, const char *procname)
|
||||
{
|
||||
return (st_proc_t) _glapi_get_proc_address(procname);
|
||||
}
|
||||
|
||||
static void
|
||||
st_api_destroy(struct st_api *stapi)
|
||||
{
|
||||
FREE(stapi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the front buffer if the current context renders to the front buffer.
|
||||
*/
|
||||
void
|
||||
st_manager_flush_frontbuffer(struct st_context *st)
|
||||
{
|
||||
struct st_framebuffer *stfb = st_framebuffer(st->ctx->DrawBuffer);
|
||||
struct st_renderbuffer *strb = NULL;
|
||||
|
||||
if (stfb)
|
||||
strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
|
||||
if (!strb)
|
||||
return;
|
||||
|
||||
/* st_public.h */
|
||||
if (!stfb->iface) {
|
||||
struct pipe_surface *front_surf = strb->surface;
|
||||
st->pipe->screen->flush_frontbuffer(st->pipe->screen,
|
||||
front_surf, st->winsys_drawable_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-validate the framebuffers.
|
||||
*/
|
||||
void
|
||||
st_manager_validate_framebuffers(struct st_context *st)
|
||||
{
|
||||
struct st_framebuffer *stdraw = st_framebuffer(st->ctx->DrawBuffer);
|
||||
struct st_framebuffer *stread = st_framebuffer(st->ctx->ReadBuffer);
|
||||
|
||||
/* st_public.h */
|
||||
if ((stdraw && !stdraw->iface) || (stread && !stread->iface)) {
|
||||
struct pipe_screen *screen = st->pipe->screen;
|
||||
if (screen->update_buffer)
|
||||
screen->update_buffer(screen, st->pipe->priv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stdraw)
|
||||
st_framebuffer_validate(stdraw, st);
|
||||
if (stread && stread != stdraw)
|
||||
st_framebuffer_validate(stread, st);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a color renderbuffer on demand.
|
||||
*/
|
||||
boolean
|
||||
st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb,
|
||||
gl_buffer_index idx)
|
||||
{
|
||||
struct st_framebuffer *stfb = st_framebuffer(fb);
|
||||
|
||||
/* FBO or st_public.h */
|
||||
if (!stfb || !stfb->iface)
|
||||
return FALSE;
|
||||
|
||||
if (stfb->Base.Attachment[idx].Renderbuffer)
|
||||
return TRUE;
|
||||
|
||||
switch (idx) {
|
||||
case BUFFER_FRONT_LEFT:
|
||||
case BUFFER_BACK_LEFT:
|
||||
case BUFFER_FRONT_RIGHT:
|
||||
case BUFFER_BACK_RIGHT:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!st_framebuffer_add_renderbuffer(stfb, idx))
|
||||
return FALSE;
|
||||
|
||||
st_framebuffer_update_attachments(stfb);
|
||||
st_invalidate_state(st->ctx, _NEW_BUFFERS);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an st_api to manage the state tracker.
|
||||
*/
|
||||
struct st_api *
|
||||
st_manager_create_api(void)
|
||||
{
|
||||
struct st_api *stapi;
|
||||
|
||||
stapi = CALLOC_STRUCT(st_api);
|
||||
if (stapi) {
|
||||
stapi->destroy = st_api_destroy;
|
||||
stapi->get_proc_address = st_api_get_proc_address;
|
||||
stapi->is_visual_supported = st_api_is_visual_supported;
|
||||
|
||||
stapi->create_context = st_api_create_context;
|
||||
stapi->make_current = st_api_make_current;
|
||||
stapi->get_current = st_api_get_current;
|
||||
}
|
||||
|
||||
return stapi;
|
||||
}
|
||||
47
src/mesa/state_tracker/st_manager.h
Normal file
47
src/mesa/state_tracker/st_manager.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL 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:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#ifndef ST_MANAGER_H
|
||||
#define ST_MANAGER_H
|
||||
|
||||
#include "state_tracker/st_api.h"
|
||||
#include "st_context.h"
|
||||
|
||||
void
|
||||
st_manager_flush_frontbuffer(struct st_context *st);
|
||||
|
||||
void
|
||||
st_manager_validate_framebuffers(struct st_context *st);
|
||||
|
||||
boolean
|
||||
st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb,
|
||||
gl_buffer_index idx);
|
||||
|
||||
struct st_api *
|
||||
st_manager_create_api(void);
|
||||
|
||||
#endif /* ST_MANAGER_H */
|
||||
Loading…
Add table
Reference in a new issue