Beispiel #1
0
void
brw_meta_resolve_color(struct brw_context *brw,
                       struct intel_mipmap_tree *mt)
{
   struct gl_context *ctx = &brw->ctx;
   struct gl_framebuffer *drawFb;
   struct gl_renderbuffer *rb;
   struct rect rect;

   brw_emit_mi_flush(brw);

   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (drawFb == NULL) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "in %s", __func__);
      return;
   }

   _mesa_meta_begin(ctx, MESA_META_ALL);

   rb = brw_get_rb_for_slice(brw, mt, 0, 0, false);

   _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer);
   _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0,
                                  rb);
   _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);

   brw_fast_clear_init(brw);

   use_rectlist(brw, true);

   brw_bind_rep_write_shader(brw, (float *) fast_clear_color);

   /* SKL+ also has a resolve mode for compressed render targets and thus more
    * bits to let us select the type of resolve.  For fast clear resolves, it
    * turns out we can use the same value as pre-SKL though.
    */
   if (intel_miptree_is_lossless_compressed(brw, mt))
      set_fast_clear_op(brw, GEN9_PS_RENDER_TARGET_RESOLVE_FULL);
   else
      set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE);

   mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
   get_resolve_rect(brw, mt, &rect);

   brw_draw_rectlist(brw, &rect, 1);

   set_fast_clear_op(brw, 0);
   use_rectlist(brw, false);

   _mesa_reference_renderbuffer(&rb, NULL);
   _mesa_reference_framebuffer(&drawFb, NULL);

   _mesa_meta_end(ctx);

   /* We're typically called from intel_update_state() and we're supposed to
    * return with the state all updated to what it was before
    * brw_meta_resolve_color() was called.  The meta rendering will have
    * messed up the state and we need to call _mesa_update_state() again to
    * get back to where we were supposed to be when resolve was called.
    */
   if (ctx->NewState)
      _mesa_update_state(ctx);
}
bool
_mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims,
                           struct gl_texture_image *tex_image,
                           int xoffset, int yoffset, int zoffset,
                           int width, int height, int depth,
                           GLenum format, GLenum type, const void *pixels,
                           bool create_pbo,
                           const struct gl_pixelstore_attrib *packing)
{
   struct gl_buffer_object *pbo = NULL;
   GLuint pbo_tex = 0;
   struct gl_framebuffer *readFb = NULL;
   struct gl_framebuffer *drawFb = NULL;
   int image_height;
   struct gl_texture_image *pbo_tex_image;
   GLenum status;
   bool success = false;
   int z;

   if (!_mesa_is_bufferobj(packing->BufferObj) &&
       (!create_pbo || pixels == NULL))
      return false;

   if (format == GL_DEPTH_COMPONENT ||
       format == GL_DEPTH_STENCIL ||
       format == GL_STENCIL_INDEX ||
       format == GL_COLOR_INDEX)
      return false;

   if (ctx->_ImageTransferState)
      return false;

   /* This function rely on BlitFramebuffer to fill in the pixel data for
    * glTex[Sub]Image*D. But, BlitFrameBuffer doesn't support signed to
    * unsigned or unsigned to signed integer conversions.
    */
   if (need_signed_unsigned_int_conversion(tex_image->TexFormat, format, type))
      return false;

   /* For arrays, use a tall (height * depth) 2D texture but taking into
    * account the inter-image padding specified with the image height packing
    * property.
    */
   image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight;

   _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER |
                           MESA_META_PIXEL_STORE));

   pbo_tex_image = create_texture_for_pbo(ctx, create_pbo,
                                          GL_PIXEL_UNPACK_BUFFER,
                                          dims, width, height, depth,
                                          format, type, pixels, packing,
                                          &pbo, &pbo_tex);
   if (!pbo_tex_image) {
      _mesa_meta_end(ctx);
      return false;
   }

   readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (readFb == NULL)
      goto fail;

   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (drawFb == NULL)
      goto fail;

   _mesa_bind_framebuffers(ctx, drawFb, tex_image ? readFb : ctx->ReadBuffer);

   if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      assert(depth == 1);
      assert(zoffset == 0);
      depth = height;
      height = 1;
      image_height = 1;
      zoffset = yoffset;
      yoffset = 0;
   }

   _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer,
                                        GL_COLOR_ATTACHMENT0,
                                        pbo_tex_image, 0);
   /* If this passes on the first layer it should pass on the others */
   status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto fail;

   _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
                                        GL_COLOR_ATTACHMENT0,
                                        tex_image, zoffset);
   /* If this passes on the first layer it should pass on the others */
   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto fail;

   /* Explicitly disable sRGB encoding */
   ctx->DrawBuffer->Visual.sRGBCapable = false;

   _mesa_update_state(ctx);

   if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                                  0, 0, width, height,
                                  xoffset, yoffset,
                                  xoffset + width, yoffset + height,
                                  GL_COLOR_BUFFER_BIT, GL_NEAREST))
      goto fail;

   for (z = 1; z < depth; z++) {
      _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
                                           GL_COLOR_ATTACHMENT0,
                                           tex_image, zoffset + z);

      _mesa_update_state(ctx);

      _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                                 0, z * image_height,
                                 width, z * image_height + height,
                                 xoffset, yoffset,
                                 xoffset + width, yoffset + height,
                                 GL_COLOR_BUFFER_BIT, GL_NEAREST);
   }

   success = true;

