-#include "native.h"
-#include "egl_g3d.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 *
-egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- const struct egl_g3d_st *stapi;
- EGLint idx = -1;
-
- switch (ctx->ClientAPI) {
- case EGL_OPENGL_ES_API:
- switch (ctx->ClientVersion) {
- case 1:
- idx = EGL_G3D_ST_OPENGL_ES;
- break;
- case 2:
- idx = EGL_G3D_ST_OPENGL_ES2;
- break;
- default:
- _eglLog(_EGL_WARNING, "unknown client version %d",
- ctx->ClientVersion);
- break;
- }
- break;
- case EGL_OPENVG_API:
- idx = EGL_G3D_ST_OPENVG;
- break;
- case EGL_OPENGL_API:
- idx = EGL_G3D_ST_OPENGL;
- break;
- default:
- _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
- break;
- }