tu: Implement fallback linear staging blit for CopyImage
[mesa.git] / src / gallium / state_trackers / hgl / hgl.c
index ce2ffb1d418833cfa277e5564bdf6a5e79754c2c..f7dc7a6d3dbadbaf853a40382fcf83347c8d948d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2013, Haiku, Inc. All Rights Reserved.
+ * Copyright 2012-2014, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
@@ -7,17 +7,18 @@
  *      Alexander von Gluck IV, kallisti5@unixzen.com
  */
 
+#include "hgl_context.h"
 
-#include "GLView.h"
+#include <stdio.h>
 
-#include "main/context.h"
-#include "main/framebuffer.h"
-#include "main/renderbuffer.h"
 #include "pipe/p_format.h"
 #include "util/u_atomic.h"
+#include "util/format/u_format.h"
 #include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
 
-#include "hgl_context.h"
+#include "GLView.h"
 
 
 #ifdef DEBUG
 #define ERROR(x...) printf("hgl:state_tracker: " x)
 
 
-static boolean
-hgl_st_framebuffer_flush_front(struct st_context_iface *stctx,
-       struct st_framebuffer_iface* stfb, enum st_attachment_type statt)
+// Perform a safe void to hgl_context cast
+static inline struct hgl_context*
+hgl_st_context(struct st_context_iface *stctxi)
 {
-       CALLED();
+       struct hgl_context* context;
+       assert(stctxi);
+       context = (struct hgl_context*)stctxi->st_manager_private;
+       assert(context);
+       return context;
+}
 
-       struct hgl_context* context = (struct hgl_context*)stfb->st_manager_private;
 
-       if (!context) {
-               ERROR("%s: Couldn't obtain valid hgl_context!\n", __func__);
-               return FALSE;
-       }
+// Perform a safe void to hgl_buffer cast
+//static inline struct hgl_buffer*
+struct hgl_buffer*
+hgl_st_framebuffer(struct st_framebuffer_iface *stfbi)
+{
+       struct hgl_buffer* buffer;
+       assert(stfbi);
+       buffer = (struct hgl_buffer*)stfbi->st_manager_private;
+       assert(buffer);
+       return buffer;
+}
+
+
+static bool
+hgl_st_framebuffer_flush_front(struct st_context_iface *stctxi,
+       struct st_framebuffer_iface* stfbi, enum st_attachment_type statt)
+{
+       CALLED();
+
+       //struct hgl_context* context = hgl_st_context(stctxi);
+       // struct hgl_buffer* buffer = hgl_st_context(stfbi);
+       struct hgl_buffer* buffer = hgl_st_framebuffer(stfbi);
+       //buffer->surface
 
        #if 0
        struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
-       pipe_mutex_lock(stwfb->fb->mutex);
+       mtx_lock(&stwfb->fb->mutex);
 
        struct pipe_resource* resource = textures[statt];
        if (resource)
                stw_framebuffer_present_locked(...);
        #endif
 
-       return TRUE;
+       return true;
+}
+
+
+static bool
+hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
+       unsigned width, unsigned height, unsigned mask)
+{
+       struct hgl_buffer* buffer;
+       enum st_attachment_type i;
+       struct pipe_resource templat;
+
+       CALLED();
+
+       buffer = hgl_st_framebuffer(stfbi);
+
+       if (buffer->width != width || buffer->height != height) {
+               for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
+                       pipe_resource_reference(&buffer->textures[i], NULL);
+       }
+
+       memset(&templat, 0, sizeof(templat));
+       templat.target = buffer->target;
+       templat.width0 = width;
+       templat.height0 = height;
+       templat.depth0 = 1;
+       templat.array_size = 1;
+       templat.last_level = 0;
+
+       for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
+               enum pipe_format format;
+               unsigned bind;
+
+               switch (i) {
+                       case ST_ATTACHMENT_FRONT_LEFT:
+                       case ST_ATTACHMENT_BACK_LEFT:
+                       case ST_ATTACHMENT_FRONT_RIGHT:
+                       case ST_ATTACHMENT_BACK_RIGHT:
+                               format = buffer->visual->color_format;
+                               bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;
+                               break;
+                       case ST_ATTACHMENT_DEPTH_STENCIL:
+                               format = buffer->visual->depth_stencil_format;
+                               bind = PIPE_BIND_DEPTH_STENCIL;
+                               break;
+                       default:
+                               format = PIPE_FORMAT_NONE;
+                               bind = 0;
+                               break;
+               }
+
+               if (format != PIPE_FORMAT_NONE) {
+                       templat.format = format;
+                       templat.bind = bind;
+                       buffer->textures[i] = buffer->screen->resource_create(buffer->screen,
+                               &templat);
+                       if (!buffer->textures[i])
+                               return FALSE;
+               }
+       }
+
+       buffer->width = width;
+       buffer->height = height;
+       buffer->mask = mask;
+
+       return true;
 }
 
 