fail:
   _mesa_reference_framebuffer(&readFb, NULL);
   _mesa_reference_framebuffer(&drawFb, NULL);
   _mesa_DeleteTextures(1, &pbo_tex);
   _mesa_reference_buffer_object(ctx, &pbo, NULL);

   _mesa_meta_end(ctx);

   return success;
}
Beispiel #3
0
/**
 * Blit rectangular region, optionally from one framebuffer to another.
 *
 * Note, if the src buffer is multisampled and the dest is not, this is
 * when the samples must be resolved to a single color.
 */
void GLAPIENTRY
_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                         GLbitfield mask, GLenum filter)
{
   const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
                                     GL_DEPTH_BUFFER_BIT |
                                     GL_STENCIL_BUFFER_BIT);
   const struct gl_framebuffer *readFb, *drawFb;
   GET_CURRENT_CONTEXT(ctx);

   FLUSH_VERTICES(ctx, 0);

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx,
                  "glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d, 0x%x, %s)\n",
                  srcX0, srcY0, srcX1, srcY1,
                  dstX0, dstY0, dstX1, dstY1,
                  mask, _mesa_lookup_enum_by_nr(filter));

   if (ctx->NewState) {
      _mesa_update_state(ctx);
   }

   readFb = ctx->ReadBuffer;
   drawFb = ctx->DrawBuffer;

   if (!readFb || !drawFb) {
      /* This will normally never happen but someday we may want to
       * support MakeCurrent() with no drawables.
       */
      return;
   }

   /* check for complete framebuffers */
   if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
       readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "glBlitFramebufferEXT(incomplete draw/read buffers)");
      return;
   }

   if (!is_valid_blit_filter(ctx, filter)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)",
                  _mesa_lookup_enum_by_nr(filter));
      return;
   }

   if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
        filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
        (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)",
                  _mesa_lookup_enum_by_nr(filter));
      return;
   }

   if (mask & ~legalMaskBits) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
      return;
   }

   /* depth/stencil must be blitted with nearest filtering */
   if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
        && filter != GL_NEAREST) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
             "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
      return;
   }

   /* get color read/draw renderbuffers */
   if (mask & GL_COLOR_BUFFER_BIT) {
      const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
      const struct gl_renderbuffer *colorDrawRb = NULL;
      GLuint i;

      /* From the EXT_framebuffer_object spec:
       *
       *     "If a buffer is specified in <mask> and does not exist in both
       *     the read and draw framebuffers, the corresponding bit is silently
       *     ignored."
       */
      if (!colorReadRb || numColorDrawBuffers == 0) {
         mask &= ~GL_COLOR_BUFFER_BIT;
      }
      else {
         for (i = 0; i < numColorDrawBuffers; i++) {
            colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
            if (!colorDrawRb)
               continue;

            /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
             * ES 3.0.1 spec says:
             *
             *     "If the source and destination buffers are identical, an
             *     INVALID_OPERATION error is generated. Different mipmap
             *     levels of a texture, different layers of a three-
             *     dimensional texture or two-dimensional array texture, and
             *     different faces of a cube map texture do not constitute
             *     identical buffers."
             */
            if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glBlitFramebuffer(source and destination color "
                           "buffer cannot be the same)");
               return;
            }

            if (!compatible_color_datatypes(colorReadRb->Format,
                                            colorDrawRb->Format)) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glBlitFramebufferEXT(color buffer datatypes mismatch)");
               return;
            }
            /* extra checks for multisample copies... */
            if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
               /* color formats must match */
               if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
                  _mesa_error(ctx, GL_INVALID_OPERATION,
                         "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
                  return;
               }
            }
         }
         if (filter != GL_NEAREST) {
            /* From EXT_framebuffer_multisample_blit_scaled specification:
             * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
             * if filter is not NEAREST and read buffer contains integer data."
             */
            GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
            if (type == GL_INT || type == GL_UNSIGNED_INT) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glBlitFramebufferEXT(integer color type)");
               return;
            }
         }
      }
   }

   if (mask & GL_STENCIL_BUFFER_BIT) {
      struct gl_renderbuffer *readRb =
         readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
      struct gl_renderbuffer *drawRb =
         drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;

      /* From the EXT_framebuffer_object spec:
       *
       *     "If a buffer is specified in <mask> and does not exist in both
       *     the read and draw framebuffers, the corresponding bit is silently
       *     ignored."
       */
      if ((readRb == NULL) || (drawRb == NULL)) {
	 mask &= ~GL_STENCIL_BUFFER_BIT;
      }
      else {
         int read_z_bits, draw_z_bits;

         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glBlitFramebuffer(source and destination stencil "
                        "buffer cannot be the same)");
            return;
         }

         if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
             _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
            /* There is no need to check the stencil datatype here, because
             * there is only one: GL_UNSIGNED_INT.
             */
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glBlitFramebuffer(stencil attachment format mismatch)");
            return;
         }

         read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
         draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);

         /* If both buffers also have depth data, the depth formats must match
          * as well.  If one doesn't have depth, it's not blitted, so we should
          * ignore the depth format check.
          */
         if (read_z_bits > 0 && draw_z_bits > 0 &&
             (read_z_bits != draw_z_bits ||
              _mesa_get_format_datatype(readRb->Format) !=
              _mesa_get_format_datatype(drawRb->Format))) {

            _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
                        "(stencil attachment depth format mismatch)");
            return;
         }
      }
   }

   if (mask & GL_DEPTH_BUFFER_BIT) {
      struct gl_renderbuffer *readRb =
         readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
      struct gl_renderbuffer *drawRb =
         drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;

      /* From the EXT_framebuffer_object spec:
       *
       *     "If a buffer is specified in <mask> and does not exist in both
       *     the read and draw framebuffers, the corresponding bit is silently
       *     ignored."
       */
      if ((readRb == NULL) || (drawRb == NULL)) {
	 mask &= ~GL_DEPTH_BUFFER_BIT;
      }
      else {
         int read_s_bit, draw_s_bit;

         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glBlitFramebuffer(source and destination depth "
                        "buffer cannot be the same)");
            return;
         }

         if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
              _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
             (_mesa_get_format_datatype(readRb->Format) !=
              _mesa_get_format_datatype(drawRb->Format))) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glBlitFramebuffer(depth attachment format mismatch)");
            return;
         }

         read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
         draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);

         /* If both buffers also have stencil data, the stencil formats must
          * match as well.  If one doesn't have stencil, it's not blitted, so
          * we should ignore the stencil format check.
          */
         if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
            _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
                        "(depth attachment stencil bits mismatch)");
            return;
         }
      }
   }


   if (_mesa_is_gles3(ctx)) {
      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
       * 3.0.1 spec says:
       *
       *     "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
       *     an INVALID_OPERATION error is generated."
       */
      if (drawFb->Visual.samples > 0) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glBlitFramebuffer(destination samples must be 0)");
         return;
      }

      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
       * 3.0.1 spec says:
       *
       *     "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
       *     no copy is performed and an INVALID_OPERATION error is generated
       *     if the formats of the read and draw framebuffers are not
       *     identical or if the source and destination rectangles are not
       *     defined with the same (X0, Y0) and (X1, Y1) bounds."
       *
       * The format check was made above because desktop OpenGL has the same
       * requirement.
       */
      if (readFb->Visual.samples > 0
          && (srcX0 != dstX0 || srcY0 != dstY0
              || srcX1 != dstX1 || srcY1 != dstY1)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glBlitFramebuffer(bad src/dst multisample region)");
         return;
      }
   } else {
      if (readFb->Visual.samples > 0 &&
          drawFb->Visual.samples > 0 &&
          readFb->Visual.samples != drawFb->Visual.samples) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glBlitFramebufferEXT(mismatched samples)");
         return;
      }

      /* extra checks for multisample copies... */
      if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
          (filter == GL_NEAREST || filter == GL_LINEAR)) {
         /* src and dest region sizes must be the same */
         if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
             abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
            return;
         }
      }
   }

   /* Debug code */
   if (DEBUG_BLIT) {
      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
      const struct gl_renderbuffer *colorDrawRb = NULL;
      GLuint i = 0;

      printf("glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d,"
	     " 0x%x, 0x%x)\n",
	     srcX0, srcY0, srcX1, srcY1,
	     dstX0, dstY0, dstX1, dstY1,
	     mask, filter);
      if (colorReadRb) {
         const struct gl_renderbuffer_attachment *att;

         att = find_attachment(readFb, colorReadRb);
         printf("  Src FBO %u  RB %u (%dx%d)  ",
		readFb->Name, colorReadRb->Name,
		colorReadRb->Width, colorReadRb->Height);
         if (att && att->Texture) {
            printf("Tex %u  tgt 0x%x  level %u  face %u",
		   att->Texture->Name,
		   att->Texture->Target,
		   att->TextureLevel,
		   att->CubeMapFace);
         }
         printf("\n");

         /* Print all active color render buffers */
         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
            colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
            if (!colorDrawRb)
               continue;

            att = find_attachment(drawFb, colorDrawRb);
            printf("  Dst FBO %u  RB %u (%dx%d)  ",
		   drawFb->Name, colorDrawRb->Name,
		   colorDrawRb->Width, colorDrawRb->Height);
            if (att && att->Texture) {
               printf("Tex %u  tgt 0x%x  level %u  face %u",
		      att->Texture->Name,
		      att->Texture->Target,
		      att->TextureLevel,
		      att->CubeMapFace);
            }
            printf("\n");
         }
      }
   }

   if (!mask ||
       (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
       (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
      return;
   }

   ASSERT(ctx->Driver.BlitFramebuffer);
   ctx->Driver.BlitFramebuffer(ctx,
                               srcX0, srcY0, srcX1, srcY1,
                               dstX0, dstY0, dstX1, dstY1,
                               mask, filter);
}
Beispiel #4
0
/**
 * Prior to drawing anything with glBegin, glDrawArrays, etc. this function
 * is called to see if it's valid to render.  This involves checking that
 * the current shader is valid and the framebuffer is complete.
 * It also check the current pipeline object is valid if any.
 * If an error is detected it'll be recorded here.
 * \return GL_TRUE if OK to render, GL_FALSE if not
 */
GLboolean
_mesa_valid_to_render(struct gl_context *ctx, const char *where)
{
   /* This depends on having up to date derived state (shaders) */
   if (ctx->NewState)
      _mesa_update_state(ctx);

   if (ctx->API == API_OPENGL_COMPAT) {
      /* Any shader stages that are not supplied by the GLSL shader and have
       * assembly shaders enabled must now be validated.
       */
      if (!ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]
          && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "%s(vertex program not valid)", where);
         return GL_FALSE;
      }

      if (!ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
         if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(fragment program not valid)", where);
            return GL_FALSE;
         }

         /* If drawing to integer-valued color buffers, there must be an
          * active fragment shader (GL_EXT_texture_integer).
          */
         if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(integer format but no fragment shader)", where);
            return GL_FALSE;
         }
      }
   }

   /* A pipeline object is bound */
   if (ctx->_Shader->Name && !ctx->_Shader->Validated) {
      if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glValidateProgramPipeline failed to validate the "
                     "pipeline");
         return GL_FALSE;
      }
   }

   /* If a program is active and SSO not in use, check if validation of
    * samplers succeeded for the active program. */
   if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) {
      char errMsg[100];
      if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram,
                                            errMsg, 100)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg);
         return GL_FALSE;
      }
   }

   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "%s(incomplete framebuffer)", where);
      return GL_FALSE;
   }

   if (!check_blend_func_error(ctx)) {
      return GL_FALSE;
   }

