Пример #1
0
static __DRIimage *
intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
{
   __DRIimage *image;

   image = calloc(1, sizeof *image);
   if (image == NULL)
      return NULL;

   intel_region_reference(&image->region, orig_image->region);
   if (image->region == NULL) {
      free(image);
      return NULL;
   }

   image->internal_format = orig_image->internal_format;
   image->planar_format   = orig_image->planar_format;
   image->dri_format      = orig_image->dri_format;
   image->format          = orig_image->format;
   image->offset          = orig_image->offset;
   image->width           = orig_image->width;
   image->height          = orig_image->height;
   image->tile_x          = orig_image->tile_x;
   image->tile_y          = orig_image->tile_y;
   image->data            = loaderPrivate;

   memcpy(image->strides, orig_image->strides, sizeof(image->strides));
   memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets));

   return image;
}
Пример #2
0
/**
 * Sets up a DRIImage structure to point to our shared image in a region
 */
static void
intel_setup_image_from_mipmap_tree(struct brw_context *brw, __DRIimage *image,
                                   struct intel_mipmap_tree *mt, GLuint level,
                                   GLuint zoffset)
{
   unsigned int draw_x, draw_y;
   uint32_t mask_x, mask_y;

   intel_miptree_make_shareable(brw, mt);

   intel_miptree_check_level_layer(mt, level, zoffset);

   intel_region_get_tile_masks(mt->region, &mask_x, &mask_y, false);
   intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y);

   image->width = mt->level[level].width;
   image->height = mt->level[level].height;
   image->tile_x = draw_x & mask_x;
   image->tile_y = draw_y & mask_y;

   image->offset = intel_region_get_aligned_offset(mt->region,
                                                   draw_x & ~mask_x,
                                                   draw_y & ~mask_y,
                                                   false);

   intel_region_reference(&image->region, mt->region);
}
Пример #3
0
static __DRIimage *
intel_create_image_from_renderbuffer(__DRIcontext *context,
				     int renderbuffer, void *loaderPrivate)
{
   __DRIimage *image;
   struct intel_context *intel = context->driverPrivate;
   struct gl_renderbuffer *rb;
   struct intel_renderbuffer *irb;

   rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer);
   if (!rb) {
      _mesa_error(&intel->ctx,
		  GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
      return NULL;
   }

   irb = intel_renderbuffer(rb);
   image = calloc(1, sizeof *image);
   if (image == NULL)
      return NULL;

   image->internal_format = rb->InternalFormat;
   image->format = rb->Format;
   image->offset = 0;
   image->data = loaderPrivate;
   intel_region_reference(&image->region, irb->mt->region);
   intel_setup_image_from_dimensions(image);
   image->dri_format = driGLFormatToImageFormat(image->format);

   rb->NeedsFinishRenderTexture = true;
   return image;
}
Пример #4
0
static __DRIimage *
intel_create_image_from_renderbuffer(__DRIcontext *context,
				     int renderbuffer, void *loaderPrivate)
{
   __DRIimage *image;
   struct brw_context *brw = context->driverPrivate;
   struct gl_context *ctx = &brw->ctx;
   struct gl_renderbuffer *rb;
   struct intel_renderbuffer *irb;

   rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
   if (!rb) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
      return NULL;
   }

   irb = intel_renderbuffer(rb);
   intel_miptree_make_shareable(brw, irb->mt);
   image = calloc(1, sizeof *image);
   if (image == NULL)
      return NULL;

   image->internal_format = rb->InternalFormat;
   image->format = rb->Format;
   image->offset = 0;
   image->data = loaderPrivate;
   intel_region_reference(&image->region, irb->mt->region);
   intel_setup_image_from_dimensions(image);
   image->dri_format = intel_dri_format(image->format);
   image->has_depthstencil = irb->mt->stencil_mt? true : false;

   rb->NeedsFinishRenderTexture = true;
   return image;
}
Пример #5
0
void
intel_renderbuffer_set_region(struct intel_renderbuffer *rb,
			      struct intel_region *region)
{
   struct intel_region *old;