@@ -60,76 +149,57 @@ hgl_st_framebuffer_flush_front(struct st_context_iface *stctx,
  * Called by the st manager to validate the framebuffer (allocate
  * its resources).
  */
-static boolean
-hgl_st_framebuffer_validate(struct st_context_iface *stctx,
+static bool
+hgl_st_framebuffer_validate(struct st_context_iface *stctxi,
        struct st_framebuffer_iface *stfbi, const enum st_attachment_type *statts,
        unsigned count, struct pipe_resource **out)
 {
+       struct hgl_context* context;
+       struct hgl_buffer* buffer;
+       unsigned stAttachmentMask, newMask;
+       unsigned i;
+       bool resized;
+
        CALLED();
 
-       if (!stfbi) {
-               ERROR("%s: Invalid st framebuffer interface!\n", __func__);
-               return FALSE;
-       }
+       context = hgl_st_context(stctxi);
+       buffer = hgl_st_framebuffer(stfbi);
 
-       struct hgl_context* context = (struct hgl_context*)stfbi->st_manager_private;
+       //int32 width = 0;
+       //int32 height = 0;
+       //get_bitmap_size(context->bitmap, &width, &height);
 
-       if (!context) {
-               ERROR("%s: Couldn't obtain valid hgl_context!\n", __func__);
-               return FALSE;
-       }
+       // Build mask of current attachments
+       stAttachmentMask = 0;
+       for (i = 0; i < count; i++)
+               stAttachmentMask |= 1 << statts[i];
 
-       int32 width = 0;
-       int32 height = 0;
-       get_bitmap_size(context->bitmap, &width, &height);
+       newMask = stAttachmentMask & ~buffer->mask;
 
-       struct pipe_resource templat;
-       memset(&templat, 0, sizeof(templat));
-       templat.target = PIPE_TEXTURE_RECT;
-       templat.width0 = width;
-       templat.height0 = height;
-       templat.depth0 = 1;
-       templat.array_size = 1;
-       templat.usage = PIPE_USAGE_DEFAULT;
-
-       if (context->stVisual && context->manager && context->manager->screen) {
-               TRACE("%s: Updating resources\n", __func__);
-               for (unsigned i = 0; i < count; i++) {
-                       enum pipe_format format = PIPE_FORMAT_NONE;
-                       unsigned bind = 0;
-
-                       switch(statts[i]) {
-                               case ST_ATTACHMENT_FRONT_LEFT:
-                               case ST_ATTACHMENT_BACK_LEFT:
-                                       format = context->stVisual->color_format;
-                                       bind = PIPE_BIND_DISPLAY_TARGET
-                                               | PIPE_BIND_RENDER_TARGET;
-                                       break;
-                               case ST_ATTACHMENT_DEPTH_STENCIL:
-                                       format = context->stVisual->depth_stencil_format;
-                                       bind = PIPE_BIND_DEPTH_STENCIL;
-                                       break;
-                               case ST_ATTACHMENT_ACCUM:
-                                       format = context->stVisual->accum_format;
-                                       bind = PIPE_BIND_RENDER_TARGET;
-                                       break;
-                               default:
-                                       format = PIPE_FORMAT_NONE;
-                                       break;
-                       }
-
-                       if (format != PIPE_FORMAT_NONE) {
-                               templat.format = format;
-                               templat.bind = bind;
-
-                               struct pipe_screen* screen = context->manager->screen;
-                               context->textures[i] = screen->resource_create(screen, &templat);
-                               out[i] = context->textures[i];
-                       }
-               }
+       resized = (buffer->width != context->width)
+               || (buffer->height != context->height);
+
+       if (resized || newMask) {
+               boolean ret;
+               TRACE("%s: resize event. old:  %d x %d; new: %d x %d\n", __func__,
+                       buffer->width, buffer->height, context->width, context->height);
+
+               ret = hgl_st_framebuffer_validate_textures(stfbi, 
+                       context->width, context->height, stAttachmentMask);
+               
+               if (!ret)
+                       return ret;
+
+               // TODO: Simply update attachments
+               //if (!resized) {
+
+               //}
        }
 
-       return TRUE;
+       for (i = 0; i < count; i++)
+               pipe_resource_reference(&out[i], buffer->textures[statts[i]]);
+
+       return true;
 }
 
 
@@ -140,9 +210,6 @@ hgl_st_manager_get_param(struct st_manager *smapi, enum st_manager_param param)
 
        switch (param) {
                case ST_MANAGER_BROKEN_INVALIDATE:
-                       TRACE("%s: TODO: How should we handle BROKEN_INVALIDATE calls?\n",
-                               __func__);
-                       // For now we force validation of the framebuffer.
                        return 1;
        }
 
@@ -156,55 +223,69 @@ hgl_st_manager_get_param(struct st_manager *smapi, enum st_manager_param param)
 struct hgl_buffer *
 hgl_create_st_framebuffer(struct hgl_context* context)
 {
+       struct hgl_buffer *buffer;
        CALLED();
 
-       struct hgl_buffer *buffer = CALLOC_STRUCT(hgl_buffer);
-
+       // Our requires before creating a framebuffer
        assert(context);
+       assert(context->screen);
        assert(context->stVisual);
 
-       if (buffer) {
-               // Copy context visual into framebuffer
-               memcpy(&buffer->visual, context->stVisual, sizeof(struct st_visual));
+       buffer = CALLOC_STRUCT(hgl_buffer);
+       assert(buffer);
 
-               // calloc and configure our st_framebuffer interface
-               buffer->stfbi = CALLOC_STRUCT(st_framebuffer_iface);
-               if (!buffer->stfbi) {
-                       ERROR("%s: Couldn't calloc framebuffer!\n", __func__);
-                       return NULL;
-               }
+       // calloc and configure our st_framebuffer interface
+       buffer->stfbi = CALLOC_STRUCT(st_framebuffer_iface);
+       assert(buffer->stfbi);
 
-               struct st_framebuffer_iface* stfbi = buffer->stfbi;
-               p_atomic_set(&stfbi->stamp, 1);
-               stfbi->flush_front = hgl_st_framebuffer_flush_front;
-               stfbi->validate = hgl_st_framebuffer_validate;
-               stfbi->st_manager_private = (void*)context;
-               stfbi->visual = &buffer->visual;
+       // Prepare our buffer
+       buffer->visual = context->stVisual;
+       buffer->screen = context->screen;
 
-               // TODO: Do we need linked list?
-       }
+       if (context->screen->get_param(buffer->screen, PIPE_CAP_NPOT_TEXTURES))
+               buffer->target = PIPE_TEXTURE_2D;
+       else
+               buffer->target = PIPE_TEXTURE_RECT;
+
+       // Prepare our state_tracker interface
+       buffer->stfbi->flush_front = hgl_st_framebuffer_flush_front;
+       buffer->stfbi->validate = hgl_st_framebuffer_validate;
+       buffer->stfbi->visual = context->stVisual;
+
+       p_atomic_set(&buffer->stfbi->stamp, 1);
+       buffer->stfbi->st_manager_private = (void*)buffer;
 
-   return buffer;
+       return buffer;
+}
+
+
+struct st_api*
+hgl_create_st_api()
+{
+       CALLED();
+       return st_gl_api_create();
 }
 
 
 struct st_manager *
-hgl_create_st_manager(struct pipe_screen* screen)
+hgl_create_st_manager(struct hgl_context* context)
 {
+       struct st_manager* manager;
+
        CALLED();
 
-       assert(screen);
-       struct st_manager* manager = CALLOC_STRUCT(st_manager);
+       // Required things
+       assert(context);
+       assert(context->screen);
 
-       if (!manager) {
-               ERROR("%s: Couldn't allocate state tracker manager!\n", __func__);
-               return NULL;
-       }
+       manager = CALLOC_STRUCT(st_manager);
+       assert(manager);
 
        //manager->display = dpy;
-       manager->screen = screen;
+       manager->screen = context->screen;
        manager->get_param = hgl_st_manager_get_param;
-
+       manager->st_manager_private = (void *)context;
+       
        return manager;
 }
 
@@ -214,96 +295,60 @@ hgl_destroy_st_manager(struct st_manager *manager)
 {
        CALLED();
 
-       if (manager)
-               FREE(manager);
+       FREE(manager);
 }
 
 
 struct st_visual*
 hgl_create_st_visual(ulong options)
 {
-       struct st_visual* visual = CALLOC_STRUCT(st_visual);
-       if (!visual) {
-               ERROR("%s: Couldn't allocate st_visual\n", __func__);
-               return NULL;
-       }
+       struct st_visual* visual;
 
-       // Calculate visual configuration
-       const GLboolean rgbFlag     = ((options & BGL_INDEX) == 0);
-       const GLboolean alphaFlag   = ((options & BGL_ALPHA) == BGL_ALPHA);
-       const GLboolean dblFlag     = ((options & BGL_DOUBLE) == BGL_DOUBLE);
-       const GLboolean stereoFlag  = false;
-       const GLint depth           = (options & BGL_DEPTH) ? 24 : 0;
-       const GLint stencil         = (options & BGL_STENCIL) ? 8 : 0;
-       const GLint accum           = (options & BGL_ACCUM) ? 16 : 0;
-       const GLint red             = rgbFlag ? 8 : 5;
-       const GLint green           = rgbFlag ? 8 : 5;
-       const GLint blue            = rgbFlag ? 8 : 5;
-       const GLint alpha           = alphaFlag ? 8 : 0;
-
-       TRACE("rgb      :\t%d\n", (bool)rgbFlag);
-       TRACE("alpha    :\t%d\n", (bool)alphaFlag);
-       TRACE("dbl      :\t%d\n", (bool)dblFlag);
-       TRACE("stereo   :\t%d\n", (bool)stereoFlag);
-       TRACE("depth    :\t%d\n", depth);
-       TRACE("stencil  :\t%d\n", stencil);
-       TRACE("accum    :\t%d\n", accum);
-       TRACE("red      :\t%d\n", red);
-       TRACE("green    :\t%d\n", green);
-       TRACE("blue     :\t%d\n", blue);
-       TRACE("alpha    :\t%d\n", alpha);
+       CALLED();
+
+       visual = CALLOC_STRUCT(st_visual);
+       assert(visual);
 
        // Determine color format
-       if (red == 8) {
-               if (alpha == 8)
-                       visual->color_format = PIPE_FORMAT_A8R8G8B8_UNORM;
-               else
-                       visual->color_format = PIPE_FORMAT_X8R8G8B8_UNORM;
-       } else {
-               // TODO: I think this should be RGB vs BGR
+       if ((options & BGL_INDEX) != 0) {
+               // Index color
                visual->color_format = PIPE_FORMAT_B5G6R5_UNORM;
+               // TODO: Indexed color depth buffer?
+               visual->depth_stencil_format = PIPE_FORMAT_NONE;
+       } else {
+               // RGB color
+               visual->color_format = (options & BGL_ALPHA)
+                       ? PIPE_FORMAT_BGRA8888_UNORM : PIPE_FORMAT_BGRX8888_UNORM;
+               // TODO: Determine additional stencil formats
+               visual->depth_stencil_format = (options & BGL_DEPTH)
+                       ? PIPE_FORMAT_Z24_UNORM_S8_UINT : PIPE_FORMAT_NONE;
     }
 
-       // Determine depth stencil format
-       switch (depth) {
-               default:
-               case 0:
-                       visual->depth_stencil_format = PIPE_FORMAT_NONE;
-                       break;
-               case 16:
-                       visual->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
-                       break;
-               case 24:
-                       if ((options & BGL_STENCIL) != 0)
-                               visual->depth_stencil_format = PIPE_FORMAT_S8_UINT_Z24_UNORM;
-                       else
-                               visual->depth_stencil_format = PIPE_FORMAT_X8Z24_UNORM;
-                       break;
-               case 32:
-                       visual->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
-                       break;
-       }
-
        visual->accum_format = (options & BGL_ACCUM)
                ? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
 
        visual->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
        visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
 
-       if (dblFlag) {
+       if ((options & BGL_DOUBLE) != 0) {
                visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
                visual->render_buffer = ST_ATTACHMENT_BACK_LEFT;
        }
 
-       if (stereoFlag) {
+       #if 0
+       if ((options & BGL_STEREO) != 0) {
                visual->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
-               if (dblFlag)
+               if ((options & BGL_DOUBLE) != 0)
                        visual->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
     }
+       #endif
 
        if ((options & BGL_DEPTH) || (options & BGL_STENCIL))
                visual->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
 
+       TRACE("%s: Visual color format: %s\n", __func__,
+               util_format_name(visual->color_format));
+
        return visual;
 }
 
@@ -313,6 +358,5 @@ hgl_destroy_st_visual(struct st_visual* visual)
 {
        CALLED();
 
-       if (visual)
-               FREE(visual);
+       FREE(visual);
 }