#ifdef DEBUG
   if (ctx->_Shader->Flags & GLSL_LOG) {
      struct gl_shader_program **shProg = ctx->_Shader->CurrentProgram;
      gl_shader_stage i;

      for (i = 0; i < MESA_SHADER_STAGES; i++) {
	 if (shProg[i] == NULL || shProg[i]->_Used
	     || shProg[i]->_LinkedShaders[i] == NULL)
	    continue;

	 /* This is the first time this shader is being used.
	  * Append shader's constants/uniforms to log file.
	  *
	  * Only log data for the program target that matches the shader
	  * target.  It's possible to have a program bound to the vertex
	  * shader target that also supplied a fragment shader.  If that
	  * program isn't also bound to the fragment shader target we don't
	  * want to log its fragment data.
	  */
	 _mesa_append_uniforms_to_file(shProg[i]->_LinkedShaders[i]);
      }

      for (i = 0; i < MESA_SHADER_STAGES; i++) {
	 if (shProg[i] != NULL)
	    shProg[i]->_Used = GL_TRUE;
      }
   }
#endif

   return GL_TRUE;
}
Beispiel #5
0
/* May fail if out of video memory for texture or vbo upload, or on
 * fallback conditions.
 */
static bool brw_try_draw_prims( struct gl_context *ctx,
				     const struct gl_client_array *arrays[],
				     const struct _mesa_prim *prim,
				     GLuint nr_prims,
				     const struct _mesa_index_buffer *ib,
				     GLuint min_index,
				     GLuint max_index )
{
   struct intel_context *intel = intel_context(ctx);
   struct brw_context *brw = brw_context(ctx);
   bool retval = true;
   GLuint i;
   bool fail_next = false;

   if (ctx->NewState)
      _mesa_update_state( ctx );

   /* We have to validate the textures *before* checking for fallbacks;
    * otherwise, the software fallback won't be able to rely on the
    * texture state, the firstLevel and lastLevel fields won't be
    * set in the intel texture object (they'll both be 0), and the 
    * software fallback will segfault if it attempts to access any
    * texture level other than level 0.
    */
   brw_validate_textures( brw );

   /* Resolves must occur after updating state and finalizing textures but
    * before setting up any hardware state for this draw call.
    */
   brw_predraw_resolve_buffers(brw);

   /* Bind all inputs, derive varying and size information:
    */
   brw_merge_inputs( brw, arrays );

   brw->ib.ib = ib;
   brw->state.dirty.brw |= BRW_NEW_INDICES;

   brw->vb.min_index = min_index;
   brw->vb.max_index = max_index;
   brw->state.dirty.brw |= BRW_NEW_VERTICES;

   /* Have to validate state quite late.  Will rebuild tnl_program,
    * which depends on varying information.  
    * 
    * Note this is where brw->vs->prog_data.inputs_read is calculated,
    * so can't access it earlier.
    */

   intel_prepare_render(intel);

   for (i = 0; i < nr_prims; i++) {
      int estimated_max_prim_size;

      estimated_max_prim_size = 512; /* batchbuffer commands */
      estimated_max_prim_size += (BRW_MAX_TEX_UNIT *
				  (sizeof(struct brw_sampler_state) +
				   sizeof(struct gen5_sampler_default_color)));
      estimated_max_prim_size += 1024; /* gen6 VS push constants */
      estimated_max_prim_size += 1024; /* gen6 WM push constants */
      estimated_max_prim_size += 512; /* misc. pad */

      /* Flush the batch if it's approaching full, so that we don't wrap while
       * we've got validated state that needs to be in the same batch as the
       * primitives.
       */
      intel_batchbuffer_require_space(intel, estimated_max_prim_size, false);
      intel_batchbuffer_save_state(intel);

      if (intel->gen < 6)
	 brw_set_prim(brw, &prim[i]);
      else
	 gen6_set_prim(brw, &prim[i]);

retry:
      /* Note that before the loop, brw->state.dirty.brw was set to != 0, and
       * that the state updated in the loop outside of this block is that in
       * *_set_prim or intel_batchbuffer_flush(), which only impacts
       * brw->state.dirty.brw.
       */
      if (brw->state.dirty.brw) {
	 intel->no_batch_wrap = true;
	 brw_upload_state(brw);

	 if (unlikely(brw->intel.Fallback)) {
	    intel->no_batch_wrap = false;
	    retval = false;
	    goto out;
	 }
      }

      if (intel->gen >= 7)
	 gen7_emit_prim(brw, &prim[i], brw->primitive);
      else
	 brw_emit_prim(brw, &prim[i], brw->primitive);

      intel->no_batch_wrap = false;

      if (dri_bufmgr_check_aperture_space(&intel->batch.bo, 1)) {
	 if (!fail_next) {
	    intel_batchbuffer_reset_to_saved(intel);
	    intel_batchbuffer_flush(intel);
	    fail_next = true;
	    goto retry;
	 } else {
	    if (intel_batchbuffer_flush(intel) == -ENOSPC) {
	       static bool warned = false;

	       if (!warned) {
		  fprintf(stderr, "i965: Single primitive emit exceeded"
			  "available aperture space\n");
		  warned = true;
	       }

	       retval = false;
	    }
	 }
      }

      if (!_mesa_meta_in_progress(ctx))
         brw_update_primitive_count(brw, &prim[i]);
   }

   if (intel->always_flush_batch)
      intel_batchbuffer_flush(intel);
 out:

   brw_state_cache_check_size(brw);
   brw_postdraw_set_buffers_need_resolve(brw);

   return retval;
}
Beispiel #6
0
void GLAPIENTRY
_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
{
   GLuint maxUnit;
   const struct gl_texture_unit *texUnit;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
      ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
   if (ctx->Texture.CurrentUnit >= maxUnit) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
      return;
   }

   texUnit = _mesa_get_current_tex_unit(ctx);

   if (target == GL_TEXTURE_ENV) {
      if (pname == GL_TEXTURE_ENV_COLOR) {
         if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
            _mesa_update_state(ctx);
         if(ctx->Color._ClampFragmentColor)
            COPY_4FV( params, texUnit->EnvColor );
         else
            COPY_4FV( params, texUnit->EnvColorUnclamped );
      }
      else {
         GLint val = get_texenvi(ctx, texUnit, pname);
         if (val >= 0) {
            *params = (GLfloat) val;
         }
      }
   }
   else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
      if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
         *params = texUnit->LodBias;
      }
      else {
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
	 return;
      }
   }
   else if (target == GL_POINT_SPRITE_NV) {
      /* GL_ARB_point_sprite / GL_NV_point_sprite */
      if (!ctx->Extensions.NV_point_sprite
	  && !ctx->Extensions.ARB_point_sprite) {
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
         return;
      }
      if (pname == GL_COORD_REPLACE_NV) {
         *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
      }
      else {
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
         return;
      }
   }
   else {
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
      return;
   }
}
Beispiel #7
0
/*
 * Render a bitmap.
 */