   old = rb->region;
   rb->region = NULL;
   intel_region_reference(&rb->region, region);
   intel_region_release(&old);
}
static __DRIimage *
intel_create_image_from_renderbuffer(__DRIcontext *context,
				     int renderbuffer, void *loaderPrivate)
{
   __DRIimage *image;
   struct intel_context *intel = context->driverPrivate;
   struct gl_renderbuffer *rb;
   struct intel_renderbuffer *irb;

   rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer);
   if (!rb) {
      _mesa_error(&intel->ctx,
		  GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
      return NULL;
   }

   irb = intel_renderbuffer(rb);
   image = calloc(1, sizeof *image);
   if (image == NULL)
      return NULL;

   image->internal_format = rb->InternalFormat;
   image->format = rb->Format;
   image->offset = 0;
   image->data = loaderPrivate;
   intel_region_reference(&image->region, irb->mt->region);

   switch (image->format) {
   case MESA_FORMAT_RGB565:
      image->dri_format = __DRI_IMAGE_FORMAT_RGB565;
      break;
   case MESA_FORMAT_XRGB8888:
      image->dri_format = __DRI_IMAGE_FORMAT_XRGB8888;
      break;
   case MESA_FORMAT_ARGB8888:
      image->dri_format = __DRI_IMAGE_FORMAT_ARGB8888;
      break;
   case MESA_FORMAT_RGBA8888_REV:
      image->dri_format = __DRI_IMAGE_FORMAT_ABGR8888;
      break;
   case MESA_FORMAT_R8:
      image->dri_format = __DRI_IMAGE_FORMAT_R8;
      break;
   case MESA_FORMAT_RG88:
      image->dri_format = __DRI_IMAGE_FORMAT_GR88;
      break;
   }

   rb->NeedsFinishRenderTexture = true;
   return image;
}
void
intel_renderbuffer_set_region(struct intel_renderbuffer *rb,
			      struct intel_region *region)
{
   struct intel_region *old;

   old = rb->region;
   rb->region = NULL;
   intel_region_reference(&rb->region, region);
   intel_region_release(&old);

   rb->pfMap = region->map;
   rb->pfPitch = region->pitch;
}
Пример #8
0
struct intel_mipmap_tree *
intel_miptree_create_for_region(struct intel_context *intel,
				GLenum target,
				GLenum internal_format,
				GLuint first_level,
				GLuint last_level,
				struct intel_region *region,
				GLuint depth0,
				GLuint compress_byte)
{
   struct intel_mipmap_tree *mt;

   mt = intel_miptree_create_internal(intel, target, internal_format,
				      first_level, last_level,
				      region->width, region->height, 1,
				      region->cpp, compress_byte);
   if (!mt)
      return mt;
#if 0
   if (mt->pitch != region->pitch) {
      fprintf(stderr,
	      "region pitch (%d) doesn't match mipmap tree pitch (%d)\n",
	      region->pitch, mt->pitch);
      free(mt);
      return NULL;
   }
#else
   /* The mipmap tree pitch is aligned to 64 bytes to make sure render
    * to texture works, but we don't need that for texturing from a
    * pixmap.  Just override it here. */
   mt->pitch = region->pitch;
#endif

   intel_region_reference(&mt->region, region);

   return mt;
 }