static bool
do_blit_bitmap( struct gl_context *ctx,
		GLint dstx, GLint dsty,
		GLsizei width, GLsizei height,
		const struct gl_pixelstore_attrib *unpack,
		const GLubyte *bitmap )
{
   struct brw_context *brw = brw_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct intel_renderbuffer *irb;
   GLfloat tmpColor[4];
   GLubyte ubcolor[4];
   GLuint color;
   GLsizei bitmap_width = width;
   GLsizei bitmap_height = height;
   GLint px, py;
   GLuint stipple[32];
   GLint orig_dstx = dstx;
   GLint orig_dsty = dsty;

   /* Update draw buffer bounds */
   _mesa_update_state(ctx);

   if (ctx->Depth.Test) {
      /* The blit path produces incorrect results when depth testing is on.
       * It seems the blit Z coord is always 1.0 (the far plane) so fragments
       * will likely be obscured by other, closer geometry.
       */
      return false;
   }

   intel_prepare_render(brw);

   if (fb->_NumColorDrawBuffers != 1) {
      perf_debug("accelerated glBitmap() only supports rendering to a "
                 "single color buffer\n");
      return false;
   }

   irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);

   if (_mesa_is_bufferobj(unpack->BufferObj)) {
      bitmap = map_pbo(ctx, width, height, unpack, bitmap);
      if (bitmap == NULL)
	 return true;	/* even though this is an error, we're done */
   }

   COPY_4V(tmpColor, ctx->Current.RasterColor);

   if (_mesa_need_secondary_color(ctx)) {
       ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
   }

   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]);

   switch (_mesa_get_render_format(ctx, intel_rb_format(irb))) {
   case MESA_FORMAT_B8G8R8A8_UNORM:
   case MESA_FORMAT_B8G8R8X8_UNORM:
      color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]);
      break;
   case MESA_FORMAT_B5G6R5_UNORM:
      color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]);
      break;
   default:
      perf_debug("Unsupported format %s in accelerated glBitmap()\n",
                 _mesa_get_format_name(irb->mt->format));
      return false;
   }

   if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F))
      return false;

   /* Clip to buffer bounds and scissor. */
   if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
			     fb->_Xmax, fb->_Ymax,
			     &dstx, &dsty, &width, &height))
      goto out;

   dsty = y_flip(fb, dsty, height);

#define DY 32
#define DX 32

   /* The blitter has no idea about fast color clears, so we need to resolve
    * the miptree before we do anything.
    */
   intel_miptree_all_slices_resolve_color(brw, irb->mt, 0);

   /* Chop it all into chunks that can be digested by hardware: */
   for (py = 0; py < height; py += DY) {
      for (px = 0; px < width; px += DX) {
	 int h = MIN2(DY, height - py);
	 int w = MIN2(DX, width - px);
	 GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8;
	 GLenum logic_op = ctx->Color.ColorLogicOpEnabled ?
	    ctx->Color.LogicOp : GL_COPY;

	 assert(sz <= sizeof(stipple));
	 memset(stipple, 0, sz);

	 /* May need to adjust this when padding has been introduced in
	  * sz above:
	  *
	  * Have to translate destination coordinates back into source
	  * coordinates.
	  */
         int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack,
                                     bitmap,
                                     -orig_dstx + (dstx + px),
                                     -orig_dsty + y_flip(fb, dsty + py, h),
                                     w, h,
                                     (GLubyte *)stipple,
                                     8,
                                     _mesa_is_winsys_fbo(fb));
         if (count == 0)
	    continue;

	 if (!intelEmitImmediateColorExpandBlit(brw,
						irb->mt->cpp,
						(GLubyte *)stipple,
						sz,
						color,
						irb->mt->pitch,
						irb->mt->bo,
						0,
						irb->mt->tiling,
						dstx + px,
						dsty + py,
						w, h,
						logic_op)) {
	    return false;
	 }

         if (ctx->Query.CurrentOcclusionObject)
            ctx->Query.CurrentOcclusionObject->Result += count;
      }
   }
out:

   if (unlikely(INTEL_DEBUG & DEBUG_SYNC))
      intel_batchbuffer_flush(brw);

   if (_mesa_is_bufferobj(unpack->BufferObj)) {
      /* done with PBO so unmap it now */
      ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL);
   }

   return true;
}