Пример #9
0
struct intel_mipmap_tree *
intel_miptree_create_for_region(struct intel_context *intel,
                                GLenum target,
                                GLenum internal_format,
                                GLuint first_level,
                                GLuint last_level,
                                struct intel_region *region,
                                GLuint depth0,
                                GLuint compress_byte)
{
    struct intel_mipmap_tree *mt;

    mt = intel_miptree_create_internal(intel, target, internal_format,
                                       first_level, last_level,
                                       region->width, region->height, 1,
                                       region->cpp, compress_byte,
                                       I915_TILING_NONE);
    if (!mt)
        return mt;

    intel_region_reference(&mt->region, region);

    return mt;
}
Пример #10
0
static __DRIimage *
intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
{
   __DRIimage *image;

   image = CALLOC(sizeof *image);
   if (image == NULL)
      return NULL;

   intel_region_reference(&image->region, orig_image->region);
   if (image->region == NULL) {
      FREE(image);
      return NULL;
   }

   image->internal_format = orig_image->internal_format;
   image->usage           = orig_image->usage;
   image->dri_format      = orig_image->dri_format;
   image->format          = orig_image->format;
   image->offset          = orig_image->offset;
   image->data            = loaderPrivate;
   
   return image;
}
Пример #11
0
void
intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
{
   struct gl_framebuffer *fb = drawable->driverPrivate;
   struct intel_renderbuffer *rb;
   struct intel_region *region, *depth_region;
   struct intel_context *intel = context->driverPrivate;
   struct intel_renderbuffer *front_rb, *back_rb, *depth_rb, *stencil_rb;
   __DRIbuffer *buffers = NULL;
   __DRIscreen *screen;
   int i, count;
   unsigned int attachments[10];
   const char *region_name;

   /* If we're rendering to the fake front buffer, make sure all the
    * pending drawing has landed on the real front buffer.  Otherwise
    * when we eventually get to DRI2GetBuffersWithFormat the stale
    * real front buffer contents will get copied to the new fake front
    * buffer.
    */
   if (intel->is_front_buffer_rendering)
      intel_flush(&intel->ctx, GL_FALSE);

   /* Set this up front, so that in case our buffers get invalidated
    * while we're getting new buffers, we don't clobber the stamp and
    * thus ignore the invalidate. */
   drawable->lastStamp = drawable->dri2.stamp;

   if (INTEL_DEBUG & DEBUG_DRI)
      fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);

   screen = intel->intelScreen->driScrnPriv;

   if (screen->dri2.loader
       && (screen->dri2.loader->base.version > 2)
       && (screen->dri2.loader->getBuffersWithFormat != NULL)) {

      front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
      back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
      depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
      stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);

      i = 0;
      if ((intel->is_front_buffer_rendering ||
	   intel->is_front_buffer_reading ||
	   !back_rb) && front_rb) {
	 attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
	 attachments[i++] = intel_bits_per_pixel(front_rb);
      }

      if (back_rb) {
	 attachments[i++] = __DRI_BUFFER_BACK_LEFT;
	 attachments[i++] = intel_bits_per_pixel(back_rb);
      }

      if ((depth_rb != NULL) && (stencil_rb != NULL)) {
	 attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
	 attachments[i++] = intel_bits_per_pixel(depth_rb);
      } else if (depth_rb != NULL) {
	 attachments[i++] = __DRI_BUFFER_DEPTH;
	 attachments[i++] = intel_bits_per_pixel(depth_rb);
      } else if (stencil_rb != NULL) {
	 attachments[i++] = __DRI_BUFFER_STENCIL;
	 attachments[i++] = intel_bits_per_pixel(stencil_rb);
      }

      buffers =
	 (*screen->dri2.loader->getBuffersWithFormat)(drawable,
						      &drawable->w,
						      &drawable->h,
						      attachments, i / 2,
						      &count,
						      drawable->loaderPrivate);
   } else if (screen->dri2.loader) {
      i = 0;
      if (intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT))
	 attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
      if (intel_get_renderbuffer(fb, BUFFER_BACK_LEFT))
	 attachments[i++] = __DRI_BUFFER_BACK_LEFT;
      if (intel_get_renderbuffer(fb, BUFFER_DEPTH))
	 attachments[i++] = __DRI_BUFFER_DEPTH;
      if (intel_get_renderbuffer(fb, BUFFER_STENCIL))
	 attachments[i++] = __DRI_BUFFER_STENCIL;

      buffers = (*screen->dri2.loader->getBuffers)(drawable,
						   &drawable->w,
						   &drawable->h,
						   attachments, i,
						   &count,
						   drawable->loaderPrivate);
   }

   if (buffers == NULL)
      return;

   drawable->x = 0;
   drawable->y = 0;
   drawable->backX = 0;
   drawable->backY = 0;
   drawable->numClipRects = 1;
   drawable->pClipRects[0].x1 = 0;
   drawable->pClipRects[0].y1 = 0;
   drawable->pClipRects[0].x2 = drawable->w;
   drawable->pClipRects[0].y2 = drawable->h;
   drawable->numBackClipRects = 1;
   drawable->pBackClipRects[0].x1 = 0;
   drawable->pBackClipRects[0].y1 = 0;
   drawable->pBackClipRects[0].x2 = drawable->w;
   drawable->pBackClipRects[0].y2 = drawable->h;

   depth_region = NULL;
   for (i = 0; i < count; i++) {
       switch (buffers[i].attachment) {
       case __DRI_BUFFER_FRONT_LEFT:
	   rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
	   region_name = "dri2 front buffer";
	   break;

       case __DRI_BUFFER_FAKE_FRONT_LEFT:
	   rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
	   region_name = "dri2 fake front buffer";
	   break;

       case __DRI_BUFFER_BACK_LEFT:
	   rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
	   region_name = "dri2 back buffer";
	   break;

       case __DRI_BUFFER_DEPTH:
	   rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
	   region_name = "dri2 depth buffer";
	   break;

       case __DRI_BUFFER_DEPTH_STENCIL:
	   rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
	   region_name = "dri2 depth / stencil buffer";
	   break;

       case __DRI_BUFFER_STENCIL:
	   rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
	   region_name = "dri2 stencil buffer";
	   break;

       case __DRI_BUFFER_ACCUM:
       default:
	   fprintf(stderr,
		   "unhandled buffer attach event, attacment type %d\n",
		   buffers[i].attachment);
	   return;
       }

       if (rb == NULL)
	  continue;

       if (rb->region && rb->region->name == buffers[i].name)
	     continue;

       if (INTEL_DEBUG & DEBUG_DRI)
	  fprintf(stderr,
		  "attaching buffer %d, at %d, cpp %d, pitch %d\n",
		  buffers[i].name, buffers[i].attachment,
		  buffers[i].cpp, buffers[i].pitch);
       
       if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_region) {
	  if (INTEL_DEBUG & DEBUG_DRI)
	     fprintf(stderr, "(reusing depth buffer as stencil)\n");
	  intel_region_reference(&region, depth_region);
       }
       else
          region = intel_region_alloc_for_handle(intel, buffers[i].cpp,
						 drawable->w,
						 drawable->h,
						 buffers[i].pitch / buffers[i].cpp,
						 buffers[i].name,
						 region_name);

       if (buffers[i].attachment == __DRI_BUFFER_DEPTH)
	  depth_region = region;

       intel_renderbuffer_set_region(intel, rb, region);
       intel_region_release(&region);

       if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) {
	  rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
	  if (rb != NULL) {
	     struct intel_region *stencil_region = NULL;

	     if (rb->region && rb->region->name == buffers[i].name)
		   continue;

	     intel_region_reference(&stencil_region, region);
	     intel_renderbuffer_set_region(intel, rb, stencil_region);
	     intel_region_release(&stencil_region);
	  }
       }
   }

   driUpdateFramebufferSize(&intel->ctx, drawable);
}
Пример #12
0
/**
 * Called by glFramebufferTexture[123]DEXT() (and other places) to
 * prepare for rendering into texture memory.  This might be called
 * many times to choose different texture levels, cube faces, etc
 * before intel_finish_render_texture() is ever called.
 */
static void
intel_render_texture(GLcontext * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
   struct gl_texture_image *newImage
      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
   struct intel_texture_image *intel_image;
   GLuint dst_x, dst_y;

   (void) fb;

   ASSERT(newImage);

   intel_image = intel_texture_image(newImage);
   if (!intel_image->mt) {
      /* Fallback on drawing to a texture that doesn't have a miptree
       * (has a border, width/height 0, etc.)
       */
      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
      _mesa_render_texture(ctx, fb, att);
      return;
   }
   else if (!irb) {
      irb = intel_wrap_texture(ctx, newImage);
      if (irb) {
         /* bind the wrapper to the attachment point */
         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
      }
      else {
         /* fallback to software rendering */
         _mesa_render_texture(ctx, fb, att);
         return;
      }
   }

   if (!intel_update_wrapper(ctx, irb, newImage)) {
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       _mesa_render_texture(ctx, fb, att);
       return;
   }

   DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
       _glthread_GetID(),
       att->Texture->Name, newImage->Width, newImage->Height,
       irb->Base.RefCount);

   /* point the renderbufer's region to the texture image region */
   if (irb->region != intel_image->mt->region) {
      if (irb->region)
	 intel_region_release(&irb->region);
      intel_region_reference(&irb->region, intel_image->mt->region);
   }

   /* compute offset of the particular 2D image within the texture region */
   intel_miptree_get_image_offset(intel_image->mt,
				  att->TextureLevel,
				  att->CubeMapFace,
				  att->Zoffset,
				  &dst_x, &dst_y);

   intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->pitch +
					   dst_x) * intel_image->mt->cpp;
   intel_image->mt->region->draw_x = dst_x;
   intel_image->mt->region->draw_y = dst_y;
   intel_image->used_as_render_target = GL_TRUE;

   /* update drawing region, etc */
   intel_draw_buffer(ctx, fb);
}
Пример #13
0
/**
 * Binds a region to a texture image, like it was uploaded by glTexImage2D().
 *
 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions,
 */
static void
intel_set_texture_image_region(struct gl_context *ctx,
			       struct gl_texture_image *image,
			       struct intel_region *region,
			       GLenum target,
			       GLenum internalFormat,
			       gl_format format,
                               uint32_t offset,
                               GLuint width,
                               GLuint height,
                               GLuint tile_x,
                               GLuint tile_y)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct gl_texture_object *texobj = image->TexObject;
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
   bool has_surface_tile_offset = false;
   uint32_t draw_x, draw_y;

   _mesa_init_teximage_fields(&intel->ctx, image,
			      width, height, 1,
			      0, internalFormat, format);

   ctx->Driver.FreeTextureImageBuffer(ctx, image);

   intel_image->mt = intel_miptree_create_layout(intel, target, image->TexFormat,
                                                 0, 0,
                                                 width, height, 1,
                                                 true, 0 /* num_samples */);
   if (intel_image->mt == NULL)
       return;
   intel_region_reference(&intel_image->mt->region, region);
   intel_image->mt->total_width = width;
   intel_image->mt->total_height = height;
   intel_image->mt->level[0].slice[0].x_offset = tile_x;
   intel_image->mt->level[0].slice[0].y_offset = tile_y;

   intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y);
#ifndef I915
   has_surface_tile_offset = brw_context(ctx)->has_surface_tile_offset;
#endif

   /* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION
    * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has
    * trouble resolving back to destination image due to alignment issues.
    */
   if (!has_surface_tile_offset &&
       (draw_x != 0 || draw_y != 0)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, __func__);
      intel_miptree_release(&intel_image->mt);
      return;
   }

   intel_texobj->needs_validate = true;

   intel_image->mt->offset = offset;
   assert(region->pitch % region->cpp == 0);
   intel_image->base.RowStride = region->pitch / region->cpp;

   /* Immediately validate the image to the object. */
   intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
}
Пример #14
0
/**
 * Called by glFramebufferTexture[123]DEXT() (and other places) to
 * prepare for rendering into texture memory.  This might be called
 * many times to choose different texture levels, cube faces, etc
 * before intel_finish_render_texture() is ever called.
 */
static void
intel_render_texture(GLcontext * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
   struct gl_texture_image *newImage
      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
   struct intel_texture_image *intel_image;
   GLuint imageOffset;

   (void) fb;

   ASSERT(newImage);

   if (!irb) {
      irb = intel_wrap_texture(ctx, newImage);
      if (irb) {
         /* bind the wrapper to the attachment point */
         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
      }
      else {
         /* fallback to software rendering */
         _mesa_render_texture(ctx, fb, att);
         return;
      }
   } if (!intel_update_wrapper(ctx, irb, newImage)) {
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       _mesa_render_texture(ctx, fb, att);
       return;
   }

   DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
       _glthread_GetID(),
       att->Texture->Name, newImage->Width, newImage->Height,
       irb->Base.RefCount);

   /* point the renderbufer's region to the texture image region */
   intel_image = intel_texture_image(newImage);
   if (irb->region != intel_image->mt->region) {
      if (irb->region)
	 intel_region_release(&irb->region);
      intel_region_reference(&irb->region, intel_image->mt->region);
   }

   /* compute offset of the particular 2D image within the texture region */
   imageOffset = intel_miptree_image_offset(intel_image->mt,
                                            att->CubeMapFace,
                                            att->TextureLevel);

   if (att->Texture->Target == GL_TEXTURE_3D) {
      const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt,
                                                          att->TextureLevel);
      imageOffset += offsets[att->Zoffset];
   }

   /* store that offset in the region */
   intel_image->mt->region->draw_offset = imageOffset;

   /* update drawing region, etc */
   intel_draw_buffer(ctx, fb);
}