/**
 * Called via glMapBufferRange and glMapBuffer
 *
 * The goal of this extension is to allow apps to accumulate their rendering
 * at the same time as they accumulate their buffer object.  Without it,
 * you'd end up blocking on execution of rendering every time you mapped
 * the buffer to put new data in.
 *
 * We support it in 3 ways: If unsynchronized, then don't bother
 * flushing the batchbuffer before mapping the buffer, which can save blocking
 * in many cases.  If we would still block, and they allow the whole buffer
 * to be invalidated, then just allocate a new buffer to replace the old one.
 * If not, and we'd block, and they allow the subrange of the buffer to be
 * invalidated, then we can make a new little BO, let them write into that,
 * and blit it into the real BO at unmap time.
 */
static void *
intel_bufferobj_map_range(struct gl_context * ctx,
			  GLintptr offset, GLsizeiptr length,
			  GLbitfield access, struct gl_buffer_object *obj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);

   assert(intel_obj);

   /* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also
    * internally uses our functions directly.
    */
   obj->Offset = offset;
   obj->Length = length;
   obj->AccessFlags = access;

   if (intel_obj->sys_buffer) {
      const bool read_only =
	 (access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == GL_MAP_READ_BIT;

      if (!read_only && intel_obj->source)
	 release_buffer(intel_obj);

      if (!intel_obj->buffer || intel_obj->source) {
	 obj->Pointer = intel_obj->sys_buffer + offset;
	 return obj->Pointer;
      }

      free(intel_obj->sys_buffer);
      intel_obj->sys_buffer = NULL;
   }

   /* If the mapping is synchronized with other GL operations, flush
    * the batchbuffer so that GEM knows about the buffer access for later
    * syncing.
    */
   if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) &&
       drm_intel_bo_references(intel->batch.bo, intel_obj->buffer))
      intel_flush(ctx);

   if (intel_obj->buffer == NULL) {
      obj->Pointer = NULL;
      return NULL;
   }

   /* If the user doesn't care about existing buffer contents and mapping
    * would cause us to block, then throw out the old buffer.
    */
   if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) &&
       (access & GL_MAP_INVALIDATE_BUFFER_BIT) &&
       drm_intel_bo_busy(intel_obj->buffer)) {
      drm_intel_bo_unreference(intel_obj->buffer);
      intel_bufferobj_alloc_buffer(intel, intel_obj);
   }

   /* If the user is mapping a range of an active buffer object but
    * doesn't require the current contents of that range, make a new
    * BO, and we'll copy what they put in there out at unmap or
    * FlushRange time.
    */
   if ((access & GL_MAP_INVALIDATE_RANGE_BIT) &&
       drm_intel_bo_busy(intel_obj->buffer)) {
      if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {
	 intel_obj->range_map_buffer = malloc(length);
	 obj->Pointer = intel_obj->range_map_buffer;
      } else {
	 intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr,
						      "range map",
						      length, 64);
	 if (!(access & GL_MAP_READ_BIT)) {
	    drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo);
	    intel_obj->mapped_gtt = true;
	 } else {
	    drm_intel_bo_map(intel_obj->range_map_bo,
			     (access & GL_MAP_WRITE_BIT) != 0);
	    intel_obj->mapped_gtt = false;
	 }
	 obj->Pointer = intel_obj->range_map_bo->virtual;
      }
      return obj->Pointer;
   }

   if (!(access & GL_MAP_READ_BIT)) {
      drm_intel_gem_bo_map_gtt(intel_obj->buffer);
      intel_obj->mapped_gtt = true;
   } else {
      drm_intel_bo_map(intel_obj->buffer, (access & GL_MAP_WRITE_BIT) != 0);
      intel_obj->mapped_gtt = false;
   }

   obj->Pointer = intel_obj->buffer->virtual + offset;
   return obj->Pointer;
}
/**
 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
 * We can do this when the dst renderbuffer is actually a texture and
 * there is no scaling, mirroring or scissoring.
 *
 * \return new buffer mask indicating the buffers left to blit using the
 *         normal path.
 */
static GLbitfield
intel_blit_framebuffer_with_blitter(struct gl_context *ctx,
                                    GLint srcX0, GLint srcY0,
                                    GLint srcX1, GLint srcY1,
                                    GLint dstX0, GLint dstY0,
                                    GLint dstX1, GLint dstY1,
                                    GLbitfield mask, GLenum filter)
{
   struct intel_context *intel = intel_context(ctx);

   if (mask & GL_COLOR_BUFFER_BIT) {
      GLint i;
      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
      struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer;
      struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb);

      if (!src_irb) {
         perf_debug("glBlitFramebuffer(): missing src renderbuffer.  "
                    "Falling back to software rendering.\n");
         return mask;
      }

      /* If the source and destination are the same size with no mirroring,
       * the rectangles are within the size of the texture and there is no
       * scissor, then we can probably use the blit engine.
       */
      if (!(srcX0 - srcX1 == dstX0 - dstX1 &&
            srcY0 - srcY1 == dstY0 - dstY1 &&
            srcX1 >= srcX0 &&
            srcY1 >= srcY0 &&
            srcX0 >= 0 && srcX1 <= readFb->Width &&
            srcY0 >= 0 && srcY1 <= readFb->Height &&
            dstX0 >= 0 && dstX1 <= drawFb->Width &&
            dstY0 >= 0 && dstY1 <= drawFb->Height &&
            !ctx->Scissor.EnableFlags)) {
         perf_debug("glBlitFramebuffer(): non-1:1 blit.  "
                    "Falling back to software rendering.\n");
         return mask;
      }

      /* Blit to all active draw buffers.  We don't do any pre-checking,
       * because we assume that copying to MRTs is rare, and failure midway
       * through copying is even more rare.  Even if it was to occur, it's
       * safe to let meta start the copy over from scratch, because
       * glBlitFramebuffer completely overwrites the destination pixels, and
       * results are undefined if any destination pixels have a dependency on
       * source pixels.
       */
      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
         struct gl_renderbuffer *dst_rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
         struct intel_renderbuffer *dst_irb = intel_renderbuffer(dst_rb);

         if (!dst_irb) {
            perf_debug("glBlitFramebuffer(): missing dst renderbuffer.  "
                       "Falling back to software rendering.\n");
            return mask;
         }

         mesa_format src_format = _mesa_get_srgb_format_linear(src_rb->Format);
         mesa_format dst_format = _mesa_get_srgb_format_linear(dst_rb->Format);
         if (src_format != dst_format) {
            perf_debug("glBlitFramebuffer(): unsupported blit from %s to %s.  "
                       "Falling back to software rendering.\n",
                       _mesa_get_format_name(src_format),
                       _mesa_get_format_name(dst_format));
            return mask;
         }

         if (!intel_miptree_blit(intel,
                                 src_irb->mt,
                                 src_irb->mt_level, src_irb->mt_layer,
                                 srcX0, srcY0, src_rb->Name == 0,
                                 dst_irb->mt,
                                 dst_irb->mt_level, dst_irb->mt_layer,
                                 dstX0, dstY0, dst_rb->Name == 0,
                                 dstX1 - dstX0, dstY1 - dstY0, GL_COPY)) {
            perf_debug("glBlitFramebuffer(): unknown blit failure.  "
                       "Falling back to software rendering.\n");
            return mask;
         }
      }

      mask &= ~GL_COLOR_BUFFER_BIT;
   }

   return mask;
}
Example #3
0
/**
 * Perform glClear where mask contains only color, depth, and/or stencil.
 *
 * The implementation is based on calling into Mesa to set GL state and
 * performing normal triangle rendering.  The intent of this path is to
 * have as generic a path as possible, so that any driver could make use of
 * it.
 */
void
intel_clear_tris(GLcontext *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   GLfloat dst_z;
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   int i;
   GLboolean saved_fp_enable = GL_FALSE, saved_vp_enable = GL_FALSE;
   GLuint saved_shader_program = 0;
   unsigned int saved_active_texture;
   struct gl_array_object *arraySave = NULL;

   if (!intel->clear.arrayObj)
      init_clear(ctx);

   assert((mask & ~(TRI_CLEAR_COLOR_BITS | BUFFER_BIT_DEPTH |
		    BUFFER_BIT_STENCIL)) == 0);

   _mesa_PushAttrib(GL_COLOR_BUFFER_BIT |
		    GL_CURRENT_BIT |
		    GL_DEPTH_BUFFER_BIT |
		    GL_ENABLE_BIT |
		    GL_POLYGON_BIT |
		    GL_STENCIL_BUFFER_BIT |
		    GL_TRANSFORM_BIT |
		    GL_CURRENT_BIT);
   saved_active_texture = ctx->Texture.CurrentUnit;

   /* Disable existing GL state we don't want to apply to a clear. */
   _mesa_Disable(GL_ALPHA_TEST);
   _mesa_Disable(GL_BLEND);
   _mesa_Disable(GL_CULL_FACE);
   _mesa_Disable(GL_FOG);
   _mesa_Disable(GL_POLYGON_SMOOTH);
   _mesa_Disable(GL_POLYGON_STIPPLE);
   _mesa_Disable(GL_POLYGON_OFFSET_FILL);
   _mesa_Disable(GL_LIGHTING);
   _mesa_Disable(GL_CLIP_PLANE0);
   _mesa_Disable(GL_CLIP_PLANE1);
   _mesa_Disable(GL_CLIP_PLANE2);
   _mesa_Disable(GL_CLIP_PLANE3);
   _mesa_Disable(GL_CLIP_PLANE4);
   _mesa_Disable(GL_CLIP_PLANE5);
   _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   if (ctx->Extensions.ARB_fragment_program && ctx->FragmentProgram.Enabled) {
      saved_fp_enable = GL_TRUE;
      _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
   }
   if (ctx->Extensions.ARB_vertex_program && ctx->VertexProgram.Enabled) {
      saved_vp_enable = GL_TRUE;
      _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
   }
   if (ctx->Extensions.ARB_shader_objects && ctx->Shader.CurrentProgram) {
      saved_shader_program = ctx->Shader.CurrentProgram->Name;
      _mesa_UseProgramObjectARB(0);
   }

   if (ctx->Texture._EnabledUnits != 0) {
      int i;

      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
	 _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
	 _mesa_Disable(GL_TEXTURE_1D);
	 _mesa_Disable(GL_TEXTURE_2D);
	 _mesa_Disable(GL_TEXTURE_3D);
	 if (ctx->Extensions.ARB_texture_cube_map)
	    _mesa_Disable(GL_TEXTURE_CUBE_MAP_ARB);
	 if (ctx->Extensions.NV_texture_rectangle)
	    _mesa_Disable(GL_TEXTURE_RECTANGLE_NV);
	 if (ctx->Extensions.MESA_texture_array) {
	    _mesa_Disable(GL_TEXTURE_1D_ARRAY_EXT);
	    _mesa_Disable(GL_TEXTURE_2D_ARRAY_EXT);
	 }
      }
   }

   /* save current array object, bind our private one */
   _mesa_reference_array_object(ctx, &arraySave, ctx->Array.ArrayObj);
   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, intel->clear.arrayObj);

   intel_meta_set_passthrough_transform(intel);

   for (i = 0; i < 4; i++) {
      COPY_4FV(intel->clear.color[i], ctx->Color.ClearColor);
   }

   /* convert clear Z from [0,1] to NDC coord in [-1,1] */
   dst_z = -1.0 + 2.0 * ctx->Depth.Clear;

   /* Prepare the vertices, which are the same regardless of which buffer we're
    * drawing to.
    */
   intel->clear.vertices[0][0] = fb->_Xmin;
   intel->clear.vertices[0][1] = fb->_Ymin;
   intel->clear.vertices[0][2] = dst_z;
   intel->clear.vertices[1][0] = fb->_Xmax;
   intel->clear.vertices[1][1] = fb->_Ymin;
   intel->clear.vertices[1][2] = dst_z;
   intel->clear.vertices[2][0] = fb->_Xmax;
   intel->clear.vertices[2][1] = fb->_Ymax;
   intel->clear.vertices[2][2] = dst_z;
   intel->clear.vertices[3][0] = fb->_Xmin;
   intel->clear.vertices[3][1] = fb->_Ymax;
   intel->clear.vertices[3][2] = dst_z;

   while (mask != 0) {
      GLuint this_mask = 0;
      GLuint color_bit;

      color_bit = _mesa_ffs(mask & TRI_CLEAR_COLOR_BITS);
      if (color_bit != 0)
	 this_mask |= (1 << (color_bit - 1));

      /* Clear depth/stencil in the same pass as color. */
      this_mask |= (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL));

      /* Select the current color buffer and use the color write mask if
       * we have one, otherwise don't write any color channels.
       */
      if (this_mask & BUFFER_BIT_FRONT_LEFT)
	 _mesa_DrawBuffer(GL_FRONT_LEFT);
      else if (this_mask & BUFFER_BIT_BACK_LEFT)
	 _mesa_DrawBuffer(GL_BACK_LEFT);
      else if (color_bit != 0)
	 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0 +
			  (color_bit - BUFFER_COLOR0 - 1));
      else
	 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

      /* Control writing of the depth clear value to depth. */
      if (this_mask & BUFFER_BIT_DEPTH) {
	 _mesa_DepthFunc(GL_ALWAYS);
	 _mesa_Enable(GL_DEPTH_TEST);
      } else {
	 _mesa_Disable(GL_DEPTH_TEST);
	 _mesa_DepthMask(GL_FALSE);
      }

      /* Control writing of the stencil clear value to stencil. */
      if (this_mask & BUFFER_BIT_STENCIL) {
	 _mesa_Enable(GL_STENCIL_TEST);
	 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
				 GL_REPLACE, GL_REPLACE, GL_REPLACE);
	 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
				   ctx->Stencil.Clear,
				   ctx->Stencil.WriteMask[0]);
      } else {
	 _mesa_Disable(GL_STENCIL_TEST);
      }

      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);

      mask &= ~this_mask;
   }

   intel_meta_restore_transform(intel);

   _mesa_ActiveTextureARB(GL_TEXTURE0 + saved_active_texture);
   if (saved_fp_enable)
      _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
   if (saved_vp_enable)
      _mesa_Enable(GL_VERTEX_PROGRAM_ARB);

   if (saved_shader_program)
      _mesa_UseProgramObjectARB(saved_shader_program);

   _mesa_PopAttrib();

   /* restore current array object */
   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, arraySave);
   _mesa_reference_array_object(ctx, &arraySave, NULL);
}
Example #4
0
/* Fallback to swrast for select and feedback.
 */
static void
i830RenderMode(struct gl_context *ctx, GLenum mode)
{
   struct intel_context *intel = intel_context(ctx);
   FALLBACK(intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER));
}
Example #5
0
/**
 * Initializes potential list of extensions if ctx == NULL, or actually enables
 * extensions for a context.
 */
void
intelInitExtensions(struct gl_context *ctx)
{
   struct intel_context *intel = intel_context(ctx);

   ctx->Extensions.ARB_draw_elements_base_vertex = true;
   ctx->Extensions.ARB_explicit_attrib_location = true;
   ctx->Extensions.ARB_framebuffer_object = true;
   ctx->Extensions.ARB_half_float_pixel = true;
   ctx->Extensions.ARB_internalformat_query = true;
   ctx->Extensions.ARB_map_buffer_range = true;
   ctx->Extensions.ARB_point_sprite = true;
   ctx->Extensions.ARB_shader_objects = true;
   ctx->Extensions.ARB_shading_language_100 = true;
   ctx->Extensions.ARB_sync = true;
   ctx->Extensions.ARB_texture_border_clamp = true;
   ctx->Extensions.ARB_texture_cube_map = true;
   ctx->Extensions.ARB_texture_env_combine = true;
   ctx->Extensions.ARB_texture_env_crossbar = true;
   ctx->Extensions.ARB_texture_env_dot3 = true;
   ctx->Extensions.ARB_texture_storage = true;
   ctx->Extensions.ARB_vertex_program = true;
   ctx->Extensions.ARB_vertex_shader = true;
   ctx->Extensions.EXT_blend_color = true;
   ctx->Extensions.EXT_blend_equation_separate = true;
   ctx->Extensions.EXT_blend_func_separate = true;
   ctx->Extensions.EXT_blend_minmax = true;
   ctx->Extensions.EXT_framebuffer_blit = true;
   ctx->Extensions.EXT_framebuffer_object = true;
   ctx->Extensions.EXT_fog_coord = true;
   ctx->Extensions.EXT_gpu_program_parameters = true;
   ctx->Extensions.EXT_packed_depth_stencil = true;
   ctx->Extensions.EXT_pixel_buffer_object = true;
   ctx->Extensions.EXT_point_parameters = true;
   ctx->Extensions.EXT_provoking_vertex = true;
   ctx->Extensions.EXT_secondary_color = true;
   ctx->Extensions.EXT_separate_shader_objects = true;
   ctx->Extensions.EXT_texture_env_dot3 = true;
   ctx->Extensions.EXT_texture_filter_anisotropic = true;
   ctx->Extensions.APPLE_object_purgeable = true;
   ctx->Extensions.MESA_pack_invert = true;
   ctx->Extensions.MESA_ycbcr_texture = true;
   ctx->Extensions.NV_blend_square = true;
   ctx->Extensions.NV_texture_rectangle = true;
   ctx->Extensions.TDFX_texture_compression_FXT1 = true;
   ctx->Extensions.OES_EGL_image = true;
   ctx->Extensions.OES_draw_texture = true;

   if (intel->gen >= 6)
      ctx->Const.GLSLVersion = 140;
   else
      ctx->Const.GLSLVersion = 120;
   _mesa_override_glsl_version(ctx);

   if (intel->gen == 6 ||
       (intel->gen == 7 && intel->intelScreen->kernel_has_gen7_sol_reset))
      ctx->Extensions.EXT_transform_feedback = true;

   if (intel->gen >= 6) {
      ctx->Extensions.EXT_framebuffer_multisample = true;
      ctx->Extensions.ARB_blend_func_extended = !driQueryOptionb(&intel->optionCache, "disable_blend_func_extended");
      ctx->Extensions.ARB_draw_buffers_blend = true;
      ctx->Extensions.ARB_ES3_compatibility = true;
      ctx->Extensions.ARB_uniform_buffer_object = true;
      ctx->Extensions.ARB_texture_buffer_object = true;
      ctx->Extensions.ARB_texture_buffer_object_rgb32 = true;
      ctx->Extensions.ARB_texture_cube_map_array = true;
      ctx->Extensions.OES_depth_texture_cube_map = true;
      ctx->Extensions.ARB_shading_language_packing = true;
   }

   if (intel->gen >= 5)
      ctx->Extensions.EXT_timer_query = true;

   if (intel->gen >= 6) {
      uint64_t dummy;
      /* Test if the kernel has the ioctl. */
      if (drm_intel_reg_read(intel->bufmgr, TIMESTAMP, &dummy) == 0)
         ctx->Extensions.ARB_timer_query = true;
   }

   if (intel->gen >= 4) {
      if (ctx->API == API_OPENGL_CORE)
         ctx->Extensions.ARB_base_instance = true;
      ctx->Extensions.ARB_color_buffer_float = true;
      ctx->Extensions.ARB_depth_buffer_float = true;
      ctx->Extensions.ARB_depth_clamp = true;
      ctx->Extensions.ARB_draw_instanced = true;
      ctx->Extensions.ARB_instanced_arrays = true;
      ctx->Extensions.ARB_fragment_coord_conventions = true;
      ctx->Extensions.ARB_fragment_program_shadow = true;
      ctx->Extensions.ARB_fragment_shader = true;
      ctx->Extensions.ARB_half_float_vertex = true;
      ctx->Extensions.ARB_occlusion_query = true;
      ctx->Extensions.ARB_occlusion_query2 = true;
      ctx->Extensions.ARB_point_sprite = true;
      ctx->Extensions.ARB_seamless_cube_map = true;
      ctx->Extensions.ARB_shader_bit_encoding = true;
      ctx->Extensions.ARB_shader_texture_lod = true;
      ctx->Extensions.ARB_texture_float = true;
      ctx->Extensions.EXT_texture_shared_exponent = true;
      ctx->Extensions.EXT_packed_float = true;
      ctx->Extensions.ARB_texture_compression_rgtc = true;
      ctx->Extensions.ARB_texture_rg = true;
      ctx->Extensions.ARB_texture_rgb10_a2ui = true;
      ctx->Extensions.ARB_vertex_type_2_10_10_10_rev = true;
      ctx->Extensions.EXT_draw_buffers2 = true;
      ctx->Extensions.EXT_framebuffer_sRGB = true;
      ctx->Extensions.EXT_texture_array = true;
      ctx->Extensions.EXT_texture_integer = true;
      ctx->Extensions.EXT_texture_snorm = true;
      ctx->Extensions.EXT_texture_sRGB = true;
      ctx->Extensions.EXT_texture_sRGB_decode = true;
      ctx->Extensions.EXT_texture_swizzle = true;
      ctx->Extensions.EXT_vertex_array_bgra = true;
      ctx->Extensions.ATI_envmap_bumpmap = true;
      ctx->Extensions.MESA_texture_array = true;
      ctx->Extensions.NV_conditional_render = true;
      ctx->Extensions.OES_compressed_ETC1_RGB8_texture = true;
      ctx->Extensions.OES_standard_derivatives = true;
   }

   if (intel->gen >= 3) {
      ctx->Extensions.ARB_ES2_compatibility = true;
      ctx->Extensions.ARB_depth_texture = true;
      ctx->Extensions.ARB_fragment_program = true;
      ctx->Extensions.ARB_shadow = true;
      ctx->Extensions.ARB_texture_non_power_of_two = true;
      ctx->Extensions.EXT_shadow_funcs = true;
      ctx->Extensions.EXT_stencil_two_side = true;
      ctx->Extensions.ATI_separate_stencil = true;
      ctx->Extensions.ATI_texture_env_combine3 = true;
      ctx->Extensions.NV_texture_env_combine4 = true;

      if (driQueryOptionb(&intel->optionCache, "fragment_shader"))
	 ctx->Extensions.ARB_fragment_shader = true;

      if (driQueryOptionb(&intel->optionCache, "stub_occlusion_query"))
	 ctx->Extensions.ARB_occlusion_query = true;
   }

   if (intel->ctx.Mesa_DXTn
       || driQueryOptionb(&intel->optionCache, "force_s3tc_enable"))
      ctx->Extensions.EXT_texture_compression_s3tc = true;

   ctx->Extensions.ANGLE_texture_compression_dxt = true;

   if (intel->gen >= 4) {
      ctx->Extensions.NV_primitive_restart = true;
   }
}
Example #6
0
/* May fail if out of video memory for texture or vbo upload, or on
 * fallback conditions.
 */
static GLboolean brw_try_draw_prims( GLcontext *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);
   GLboolean retval = GL_FALSE;
   GLboolean warn = GL_FALSE;
   GLboolean first_time = GL_TRUE;
   GLuint i;

   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 );

   if (check_fallbacks(brw, prim, nr_prims))
      return GL_FALSE;

   /* 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++) {
      uint32_t hw_prim;

      /* 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.  This fraction is just a guess (minimal full state plus
       * a primitive is around 512 bytes), and would be better if we had
       * an upper bound of how much we might emit in a single
       * brw_try_draw_prims().
       */
      intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4);

      hw_prim = brw_set_prim(brw, &prim[i]);

      if (first_time || (brw->state.dirty.brw & BRW_NEW_PRIMITIVE)) {
	 first_time = GL_FALSE;

	 brw_validate_state(brw);

	 /* Various fallback checks:  */
	 if (brw->intel.Fallback)
	    goto out;

	 /* Check that we can fit our state in with our existing batchbuffer, or
	  * flush otherwise.
	  */
	 if (dri_bufmgr_check_aperture_space(brw->state.validated_bos,
					     brw->state.validated_bo_count)) {
	    static GLboolean warned;
	    intel_batchbuffer_flush(intel->batch);

	    /* Validate the state after we flushed the batch (which would have
	     * changed the set of dirty state).  If we still fail to
	     * check_aperture, warn of what's happening, but attempt to continue
	     * on since it may succeed anyway, and the user would probably rather
	     * see a failure and a warning than a fallback.
	     */
	    brw_validate_state(brw);
	    if (!warned &&
		dri_bufmgr_check_aperture_space(brw->state.validated_bos,
						brw->state.validated_bo_count)) {
	       warn = GL_TRUE;
	       warned = GL_TRUE;
	    }
	 }

	 intel->no_batch_wrap = GL_TRUE;
	 brw_upload_state(brw);
      }

      brw_emit_prim(brw, &prim[i], hw_prim);

      intel->no_batch_wrap = GL_FALSE;

      retval = GL_TRUE;
   }

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

   brw_state_cache_check_size(brw);

   if (warn)
      fprintf(stderr, "i965: Single primitive emit potentially exceeded "
	      "available aperture space\n");

   if (!retval)
      DBG("%s failed\n", __FUNCTION__);

   return retval;
}
Example #7
0
static void brw_emit_vertices(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->intel.ctx;
   struct intel_context *intel = intel_context(ctx);
   GLuint i, nr_elements;

   brw_prepare_vertices(brw);

   brw_emit_query_begin(brw);

   /* If the VS doesn't read any inputs (calculating vertex position from
    * a state variable for some reason, for example), emit a single pad
    * VERTEX_ELEMENT struct and bail.
    *
    * The stale VB state stays in place, but they don't do anything unless
    * a VE loads from them.
    */
   if (brw->vb.nr_enabled == 0) {
      BEGIN_BATCH(3);
      OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | 1);
      if (intel->gen >= 6) {
	 OUT_BATCH((0 << GEN6_VE0_INDEX_SHIFT) |
		   GEN6_VE0_VALID |
		   (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) |
		   (0 << BRW_VE0_SRC_OFFSET_SHIFT));
      } else {
	 OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) |
		   BRW_VE0_VALID |
		   (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) |
		   (0 << BRW_VE0_SRC_OFFSET_SHIFT));
      }
      OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) |
		(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
		(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
		(BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT));
      CACHED_BATCH();
      return;
   }

   /* Now emit VB and VEP state packets.
    */

   if (brw->vb.nr_buffers) {
      if (intel->gen >= 6) {
	 assert(brw->vb.nr_buffers <= 33);
      } else {
	 assert(brw->vb.nr_buffers <= 17);
      }

      BEGIN_BATCH(1 + 4*brw->vb.nr_buffers);
      OUT_BATCH((_3DSTATE_VERTEX_BUFFERS << 16) | (4*brw->vb.nr_buffers - 1));
      for (i = 0; i < brw->vb.nr_buffers; i++) {
	 struct brw_vertex_buffer *buffer = &brw->vb.buffers[i];
	 uint32_t dw0;

	 if (intel->gen >= 6) {
	    dw0 = buffer->step_rate
	             ? GEN6_VB0_ACCESS_INSTANCEDATA
	             : GEN6_VB0_ACCESS_VERTEXDATA;
	    dw0 |= i << GEN6_VB0_INDEX_SHIFT;
	 } else {
	    dw0 = buffer->step_rate
	             ? BRW_VB0_ACCESS_INSTANCEDATA
	             : BRW_VB0_ACCESS_VERTEXDATA;
	    dw0 |= i << BRW_VB0_INDEX_SHIFT;
	 }

	 if (intel->gen >= 7)
	    dw0 |= GEN7_VB0_ADDRESS_MODIFYENABLE;

	 OUT_BATCH(dw0 | (buffer->stride << BRW_VB0_PITCH_SHIFT));
	 OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->offset);
	 if (intel->gen >= 5) {
	    OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->bo->size - 1);
	 } else
	    OUT_BATCH(0);
	 OUT_BATCH(buffer->step_rate);

	 brw->vb.current_buffers[i].handle = buffer->bo->handle;
	 brw->vb.current_buffers[i].offset = buffer->offset;
	 brw->vb.current_buffers[i].stride = buffer->stride;
	 brw->vb.current_buffers[i].step_rate = buffer->step_rate;
      }
      brw->vb.nr_current_buffers = i;
      ADVANCE_BATCH();
   }

   nr_elements = brw->vb.nr_enabled + brw->vs.prog_data->uses_vertexid;

   /* The hardware allows one more VERTEX_ELEMENTS than VERTEX_BUFFERS, presumably
    * for VertexID/InstanceID.
    */
   if (intel->gen >= 6) {
      assert(nr_elements <= 34);
   } else {
      assert(nr_elements <= 18);
   }

   struct brw_vertex_element *gen6_edgeflag_input = NULL;

   BEGIN_BATCH(1 + nr_elements * 2);
   OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | (2 * nr_elements - 1));
   for (i = 0; i < brw->vb.nr_enabled; i++) {
      struct brw_vertex_element *input = brw->vb.enabled[i];
      uint32_t format = get_surface_type(input->glarray->Type,
					 input->glarray->Size,
					 input->glarray->Format,
					 input->glarray->Normalized,
                                         input->glarray->Integer);
      uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC;
      uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC;
      uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC;
      uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC;

      /* The gen4 driver expects edgeflag to come in as a float, and passes
       * that float on to the tests in the clipper.  Mesa's current vertex
       * attribute value for EdgeFlag is stored as a float, which works out.
       * glEdgeFlagPointer, on the other hand, gives us an unnormalized
       * integer ubyte.  Just rewrite that to convert to a float.
       */
      if (input->attrib == VERT_ATTRIB_EDGEFLAG) {
         /* Gen6+ passes edgeflag as sideband along with the vertex, instead
          * of in the VUE.  We have to upload it sideband as the last vertex
          * element according to the B-Spec.
          */
         if (intel->gen >= 6) {
            gen6_edgeflag_input = input;
            continue;
         }

         if (format == BRW_SURFACEFORMAT_R8_UINT)
            format = BRW_SURFACEFORMAT_R8_SSCALED;
      }

      switch (input->glarray->Size) {
      case 0: comp0 = BRW_VE1_COMPONENT_STORE_0;
      case 1: comp1 = BRW_VE1_COMPONENT_STORE_0;
      case 2: comp2 = BRW_VE1_COMPONENT_STORE_0;
      case 3: comp3 = input->glarray->Integer ? BRW_VE1_COMPONENT_STORE_1_INT
                                              : BRW_VE1_COMPONENT_STORE_1_FLT;
	 break;
      }

      if (intel->gen >= 6) {
	 OUT_BATCH((input->buffer << GEN6_VE0_INDEX_SHIFT) |
		   GEN6_VE0_VALID |
		   (format << BRW_VE0_FORMAT_SHIFT) |
		   (input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
      } else {
	 OUT_BATCH((input->buffer << BRW_VE0_INDEX_SHIFT) |
		   BRW_VE0_VALID |
		   (format << BRW_VE0_FORMAT_SHIFT) |
		   (input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
      }

      if (intel->gen >= 5)
          OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
                    (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
                    (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
                    (comp3 << BRW_VE1_COMPONENT_3_SHIFT));
      else
          OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
                    (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
                    (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
                    (comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
                    ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
   }

   if (intel->gen >= 6 && gen6_edgeflag_input) {
      uint32_t format = get_surface_type(gen6_edgeflag_input->glarray->Type,
                                         gen6_edgeflag_input->glarray->Size,
                                         gen6_edgeflag_input->glarray->Format,
                                         gen6_edgeflag_input->glarray->Normalized,
                                         gen6_edgeflag_input->glarray->Integer);

      OUT_BATCH((gen6_edgeflag_input->buffer << GEN6_VE0_INDEX_SHIFT) |
                GEN6_VE0_VALID |
                GEN6_VE0_EDGE_FLAG_ENABLE |
                (format << BRW_VE0_FORMAT_SHIFT) |
                (gen6_edgeflag_input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
      OUT_BATCH((BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) |
                (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
                (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
                (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));
   }

   if (brw->vs.prog_data->uses_vertexid) {
      uint32_t dw0 = 0, dw1 = 0;

      dw1 = ((BRW_VE1_COMPONENT_STORE_VID << BRW_VE1_COMPONENT_0_SHIFT) |
	     (BRW_VE1_COMPONENT_STORE_IID << BRW_VE1_COMPONENT_1_SHIFT) |
	     (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
	     (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));

      if (intel->gen >= 6) {
	 dw0 |= GEN6_VE0_VALID;
      } else {
	 dw0 |= BRW_VE0_VALID;
	 dw1 |= (i * 4) << BRW_VE1_DST_OFFSET_SHIFT;
      }

      /* Note that for gl_VertexID, gl_InstanceID, and gl_PrimitiveID values,
       * the format is ignored and the value is always int.
       */

      OUT_BATCH(dw0);
      OUT_BATCH(dw1);
   }

   CACHED_BATCH();
}
Example #8
0
/**
 * CopyPixels with the blitter.  Don't support zooming, pixel transfer, etc.
 */
static bool
do_blit_copypixels(struct gl_context * ctx,
                   GLint srcx, GLint srcy,
                   GLsizei width, GLsizei height,
                   GLint dstx, GLint dsty, GLenum type)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct gl_framebuffer *read_fb = ctx->ReadBuffer;
   GLint orig_dstx;
   GLint orig_dsty;
   GLint orig_srcx;
   GLint orig_srcy;
   bool flip = false;
   struct intel_renderbuffer *draw_irb = NULL;
   struct intel_renderbuffer *read_irb = NULL;
   gl_format read_format, draw_format;

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

   switch (type) {
   case GL_COLOR:
      if (fb->_NumColorDrawBuffers != 1) {
	 perf_debug("glCopyPixels() fallback: MRT\n");
	 return false;
      }

      draw_irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
      read_irb = intel_renderbuffer(read_fb->_ColorReadBuffer);
      break;
   case GL_DEPTH_STENCIL_EXT:
      draw_irb = intel_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
      read_irb =
	 intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer);
      break;
   case GL_DEPTH:
      perf_debug("glCopyPixels() fallback: GL_DEPTH\n");
      return false;
   case GL_STENCIL:
      perf_debug("glCopyPixels() fallback: GL_STENCIL\n");
      return false;
   default:
      perf_debug("glCopyPixels(): Unknown type\n");
      return false;
   }

   if (!draw_irb) {
      perf_debug("glCopyPixels() fallback: missing draw buffer\n");
      return false;
   }

   if (!read_irb) {
      perf_debug("glCopyPixels() fallback: missing read buffer\n");
      return false;
   }

   read_format = intel_rb_format(read_irb);
   draw_format = intel_rb_format(draw_irb);

   if (draw_format != read_format &&
       !(draw_format == MESA_FORMAT_XRGB8888 &&
	 read_format == MESA_FORMAT_ARGB8888)) {
      perf_debug("glCopyPixels() fallback: mismatched formats (%s -> %s\n",
                 _mesa_get_format_name(read_format),
                 _mesa_get_format_name(draw_format));
      return false;
   }

   /* Copypixels can be more than a straight copy.  Ensure all the
    * extra operations are disabled:
    */
   if (!intel_check_copypixel_blit_fragment_ops(ctx) ||
       ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
      return false;

   intel_prepare_render(intel);

   intel_flush(&intel->ctx);

   /* Clip to destination buffer. */
   orig_dstx = dstx;
   orig_dsty = dsty;
   if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
			     fb->_Xmax, fb->_Ymax,
			     &dstx, &dsty, &width, &height))
      goto out;
   /* Adjust src coords for our post-clipped destination origin */
   srcx += dstx - orig_dstx;
   srcy += dsty - orig_dsty;

   /* Clip to source buffer. */
   orig_srcx = srcx;
   orig_srcy = srcy;
   if (!_mesa_clip_to_region(0, 0,
			     read_fb->Width, read_fb->Height,
			     &srcx, &srcy, &width, &height))
      goto out;
   /* Adjust dst coords for our post-clipped source origin */
   dstx += srcx - orig_srcx;
   dsty += srcy - orig_srcy;

   /* Flip dest Y if it's a window system framebuffer. */
   if (_mesa_is_winsys_fbo(fb)) {
      /* copypixels to a window system framebuffer */
      dsty = fb->Height - dsty - height;
      flip = !flip;
   }

   /* Flip source Y if it's a window system framebuffer. */
   if (_mesa_is_winsys_fbo(read_fb)) {
      srcy = read_fb->Height - srcy - height;
      flip = !flip;
   }

   srcx += read_irb->draw_x;
   srcy += read_irb->draw_y;
   dstx += draw_irb->draw_x;
   dsty += draw_irb->draw_y;

   uint32_t src_pitch = read_irb->mt->region->pitch;
   if (flip)
      src_pitch = -src_pitch;

   if (!intelEmitCopyBlit(intel,
                          draw_irb->mt->cpp,
                          src_pitch, read_irb->mt->region->bo,
                          0, read_irb->mt->region->tiling,
                          draw_irb->mt->region->pitch, draw_irb->mt->region->bo,
                          0, draw_irb->mt->region->tiling,
                          srcx, srcy,
                          dstx, dsty,
                          width, height,
                          ctx->Color.ColorLogicOpEnabled ?
                          ctx->Color.LogicOp : GL_COPY)) {
      DBG("%s: blit failure\n", __FUNCTION__);
      return false;
   }

out:
   intel_check_front_buffer_rendering(intel);

   DBG("%s: success\n", __FUNCTION__);
   return true;
}
/* XXX: Do this for TexSubImage also:
 */
static bool
try_pbo_upload(struct gl_context *ctx,
               struct gl_texture_image *image,
               const struct gl_pixelstore_attrib *unpack,
	       GLenum format, GLenum type, const void *pixels)
{
   struct intel_texture_image *intelImage = intel_texture_image(image);
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset, src_stride;
   GLuint dst_x, dst_y, dst_stride;
   drm_intel_bo *dst_buffer, *src_buffer;

   if (!_mesa_is_bufferobj(unpack->BufferObj))
      return false;

   DBG("trying pbo upload\n");

   if (intel->ctx._ImageTransferState ||
       unpack->SkipPixels || unpack->SkipRows) {
      DBG("%s: image transfer\n", __FUNCTION__);
      return false;
   }

   if (!check_pbo_format(format, type, intelImage->base.Base.TexFormat)) {
      DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n",
	  __FUNCTION__, _mesa_get_format_name(intelImage->base.Base.TexFormat),
	  format, type);
      return false;
   }

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

   if (!intelImage->mt) {
      DBG("%s: no miptree\n", __FUNCTION__);
      return false;
   }

   dst_buffer = intelImage->mt->region->bo;
   src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset);
   /* note: potential 64-bit ptr to 32-bit int cast */
   src_offset += (GLuint) (unsigned long) pixels;

   if (unpack->RowLength > 0)
      src_stride = unpack->RowLength;
   else
      src_stride = image->Width;

   intel_miptree_get_image_offset(intelImage->mt, intelImage->base.Base.Level,
				  intelImage->base.Base.Face, 0,
				  &dst_x, &dst_y);

   dst_stride = intelImage->mt->region->pitch;

   if (!intelEmitCopyBlit(intel,
			  intelImage->mt->cpp,
			  src_stride, src_buffer,
			  src_offset, false,
			  dst_stride, dst_buffer, 0,
			  intelImage->mt->region->tiling,
			  0, 0, dst_x, dst_y, image->Width, image->Height,
			  GL_COPY)) {
      DBG("%s: blit failed\n", __FUNCTION__);
      return false;
   }

   DBG("%s: success\n", __FUNCTION__);
   return true;
}
Example #10
0
static void brw_prepare_vertices(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->intel.ctx;
   struct intel_context *intel = intel_context(ctx);
   /* CACHE_NEW_VS_PROG */
   GLbitfield64 vs_inputs = brw->vs.prog_data->inputs_read;
   const unsigned char *ptr = NULL;
   GLuint interleaved = 0, total_size = 0;
   unsigned int min_index = brw->vb.min_index;
   unsigned int max_index = brw->vb.max_index;
   int delta, i, j;
   GLboolean can_merge_uploads = GL_TRUE;

   struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
   GLuint nr_uploads = 0;

   /* _NEW_POLYGON
    *
    * On gen6+, edge flags don't end up in the VUE (either in or out of the
    * VS).  Instead, they're uploaded as the last vertex element, and the data
    * is passed sideband through the fixed function units.  So, we need to
    * prepare the vertex buffer for it, but it's not present in inputs_read.
    */
   if (intel->gen >= 6 && (ctx->Polygon.FrontMode != GL_FILL ||
                           ctx->Polygon.BackMode != GL_FILL)) {
      vs_inputs |= VERT_BIT_EDGEFLAG;
   }

   /* First build an array of pointers to ve's in vb.inputs_read
    */
   if (0)
      printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);

   /* Accumulate the list of enabled arrays. */
   brw->vb.nr_enabled = 0;
   while (vs_inputs) {
      GLuint i = ffsll(vs_inputs) - 1;
      struct brw_vertex_element *input = &brw->vb.inputs[i];

      vs_inputs &= ~BITFIELD64_BIT(i);
      if (input->glarray->Size && get_size(input->glarray->Type))
         brw->vb.enabled[brw->vb.nr_enabled++] = input;
   }

   if (brw->vb.nr_enabled == 0)
      return;

   if (brw->vb.nr_buffers)
      goto prepare;

   for (i = j = 0; i < brw->vb.nr_enabled; i++) {
      struct brw_vertex_element *input = brw->vb.enabled[i];
      const struct gl_client_array *glarray = input->glarray;
      int type_size = get_size(glarray->Type);

      input->element_size = type_size * glarray->Size;

      if (_mesa_is_bufferobj(glarray->BufferObj)) {
	 struct intel_buffer_object *intel_buffer =
	    intel_buffer_object(glarray->BufferObj);
	 int k;

	 for (k = 0; k < i; k++) {
	    const struct gl_client_array *other = brw->vb.enabled[k]->glarray;
	    if (glarray->BufferObj == other->BufferObj &&
		glarray->StrideB == other->StrideB &&
		glarray->InstanceDivisor == other->InstanceDivisor &&
		(uintptr_t)(glarray->Ptr - other->Ptr) < glarray->StrideB)
	    {
	       input->buffer = brw->vb.enabled[k]->buffer;
	       input->offset = glarray->Ptr - other->Ptr;
	       break;
	    }
	 }
	 if (k == i) {
	    struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];

	    /* Named buffer object: Just reference its contents directly. */
            buffer->bo = intel_bufferobj_source(intel,
                                                intel_buffer, type_size,
						&buffer->offset);
	    drm_intel_bo_reference(buffer->bo);
	    buffer->offset += (uintptr_t)glarray->Ptr;
	    buffer->stride = glarray->StrideB;
	    buffer->step_rate = glarray->InstanceDivisor;

	    input->buffer = j++;
	    input->offset = 0;
	 }

	 /* This is a common place to reach if the user mistakenly supplies
	  * a pointer in place of a VBO offset.  If we just let it go through,
	  * we may end up dereferencing a pointer beyond the bounds of the
	  * GTT.  We would hope that the VBO's max_index would save us, but
	  * Mesa appears to hand us min/max values not clipped to the
	  * array object's _MaxElement, and _MaxElement frequently appears
	  * to be wrong anyway.
	  *
	  * The VBO spec allows application termination in this case, and it's
	  * probably a service to the poor programmer to do so rather than
	  * trying to just not render.
	  */
	 assert(input->offset < brw->vb.buffers[input->buffer].bo->size);
      } else {
	 /* Queue the buffer object up to be uploaded in the next pass,
	  * when we've decided if we're doing interleaved or not.
	  */
	 if (nr_uploads == 0) {
	    interleaved = glarray->StrideB;
	    ptr = glarray->Ptr;
	 }
	 else if (interleaved != glarray->StrideB ||
		  (uintptr_t)(glarray->Ptr - ptr) > interleaved)
	 {
	    interleaved = 0;
	 }
	 else if ((uintptr_t)(glarray->Ptr - ptr) & (type_size -1))
	 {
	    /* enforce natural alignment (for doubles) */
	    interleaved = 0;
	 }

	 upload[nr_uploads++] = input;

	 total_size = ALIGN(total_size, type_size);
	 total_size += input->element_size;

         if (glarray->InstanceDivisor != 0) {
            can_merge_uploads = GL_FALSE;
         }
      }
   }

   /* If we need to upload all the arrays, then we can trim those arrays to
    * only the used elements [min_index, max_index] so long as we adjust all
    * the values used in the 3DPRIMITIVE i.e. by setting the vertex bias.
    */
   brw->vb.start_vertex_bias = 0;
   delta = min_index;
   if (nr_uploads == brw->vb.nr_enabled) {
      brw->vb.start_vertex_bias = -delta;
      delta = 0;
   }
   if (delta && !brw->intel.intelScreen->relaxed_relocations)
      min_index = delta = 0;

   /* Handle any arrays to be uploaded. */
   if (nr_uploads > 1) {
      if (interleaved && interleaved <= 2*total_size) {
	 struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
	 /* All uploads are interleaved, so upload the arrays together as
	  * interleaved.  First, upload the contents and set up upload[0].
	  */
	 copy_array_to_vbo_array(brw, upload[0], min_index, max_index,
				 buffer, interleaved);
	 buffer->offset -= delta * interleaved;

	 for (i = 0; i < nr_uploads; i++) {
	    /* Then, just point upload[i] at upload[0]'s buffer. */
	    upload[i]->offset =
	       ((const unsigned char *)upload[i]->glarray->Ptr - ptr);
	    upload[i]->buffer = j;
	 }
	 j++;

	 nr_uploads = 0;
      }
      else if ((total_size < 2048) && can_merge_uploads) {
	 /* Upload non-interleaved arrays into a single interleaved array */
	 struct brw_vertex_buffer *buffer;
	 int count = MAX2(max_index - min_index + 1, 1);
	 int offset;
	 char *map;

	 map = intel_upload_map(&brw->intel, total_size * count, total_size);
	 for (i = offset = 0; i < nr_uploads; i++) {
	    const unsigned char *src = upload[i]->glarray->Ptr;
	    int size = upload[i]->element_size;
	    int stride = upload[i]->glarray->StrideB;
	    char *dst;
	    int n;

	    offset = ALIGN(offset, get_size(upload[i]->glarray->Type));
	    dst = map + offset;
	    src += min_index * stride;

	    for (n = 0; n < count; n++) {
	       memcpy(dst, src, size);
	       src += stride;
	       dst += total_size;
	    }

	    upload[i]->offset = offset;
	    upload[i]->buffer = j;

	    offset += size;
	 }
	 assert(offset == total_size);
	 buffer = &brw->vb.buffers[j++];
	 intel_upload_unmap(&brw->intel, map, offset * count, offset,
			    &buffer->bo, &buffer->offset);
	 buffer->stride = offset;
	 buffer->step_rate = 0;
	 buffer->offset -= delta * offset;

	 nr_uploads = 0;
      }
   }
   /* Upload non-interleaved arrays */
   for (i = 0; i < nr_uploads; i++) {
      struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
      if (upload[i]->glarray->InstanceDivisor == 0) {
         copy_array_to_vbo_array(brw, upload[i], min_index, max_index,
                                 buffer, upload[i]->element_size);
      } else {
         /* This is an instanced attribute, since its InstanceDivisor
          * is not zero. Therefore, its data will be stepped after the
          * instanced draw has been run InstanceDivisor times.
          */
         uint32_t instanced_attr_max_index =
            (brw->num_instances - 1) / upload[i]->glarray->InstanceDivisor;
         copy_array_to_vbo_array(brw, upload[i], 0, instanced_attr_max_index,
                                 buffer, upload[i]->element_size);
      }
      buffer->offset -= delta * buffer->stride;
      buffer->step_rate = upload[i]->glarray->InstanceDivisor;
      upload[i]->buffer = j++;
      upload[i]->offset = 0;
   }

   /* can we simply extend the current vb? */
   if (j == brw->vb.nr_current_buffers) {
      int delta = 0;
      for (i = 0; i < j; i++) {
	 int d;

	 if (brw->vb.current_buffers[i].handle != brw->vb.buffers[i].bo->handle ||
	     brw->vb.current_buffers[i].stride != brw->vb.buffers[i].stride ||
	     brw->vb.current_buffers[i].step_rate != brw->vb.buffers[i].step_rate)
	    break;

	 d = brw->vb.buffers[i].offset - brw->vb.current_buffers[i].offset;
	 if (d < 0)
	    break;
	 if (i == 0)
	    delta = d / brw->vb.current_buffers[i].stride;
	 if (delta * brw->vb.current_buffers[i].stride != d)
	    break;
      }

      if (i == j) {
	 brw->vb.start_vertex_bias += delta;
	 while (--j >= 0)
	    drm_intel_bo_unreference(brw->vb.buffers[j].bo);
	 j = 0;
      }
   }

   brw->vb.nr_buffers = j;

prepare:
   brw_prepare_query_begin(brw);
}
Example #11
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;
}
Example #12
0
static GLboolean
do_texture_drawpixels(GLcontext * ctx,
                      GLint x, GLint y,
                      GLsizei width, GLsizei height,
                      GLenum format, GLenum type,
                      const struct gl_pixelstore_attrib *unpack,
                      const GLvoid * pixels)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_region *dst = intel_drawbuf_region(intel);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
   GLuint src_offset;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      fprintf(stderr, "%s\n", __FUNCTION__);

   intelFlush(&intel->ctx);
   intel->vtbl.render_start(intel);
   intel->vtbl.emit_state(intel);

   if (!dst)
      return GL_FALSE;

   if (src) {
      if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
                                     format, type, pixels)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
         return GL_TRUE;
      }
   }
   else {
      /* PBO only for now:
       */
/*       _mesa_printf("%s - not PBO\n", __FUNCTION__); */
      return GL_FALSE;
   }

   /* There are a couple of things we can't do yet, one of which is
    * set the correct state for pixel operations when GL texturing is
    * enabled.  That's a pretty rare state and probably not worth the
    * effort.  A completely device-independent version of this may do
    * more.
    *
    * Similarly, we make no attempt to merge metaops processing with
    * an enabled fragment program, though it would certainly be
    * possible.
    */
   if (!intel_check_meta_tex_fragment_ops(ctx)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad GL fragment state for metaops texture\n",
                      __FUNCTION__);
      return GL_FALSE;
   }

   intel->vtbl.install_meta_state(intel);


   /* Is this true?  Also will need to turn depth testing on according
    * to state:
    */
   intel->vtbl.meta_no_stencil_write(intel);
   intel->vtbl.meta_no_depth_write(intel);

   /* Set the 3d engine to draw into the destination region:
    */
   intel->vtbl.meta_draw_region(intel, dst, intel->intelScreen->depth_region);

   intel->vtbl.meta_import_pixel_state(intel);

   src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
                                             format, type, 0, 0, 0);


   /* Setup the pbo up as a rectangular texture, if possible.
    *
    * TODO: This is almost always possible if the i915 fragment
    * program is adjusted to correctly swizzle the sampled colors.
    * The major exception is any 24bit texture, like RGB888, for which
    * there is no hardware support.  
    */
   if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, src_offset,
                                         rowLength, height, format, type)) {
      intel->vtbl.leave_meta_state(intel);
      return GL_FALSE;
   }

   intel->vtbl.meta_texture_blend_replace(intel);


   LOCK_HARDWARE(intel);

   if (intel->driDrawable->numClipRects) {
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
      GLint srcx, srcy;
      GLint dstx, dsty;

      dstx = x;
      dsty = dPriv->h - (y + height);

      srcx = 0;                 /* skiprows/pixels already done */
      srcy = 0;

      if (0) {
         const GLint orig_x = dstx;
         const GLint orig_y = dsty;

         if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
                                   &dstx, &dsty, &width, &height))
            goto out;

         srcx += dstx - orig_x;
         srcy += dsty - orig_y;
      }


      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("draw %d,%d %dx%d\n", dstx, dsty, width, height);

      /* Must use the regular cliprect mechanism in order to get the
       * drawing origin set correctly.  Otherwise scissor state is in
       * incorrect coordinate space.  Does this even need to hold the
       * lock???
       */
      intel_meta_draw_quad(intel,
                           dstx, dstx + width * ctx->Pixel.ZoomX,
                           dPriv->h - (y + height * ctx->Pixel.ZoomY),
                           dPriv->h - (y),
                           -ctx->Current.RasterPos[2] * .5,
                           0x00ff00ff,
                           srcx, srcx + width, srcy + height, srcy);
    out:
      intel->vtbl.leave_meta_state(intel);
      intel_batchbuffer_flush(intel->batch);
   }
   UNLOCK_HARDWARE(intel);
   return GL_TRUE;
}
Example #13
0
/* Pros:  
 *   - no waiting for idle before updating framebuffer.
 *   
 * Cons:
 *   - if upload is by memcpy, this may actually be slower than fallback path.
 *   - uploads the whole image even if destination is clipped
 *   
 * Need to benchmark.
 *
 * Given the questions about performance, implement for pbo's only.
 * This path is definitely a win if the pbo is already in agp.  If it
 * turns out otherwise, we can add the code necessary to upload client
 * data to agp space before performing the blit.  (Though it may turn
 * out to be better/simpler just to use the texture engine).
 */
static GLboolean
do_blit_drawpixels(GLcontext * ctx,
                   GLint x, GLint y,
                   GLsizei width, GLsizei height,
                   GLenum format, GLenum type,
                   const struct gl_pixelstore_attrib *unpack,
                   const GLvoid * pixels)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_region *dest = intel_drawbuf_region(intel);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset;
   GLuint rowLength;
   struct _DriFenceObject *fence = NULL;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      _mesa_printf("%s\n", __FUNCTION__);


   if (!dest) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - no dest\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (src) {
      /* This validation should be done by core mesa:
       */
      if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
                                     format, type, pixels)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
         return GL_TRUE;
      }
   }
   else {
      /* PBO only for now:
       */
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - not PBO\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (!intel_check_blit_format(dest, format, type)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (!intel_check_blit_fragment_ops(ctx)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad GL fragment state for blitter\n",
                      __FUNCTION__);
      return GL_FALSE;
   }

   if (ctx->Pixel.ZoomX != 1.0F) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
      return GL_FALSE;
   }


   if (unpack->RowLength > 0)
      rowLength = unpack->RowLength;
   else
      rowLength = width;

   if (ctx->Pixel.ZoomY == -1.0F) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
      return GL_FALSE;          /* later */
      y -= height;
   }
   else if (ctx->Pixel.ZoomY == 1.0F) {
      rowLength = -rowLength;
   }
   else {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
      return GL_FALSE;
   }

   src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
                                             format, type, 0, 0, 0);

   intelFlush(&intel->ctx);
   LOCK_HARDWARE(intel);

   if (intel->driDrawable->numClipRects) {
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
      int nbox = dPriv->numClipRects;
      drm_clip_rect_t *box = dPriv->pClipRects;
      drm_clip_rect_t rect;
      drm_clip_rect_t dest_rect;
      struct _DriBufferObject *src_buffer =
         intel_bufferobj_buffer(intel, src, INTEL_READ);
      int i;

      dest_rect.x1 = dPriv->x + x;
      dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
      dest_rect.x2 = dest_rect.x1 + width;
      dest_rect.y2 = dest_rect.y1 + height;

      for (i = 0; i < nbox; i++) {
         if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
            continue;

         intelEmitCopyBlit(intel,
                           dest->cpp,
                           rowLength,
                           src_buffer, src_offset,
                           dest->pitch,
                           dest->buffer, 0,
                           rect.x1 - dest_rect.x1,
                           rect.y2 - dest_rect.y2,
                           rect.x1,
                           rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1,
			   ctx->Color.ColorLogicOpEnabled ?
			   ctx->Color.LogicOp : GL_COPY);
      }
      fence = intel_batchbuffer_flush(intel->batch);
      driFenceReference(fence);
   }
   UNLOCK_HARDWARE(intel);

   if (fence) {
      driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE);
      driFenceUnReference(fence);
   }

   if (INTEL_DEBUG & DEBUG_PIXEL)
      _mesa_printf("%s - DONE\n", __FUNCTION__);

   return GL_TRUE;
}
Example #14
0
void
intelChooseRenderState(GLcontext * ctx)
{
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct intel_context *intel = intel_context(ctx);
   GLuint flags = ctx->_TriangleCaps;
   const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
   GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
   GLuint index = 0;

   if (INTEL_DEBUG & DEBUG_STATE)
      fprintf(stderr, "\n%s\n", __FUNCTION__);

   if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) {

      if (flags & ANY_RASTER_FLAGS) {
         if (flags & DD_TRI_LIGHT_TWOSIDE)
            index |= INTEL_TWOSIDE_BIT;
         if (flags & DD_TRI_OFFSET)
            index |= INTEL_OFFSET_BIT;
         if (flags & DD_TRI_UNFILLED)
            index |= INTEL_UNFILLED_BIT;
      }

      if (have_wpos) {
         intel->draw_point = intel_wpos_point;
         intel->draw_line = intel_wpos_line;
         intel->draw_tri = intel_wpos_triangle;

         /* Make sure these get called:
          */
         index |= INTEL_FALLBACK_BIT;
      }
      else {
         intel->draw_point = intel_draw_point;
         intel->draw_line = intel_draw_line;
         intel->draw_tri = intel_draw_triangle;
      }

      /* Hook in fallbacks for specific primitives.
       */
      if (flags & ANY_FALLBACK_FLAGS) {
         if (flags & DD_LINE_STIPPLE)
            intel->draw_line = intel_fallback_line;

         if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
            intel->draw_tri = intel_fallback_tri;

         if (flags & DD_TRI_SMOOTH) {
	    if (intel->strict_conformance)
	       intel->draw_tri = intel_fallback_tri;
	 }

         if (flags & DD_POINT_ATTEN) {
	    if (0)
	       intel->draw_point = intel_atten_point;
	    else
	       intel->draw_point = intel_fallback_point;
	 }

	 if (flags & DD_POINT_SMOOTH) {
	    if (intel->strict_conformance)
	       intel->draw_point = intel_fallback_point;
	 }

         index |= INTEL_FALLBACK_BIT;
      }
   }

   if (intel->RenderIndex != index) {
      intel->RenderIndex = index;

      tnl->Driver.Render.Points = rast_tab[index].points;
      tnl->Driver.Render.Line = rast_tab[index].line;
      tnl->Driver.Render.Triangle = rast_tab[index].triangle;
      tnl->Driver.Render.Quad = rast_tab[index].quad;

      if (index == 0) {
         tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts;
         tnl->Driver.Render.PrimTabElts = intel_render_tab_elts;
         tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
         tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly;
      }
      else {
         tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
         tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
         tnl->Driver.Render.ClippedLine = intelRenderClippedLine;
         tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly;
      }
   }
}
Example #15
0
/**
 * Use blitting to clear the renderbuffers named by 'flags'.
 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
 * since that might include software renderbuffers or renderbuffers
 * which we're clearing with triangles.
 * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear
 */
GLbitfield
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
{
    struct intel_context *intel = intel_context(ctx);
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    GLuint clear_depth_value, clear_depth_mask;
    GLboolean all;
    GLint cx, cy, cw, ch;
    GLbitfield fail_mask = 0;
    BATCH_LOCALS;

    /*
     * Compute values for clearing the buffers.
     */
    clear_depth_value = 0;
    clear_depth_mask = 0;
    if (mask & BUFFER_BIT_DEPTH) {
        clear_depth_value = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
        clear_depth_mask = XY_BLT_WRITE_RGB;
    }
    if (mask & BUFFER_BIT_STENCIL) {
        clear_depth_value |= (ctx->Stencil.Clear & 0xff) << 24;
        clear_depth_mask |= XY_BLT_WRITE_ALPHA;
    }

    cx = fb->_Xmin;
    if (fb->Name == 0)
        cy = ctx->DrawBuffer->Height - fb->_Ymax;
    else
        cy = fb->_Ymin;
    cw = fb->_Xmax - fb->_Xmin;
    ch = fb->_Ymax - fb->_Ymin;

    if (cw == 0 || ch == 0)
        return 0;

    all = (cw == fb->Width && ch == fb->Height);

    /* Loop over all renderbuffers */
    mask &= (1 << BUFFER_COUNT) - 1;
    while (mask) {
        GLuint buf = _mesa_ffs(mask) - 1;
        GLboolean is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL;
        struct intel_renderbuffer *irb;
        drm_intel_bo *write_buffer;
        int x1, y1, x2, y2;
        uint32_t clear_val;
        uint32_t BR13, CMD;
        int pitch, cpp;
        drm_intel_bo *aper_array[2];

        mask &= ~(1 << buf);

        irb = intel_get_renderbuffer(fb, buf);
        if (irb == NULL || irb->region == NULL || irb->region->buffer == NULL) {
            fail_mask |= 1 << buf;
            continue;
        }

        /* OK, clear this renderbuffer */
        write_buffer = intel_region_buffer(intel, irb->region,
                                           all ? INTEL_WRITE_FULL :
                                           INTEL_WRITE_PART);
        x1 = cx + irb->draw_x;
        y1 = cy + irb->draw_y;
        x2 = cx + cw + irb->draw_x;
        y2 = cy + ch + irb->draw_y;

        pitch = irb->region->pitch;
        cpp = irb->region->cpp;

        DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
            __FUNCTION__,
            irb->region->buffer, (pitch * cpp),
            x1, y1, x2 - x1, y2 - y1);

        BR13 = 0xf0 << 16;
        CMD = XY_COLOR_BLT_CMD;

        /* Setup the blit command */
        if (cpp == 4) {
            if (is_depth_stencil) {
                CMD |= clear_depth_mask;
            } else {
                /* clearing RGBA */
                CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
            }
        }

        assert(irb->region->tiling != I915_TILING_Y);

#ifndef I915
        if (irb->region->tiling != I915_TILING_NONE) {
            CMD |= XY_DST_TILED;
            pitch /= 4;
        }
#endif
        BR13 |= (pitch * cpp);

        if (is_depth_stencil) {
            clear_val = clear_depth_value;
        } else {
            uint8_t clear[4];
            GLclampf *color = ctx->Color.ClearColor;

            CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
            CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
            CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
            CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);

            switch (irb->Base.Format) {
            case MESA_FORMAT_ARGB8888:
            case MESA_FORMAT_XRGB8888:
                clear_val = PACK_COLOR_8888(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_RGB565:
                clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]);
                break;
            case MESA_FORMAT_ARGB4444:
                clear_val = PACK_COLOR_4444(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_ARGB1555:
                clear_val = PACK_COLOR_1555(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_A8:
                clear_val = PACK_COLOR_8888(clear[3], clear[3],
                                            clear[3], clear[3]);
                break;
            default:
                fail_mask |= 1 << buf;
                continue;
            }
        }

        BR13 |= br13_for_cpp(cpp);

        assert(x1 < x2);
        assert(y1 < y2);

        /* do space check before going any further */
        aper_array[0] = intel->batch.bo;
        aper_array[1] = write_buffer;

        if (drm_intel_bufmgr_check_aperture_space(aper_array,
                ARRAY_SIZE(aper_array)) != 0) {
            intel_batchbuffer_flush(intel);
        }

        BEGIN_BATCH_BLT(6);
        OUT_BATCH(CMD);
        OUT_BATCH(BR13);
        OUT_BATCH((y1 << 16) | x1);
        OUT_BATCH((y2 << 16) | x2);
        OUT_RELOC_FENCED(write_buffer,
                         I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                         0);
        OUT_BATCH(clear_val);
        ADVANCE_BATCH();

        if (intel->always_flush_cache)
            intel_batchbuffer_emit_mi_flush(intel);

        if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
            mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
    }

    return fail_mask;
}
Example #16
0
void intelClearWithBlit(GLcontext *ctx, GLbitfield flags)
{
    struct intel_context *intel = intel_context( ctx );
    intelScreenPrivate *intelScreen = intel->intelScreen;
    GLuint clear_depth, clear_color;
    GLint cx, cy, cw, ch;
    GLint cpp = intelScreen->cpp;
    GLboolean all;
    GLint i;
    struct intel_region *front = intel->front_region;
    struct intel_region *back = intel->back_region;
    struct intel_region *depth = intel->depth_region;
    GLuint BR13, FRONT_CMD, BACK_CMD, DEPTH_CMD;
    GLuint front_pitch;
    GLuint back_pitch;
    GLuint depth_pitch;
    BATCH_LOCALS;


    clear_color = intel->ClearColor;
    clear_depth = 0;

    if (flags & BUFFER_BIT_DEPTH) {
        clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
    }

    if (flags & BUFFER_BIT_STENCIL) {
        clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
    }

    switch(cpp) {
    case 2:
        BR13 = (0xF0 << 16) | (1<<24);
        BACK_CMD  = FRONT_CMD = XY_COLOR_BLT_CMD;
        DEPTH_CMD = XY_COLOR_BLT_CMD;
        break;
    case 4:
        BR13 = (0xF0 << 16) | (1<<24) | (1<<25);
        BACK_CMD = FRONT_CMD = (XY_COLOR_BLT_CMD |
                                XY_COLOR_BLT_WRITE_ALPHA |
                                XY_COLOR_BLT_WRITE_RGB);
        DEPTH_CMD = XY_COLOR_BLT_CMD;
        if (flags & BUFFER_BIT_DEPTH) DEPTH_CMD |= XY_COLOR_BLT_WRITE_RGB;
        if (flags & BUFFER_BIT_STENCIL) DEPTH_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
        break;
    default:
        return;
    }



    intelFlush( &intel->ctx );
    LOCK_HARDWARE( intel );
    {
        /* get clear bounds after locking */
        cx = ctx->DrawBuffer->_Xmin;
        cy = ctx->DrawBuffer->_Ymin;
        ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
        cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
        all = (cw == ctx->DrawBuffer->Width && ch == ctx->DrawBuffer->Height);

        /* flip top to bottom */
        cy = intel->driDrawable->h - cy - ch;
        cx = cx + intel->drawX;
        cy += intel->drawY;

        /* adjust for page flipping */
        if ( intel->sarea->pf_current_page == 0 ) {
            front = intel->front_region;
            back = intel->back_region;
        }
        else {
            back = intel->front_region;
            front = intel->back_region;
        }

        front_pitch = front->pitch * front->cpp;
        back_pitch = back->pitch * back->cpp;
        depth_pitch = depth->pitch * depth->cpp;

        if (front->tiled) {
            FRONT_CMD |= XY_DST_TILED;
            front_pitch /= 4;
        }

        if (back->tiled) {
            BACK_CMD |= XY_DST_TILED;
            back_pitch /= 4;
        }

        if (depth->tiled) {
            DEPTH_CMD |= XY_DST_TILED;
            depth_pitch /= 4;
        }

        for (i = 0 ; i < intel->numClipRects ; i++)
        {
            drm_clip_rect_t *box = &intel->pClipRects[i];
            drm_clip_rect_t b;

            if (!all) {
                GLint x = box->x1;
                GLint y = box->y1;
                GLint w = box->x2 - x;
                GLint h = box->y2 - y;

                if (x < cx) w -= cx - x, x = cx;
                if (y < cy) h -= cy - y, y = cy;
                if (x + w > cx + cw) w = cx + cw - x;
                if (y + h > cy + ch) h = cy + ch - y;
                if (w <= 0) continue;
                if (h <= 0) continue;

                b.x1 = x;
                b.y1 = y;
                b.x2 = x + w;
                b.y2 = y + h;
            } else {
                b = *box;
            }


            if (b.x1 > b.x2 ||
                    b.y1 > b.y2 ||
                    b.x2 > intelScreen->width ||
                    b.y2 > intelScreen->height)
                continue;

            if ( flags & BUFFER_BIT_FRONT_LEFT ) {
                BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
                OUT_BATCH( FRONT_CMD );
                OUT_BATCH( front_pitch | BR13 );
                OUT_BATCH( (b.y1 << 16) | b.x1 );
                OUT_BATCH( (b.y2 << 16) | b.x2 );
                OUT_BATCH( bmBufferOffset(intel, front->buffer) );
                OUT_BATCH( clear_color );
                ADVANCE_BATCH();
            }

            if ( flags & BUFFER_BIT_BACK_LEFT ) {
                BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
                OUT_BATCH( BACK_CMD );
                OUT_BATCH( back_pitch | BR13 );
                OUT_BATCH( (b.y1 << 16) | b.x1 );
                OUT_BATCH( (b.y2 << 16) | b.x2 );
                OUT_BATCH( bmBufferOffset(intel, back->buffer) );
                OUT_BATCH( clear_color );
                ADVANCE_BATCH();
            }

            if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
                BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
                OUT_BATCH( DEPTH_CMD );
                OUT_BATCH( depth_pitch | BR13 );
                OUT_BATCH( (b.y1 << 16) | b.x1 );
                OUT_BATCH( (b.y2 << 16) | b.x2 );
                OUT_BATCH( bmBufferOffset(intel, depth->buffer) );
                OUT_BATCH( clear_depth );
                ADVANCE_BATCH();
            }
        }
    }
    intel_batchbuffer_flush( intel->batch );
    UNLOCK_HARDWARE( intel );
}
Example #17
0
/**
 * Used to initialize the alpha value of an ARGB8888 teximage after
 * loading it from an XRGB8888 source.
 *
 * This is very common with glCopyTexImage2D().
 */
void
intel_set_teximage_alpha_to_one(struct gl_context *ctx,
                                struct intel_texture_image *intel_image)
{
    struct intel_context *intel = intel_context(ctx);
    unsigned int image_x, image_y;
    uint32_t x1, y1, x2, y2;
    uint32_t BR13, CMD;
    int pitch, cpp;
    drm_intel_bo *aper_array[2];
    struct intel_region *region = intel_image->mt->region;
    BATCH_LOCALS;

    assert(intel_image->base.TexFormat == MESA_FORMAT_ARGB8888);

    /* get dest x/y in destination texture */
    intel_miptree_get_image_offset(intel_image->mt,
                                   intel_image->level,
                                   intel_image->face,
                                   0,
                                   &image_x, &image_y);

    x1 = image_x;
    y1 = image_y;
    x2 = image_x + intel_image->base.Width;
    y2 = image_y + intel_image->base.Height;

    pitch = region->pitch;
    cpp = region->cpp;

    DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
        __FUNCTION__,
        intel_image->mt->region->buffer, (pitch * cpp),
        x1, y1, x2 - x1, y2 - y1);

    BR13 = br13_for_cpp(cpp) | 0xf0 << 16;
    CMD = XY_COLOR_BLT_CMD;
    CMD |= XY_BLT_WRITE_ALPHA;

    assert(region->tiling != I915_TILING_Y);

#ifndef I915
    if (region->tiling != I915_TILING_NONE) {
        CMD |= XY_DST_TILED;
        pitch /= 4;
    }
#endif
    BR13 |= (pitch * cpp);

    /* do space check before going any further */
    aper_array[0] = intel->batch.bo;
    aper_array[1] = region->buffer;

    if (drm_intel_bufmgr_check_aperture_space(aper_array,
            ARRAY_SIZE(aper_array)) != 0) {
        intel_batchbuffer_flush(intel);
    }

    BEGIN_BATCH_BLT(6);
    OUT_BATCH(CMD);
    OUT_BATCH(BR13);
    OUT_BATCH((y1 << 16) | x1);
    OUT_BATCH((y2 << 16) | x2);
    OUT_RELOC_FENCED(region->buffer,
                     I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                     0);
    OUT_BATCH(0xffffffff); /* white, but only alpha gets written */
    ADVANCE_BATCH();

    intel_batchbuffer_emit_mi_flush(intel);
}
Example #18
0
/**
 * Initializes potential list of extensions if ctx == NULL, or actually enables
 * extensions for a context.
 */
void
intelInitExtensions(struct gl_context *ctx)
{
   struct intel_context *intel = intel_context(ctx);

   assert(intel->gen == 2 || intel->gen == 3);

   ctx->Extensions.ARB_draw_elements_base_vertex = true;
   ctx->Extensions.ARB_explicit_attrib_location = true;
   ctx->Extensions.ARB_explicit_uniform_location = true;
   ctx->Extensions.ARB_framebuffer_object = true;
   ctx->Extensions.ARB_internalformat_query = true;
   ctx->Extensions.ARB_map_buffer_range = true;
   ctx->Extensions.ARB_point_sprite = true;
   ctx->Extensions.ARB_sync = true;
   ctx->Extensions.ARB_texture_border_clamp = true;
   ctx->Extensions.ARB_texture_cube_map = true;
   ctx->Extensions.ARB_texture_env_combine = true;
   ctx->Extensions.ARB_texture_env_crossbar = true;
   ctx->Extensions.ARB_texture_env_dot3 = true;
   ctx->Extensions.ARB_vertex_program = true;
   ctx->Extensions.ARB_vertex_shader = true;
   ctx->Extensions.EXT_blend_color = true;
   ctx->Extensions.EXT_blend_equation_separate = true;
   ctx->Extensions.EXT_blend_func_separate = true;
   ctx->Extensions.EXT_blend_minmax = true;
   ctx->Extensions.EXT_gpu_program_parameters = true;
   ctx->Extensions.EXT_pixel_buffer_object = true;
   ctx->Extensions.EXT_point_parameters = true;
   ctx->Extensions.EXT_provoking_vertex = true;
   ctx->Extensions.EXT_texture_env_dot3 = true;
   ctx->Extensions.EXT_texture_filter_anisotropic = true;
   ctx->Extensions.APPLE_object_purgeable = true;
   ctx->Extensions.MESA_pack_invert = true;
   ctx->Extensions.MESA_ycbcr_texture = true;
   ctx->Extensions.NV_texture_rectangle = true;
   ctx->Extensions.TDFX_texture_compression_FXT1 = true;
   ctx->Extensions.OES_EGL_image = true;
   ctx->Extensions.OES_draw_texture = true;

   ctx->Const.GLSLVersion = 120;
   _mesa_override_glsl_version(&ctx->Const);

   if (intel->gen >= 3) {
      ctx->Extensions.ARB_ES2_compatibility = true;
      ctx->Extensions.ARB_depth_texture = true;
      ctx->Extensions.ARB_fragment_program = true;
      ctx->Extensions.ARB_shadow = true;
      ctx->Extensions.ARB_texture_non_power_of_two = true;
      ctx->Extensions.EXT_texture_sRGB = true;
      ctx->Extensions.EXT_texture_sRGB_decode = true;
      ctx->Extensions.EXT_stencil_two_side = true;
      ctx->Extensions.ATI_separate_stencil = true;
      ctx->Extensions.ATI_texture_env_combine3 = true;
      ctx->Extensions.NV_texture_env_combine4 = true;
      ctx->Extensions.ARB_fragment_shader = true;
      ctx->Extensions.ARB_occlusion_query = true;
   }

   if (intel->ctx.Mesa_DXTn
       || driQueryOptionb(&intel->optionCache, "force_s3tc_enable"))
      ctx->Extensions.EXT_texture_compression_s3tc = true;

   ctx->Extensions.ANGLE_texture_compression_dxt = true;
}
Example #19
0
/**
 * Use blitting to clear the renderbuffers named by 'flags'.
 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
 * since that might include software renderbuffers or renderbuffers
 * which we're clearing with triangles.
 * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear
 */
GLbitfield
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLuint clear_depth_value, clear_depth_mask;
   GLint cx, cy, cw, ch;
   GLbitfield fail_mask = 0;
   BATCH_LOCALS;

   /* Note: we don't use this function on Gen7+ hardware, so we can safely
    * ignore fast color clear issues.
    */
   assert(intel->gen < 7);

   /*
    * Compute values for clearing the buffers.
    */
   clear_depth_value = 0;
   clear_depth_mask = 0;
   if (mask & BUFFER_BIT_DEPTH) {
      clear_depth_value = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
      clear_depth_mask = XY_BLT_WRITE_RGB;
   }
   if (mask & BUFFER_BIT_STENCIL) {
      clear_depth_value |= (ctx->Stencil.Clear & 0xff) << 24;
      clear_depth_mask |= XY_BLT_WRITE_ALPHA;
   }

   cx = fb->_Xmin;
   if (_mesa_is_winsys_fbo(fb))
      cy = ctx->DrawBuffer->Height - fb->_Ymax;
   else
      cy = fb->_Ymin;
   cw = fb->_Xmax - fb->_Xmin;
   ch = fb->_Ymax - fb->_Ymin;

   if (cw == 0 || ch == 0)
      return 0;

   /* Loop over all renderbuffers */
   mask &= (1 << BUFFER_COUNT) - 1;
   while (mask) {
      GLuint buf = ffs(mask) - 1;
      bool is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL;
      struct intel_renderbuffer *irb;
      int x1, y1, x2, y2;
      uint32_t clear_val;
      uint32_t BR13, CMD;
      struct intel_region *region;
      int pitch, cpp;
      drm_intel_bo *aper_array[2];

      mask &= ~(1 << buf);

      irb = intel_get_renderbuffer(fb, buf);
      if (irb && irb->mt) {
	 region = irb->mt->region;
	 assert(region);
	 assert(region->bo);
      } else {
         fail_mask |= 1 << buf;
         continue;
      }

      /* OK, clear this renderbuffer */
      x1 = cx + irb->draw_x;
      y1 = cy + irb->draw_y;
      x2 = cx + cw + irb->draw_x;
      y2 = cy + ch + irb->draw_y;

      pitch = region->pitch;
      cpp = region->cpp;

      DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
	  __func__,
	  region->bo, pitch,
	  x1, y1, x2 - x1, y2 - y1);

      BR13 = 0xf0 << 16;
      CMD = XY_COLOR_BLT_CMD;

      /* Setup the blit command */
      if (cpp == 4) {
	 if (is_depth_stencil) {
	    CMD |= clear_depth_mask;
	 } else {
	    /* clearing RGBA */
	    CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
	 }
      }

      assert(region->tiling != I915_TILING_Y);

      BR13 |= pitch;

      if (is_depth_stencil) {
	 clear_val = clear_depth_value;
      } else {
	 uint8_t clear[4];
	 GLfloat *color = ctx->Color.ClearColor.f;

	 _mesa_unclamped_float_rgba_to_ubyte(clear, color);

	 switch (intel_rb_format(irb)) {
	 case MESA_FORMAT_B8G8R8A8_UNORM:
	 case MESA_FORMAT_B8G8R8X8_UNORM:
	    clear_val = PACK_COLOR_8888(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_B5G6R5_UNORM:
	    clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_B4G4R4A4_UNORM:
	    clear_val = PACK_COLOR_4444(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_B5G5R5A1_UNORM:
	    clear_val = PACK_COLOR_1555(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_A_UNORM8:
	    clear_val = PACK_COLOR_8888(clear[3], clear[3],
					clear[3], clear[3]);
	    break;
	 default:
	    fail_mask |= 1 << buf;
	    continue;
	 }
      }

      BR13 |= br13_for_cpp(cpp);

      assert(x1 < x2);
      assert(y1 < y2);

      /* do space check before going any further */
      aper_array[0] = intel->batch.bo;
      aper_array[1] = region->bo;

      if (drm_intel_bufmgr_check_aperture_space(aper_array,
						ARRAY_SIZE(aper_array)) != 0) {
	 intel_batchbuffer_flush(intel);
      }

      BEGIN_BATCH(6);
      OUT_BATCH(CMD | (6 - 2));
      OUT_BATCH(BR13);
      OUT_BATCH((y1 << 16) | x1);
      OUT_BATCH((y2 << 16) | x2);
      OUT_RELOC_FENCED(region->bo,
		       I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
		       0);
      OUT_BATCH(clear_val);
      ADVANCE_BATCH();

      if (intel->always_flush_cache)
	 intel_batchbuffer_emit_mi_flush(intel);

      if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
	 mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
   }

   return fail_mask;
}
/**
 * Called via glRenderbufferStorageEXT() to set the format and allocate
 * storage for a user-created renderbuffer.
 */
static GLboolean
intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
                                 GLenum internalFormat,
                                 GLuint width, GLuint height)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   GLboolean softwareBuffer = GL_FALSE;
   int cpp;

   ASSERT(rb->Name != 0);

   switch (internalFormat) {
   case GL_R3_G3_B2:
   case GL_RGB4:
   case GL_RGB5:
      rb->_ActualFormat = GL_RGB5;
      rb->DataType = GL_UNSIGNED_BYTE;
      rb->RedBits = 5;
      rb->GreenBits = 6;
      rb->BlueBits = 5;
      cpp = 2;
      break;
   case GL_RGB:
   case GL_RGB8:
   case GL_RGB10:
   case GL_RGB12:
   case GL_RGB16:
   case GL_RGBA:
   case GL_RGBA2:
   case GL_RGBA4:
   case GL_RGB5_A1:
   case GL_RGBA8:
   case GL_RGB10_A2:
   case GL_RGBA12:
   case GL_RGBA16:
      rb->_ActualFormat = GL_RGBA8;
      rb->DataType = GL_UNSIGNED_BYTE;
      rb->RedBits = 8;
      rb->GreenBits = 8;
      rb->BlueBits = 8;
      rb->AlphaBits = 8;
      cpp = 4;
      break;
   case GL_STENCIL_INDEX:
   case GL_STENCIL_INDEX1_EXT:
   case GL_STENCIL_INDEX4_EXT:
   case GL_STENCIL_INDEX8_EXT:
   case GL_STENCIL_INDEX16_EXT:
      /* alloc a depth+stencil buffer */
      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
      rb->StencilBits = 8;
      cpp = 4;
      break;
   case GL_DEPTH_COMPONENT16:
      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
      rb->DataType = GL_UNSIGNED_SHORT;
      rb->DepthBits = 16;
      cpp = 2;
      break;
   case GL_DEPTH_COMPONENT:
   case GL_DEPTH_COMPONENT24:
   case GL_DEPTH_COMPONENT32:
      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
      rb->DepthBits = 24;
      cpp = 4;
      break;
   case GL_DEPTH_STENCIL_EXT:
   case GL_DEPTH24_STENCIL8_EXT:
      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
      rb->DepthBits = 24;
      rb->StencilBits = 8;
      cpp = 4;
      break;
   default:
      _mesa_problem(ctx,
                    "Unexpected format in intel_alloc_renderbuffer_storage");
      return GL_FALSE;
   }

   intelFlush(ctx);

   /* free old region */
   if (irb->region) {
      intel_region_release(&irb->region);
   }

   /* allocate new memory region/renderbuffer */
   if (softwareBuffer) {
      return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
                                             width, height);
   }
   else {
      /* Choose a pitch to match hardware requirements:
       */
      GLuint pitch = ((cpp * width + 63) & ~63) / cpp;

      /* alloc hardware renderbuffer */
      DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
	  height, pitch);

      irb->region = intel_region_alloc(intel, cpp, pitch, height);
      if (!irb->region)
         return GL_FALSE;       /* out of memory? */

      ASSERT(irb->region->buffer);

      rb->Width = width;
      rb->Height = height;

      /* This sets the Get/PutRow/Value functions */
      intel_set_span_functions(&irb->Base);

      return GL_TRUE;
   }
}
int brw_prepare_vertices( struct brw_context *brw,
			       GLuint min_index,
			       GLuint max_index )
{
   GLcontext *ctx = &brw->intel.ctx;
   struct intel_context *intel = intel_context(ctx);
   GLuint tmp = brw->vs.prog_data->inputs_read; 
   GLuint i;
   const unsigned char *ptr = NULL;
   GLuint interleave = 0;
   int ret = 0;

   struct brw_vertex_element *enabled[VERT_ATTRIB_MAX];
   GLuint nr_enabled = 0;

   struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
   GLuint nr_uploads = 0;

   /* First build an array of pointers to ve's in vb.inputs_read
    */
   if (0)
      _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);

   /* Accumulate the list of enabled arrays. */
   while (tmp) {
      GLuint i = _mesa_ffsll(tmp)-1;
      struct brw_vertex_element *input = &brw->vb.inputs[i];

      tmp &= ~(1<<i);
      enabled[nr_enabled++] = input;
   }

   /* XXX: In the rare cases where this happens we fallback all
    * the way to software rasterization, although a tnl fallback
    * would be sufficient.  I don't know of *any* real world
    * cases with > 17 vertex attributes enabled, so it probably
    * isn't an issue at this point.
    */
   if (nr_enabled >= BRW_VEP_MAX)
       return -1;

   for (i = 0; i < nr_enabled; i++) {
      struct brw_vertex_element *input = enabled[i];

      input->element_size = get_size(input->glarray->Type) * input->glarray->Size;
      input->count = input->glarray->StrideB ? max_index + 1 - min_index : 1;

      if (input->glarray->BufferObj->Name != 0) {
	 struct intel_buffer_object *intel_buffer =
	    intel_buffer_object(input->glarray->BufferObj);

	 /* Named buffer object: Just reference its contents directly. */
	 input->bo = intel_bufferobj_buffer(intel, intel_buffer,
					    INTEL_READ);
	 dri_bo_reference(input->bo);
	 input->offset = (unsigned long)input->glarray->Ptr;
	 input->stride = input->glarray->StrideB;

	 ret |= dri_bufmgr_check_aperture_space(input->bo);
      } else {
	 /* Queue the buffer object up to be uploaded in the next pass,
	  * when we've decided if we're doing interleaved or not.
	  */
	 if (i == 0) {
	    /* Position array not properly enabled:
	     */
	    if (input->glarray->StrideB == 0)
	      return -1;

	    interleave = input->glarray->StrideB;
	    ptr = input->glarray->Ptr;
	 }
	 else if (interleave != input->glarray->StrideB ||
		  (const unsigned char *)input->glarray->Ptr - ptr < 0 ||
		  (const unsigned char *)input->glarray->Ptr - ptr > interleave)
	 {
	    interleave = 0;
	 }

	 upload[nr_uploads++] = input;
	 
	 /* We rebase drawing to start at element zero only when
	  * varyings are not in vbos, which means we can end up
	  * uploading non-varying arrays (stride != 0) when min_index
	  * is zero.  This doesn't matter as the amount to upload is
	  * the same for these arrays whether the draw call is rebased
	  * or not - we just have to upload the one element.
	  */
	 assert(min_index == 0 || input->glarray->StrideB == 0);
      }
   }

   /* Handle any arrays to be uploaded. */
   if (nr_uploads > 1 && interleave && interleave <= 256) {
      /* All uploads are interleaved, so upload the arrays together as
       * interleaved.  First, upload the contents and set up upload[0].
       */
      copy_array_to_vbo_array(brw, upload[0], interleave);

      ret |= dri_bufmgr_check_aperture_space(upload[0]->bo);
      for (i = 1; i < nr_uploads; i++) {
	 /* Then, just point upload[i] at upload[0]'s buffer. */
	 upload[i]->stride = interleave;
	 upload[i]->offset = upload[0]->offset +
	    ((const unsigned char *)upload[i]->glarray->Ptr - ptr);
	 upload[i]->bo = upload[0]->bo;
	 dri_bo_reference(upload[i]->bo);
      }
   }
   else {
      /* Upload non-interleaved arrays */
      for (i = 0; i < nr_uploads; i++) {
          copy_array_to_vbo_array(brw, upload[i], upload[i]->element_size);
          if (upload[i]->bo) {
              ret |= dri_bufmgr_check_aperture_space(upload[i]->bo);
          }
      }
   }


   if (ret)
     return 1;


   return 0;
}
/**
 * Use blitting to clear the renderbuffers named by 'flags'.
 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
 * since that might include software renderbuffers or renderbuffers
 * which we're clearing with triangles.
 * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear
 */
void
intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLuint clear_depth;
   GLbitfield skipBuffers = 0;
   BATCH_LOCALS;

   /*
    * Compute values for clearing the buffers.
    */
   clear_depth = 0;
   if (mask & BUFFER_BIT_DEPTH) {
      clear_depth = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
   }
   if (mask & BUFFER_BIT_STENCIL) {
      clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
   }

   /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in
    * the loop below.
    */
   if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) {
      skipBuffers = BUFFER_BIT_STENCIL;
   }

   /* XXX Move this flush/lock into the following conditional? */
   intelFlush(&intel->ctx);
   LOCK_HARDWARE(intel);

   if (intel->numClipRects) {
      GLint cx, cy, cw, ch;
      drm_clip_rect_t clear;
      int i;

      /* Get clear bounds after locking */
      cx = fb->_Xmin;
      cy = fb->_Ymin;
      cw = fb->_Xmax - cx;
      ch = fb->_Ymax - cy;

      if (fb->Name == 0) {
         /* clearing a window */

         /* flip top to bottom */
         clear.x1 = cx + intel->drawX;
         clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
         clear.x2 = clear.x1 + cw;
         clear.y2 = clear.y1 + ch;
      }
      else {
         /* clearing FBO */
         assert(intel->numClipRects == 1);
         assert(intel->pClipRects == &intel->fboRect);
         clear.x1 = cx;
         clear.y1 = cy;
         clear.x2 = clear.x1 + cw;
         clear.y2 = clear.y1 + ch;
         /* no change to mask */
      }

      for (i = 0; i < intel->numClipRects; i++) {
         const drm_clip_rect_t *box = &intel->pClipRects[i];
         drm_clip_rect_t b;
         GLuint buf;
         GLuint clearMask = mask;      /* use copy, since we modify it below */
         GLboolean all = (cw == fb->Width && ch == fb->Height);

         if (!all) {
            intel_intersect_cliprects(&b, &clear, box);
         }
         else {
            b = *box;
         }

         if (b.x1 >= b.x2 || b.y1 >= b.y2)
            continue;

         if (0)
            _mesa_printf("clear %d,%d..%d,%d, mask %x\n",
                         b.x1, b.y1, b.x2, b.y2, mask);

         /* Loop over all renderbuffers */
         for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
            const GLbitfield bufBit = 1 << buf;
            if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
               /* OK, clear this renderbuffer */
               struct intel_region *irb_region =
		  intel_get_rb_region(fb, buf);
               dri_bo *write_buffer =
                  intel_region_buffer(intel, irb_region,
                                      all ? INTEL_WRITE_FULL :
                                      INTEL_WRITE_PART);

               GLuint clearVal;
               GLint pitch, cpp;
               GLuint BR13, CMD;

               ASSERT(irb_region);

               pitch = irb_region->pitch;
               cpp = irb_region->cpp;

               DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
                   __FUNCTION__,
                   irb_region->buffer, (pitch * cpp),
                   irb_region->draw_offset,
                   b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1);

	       BR13 = 0xf0 << 16;
	       CMD = XY_COLOR_BLT_CMD;

               /* Setup the blit command */
               if (cpp == 4) {
                  BR13 |= (1 << 24) | (1 << 25);
                  if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
                     if (clearMask & BUFFER_BIT_DEPTH)
                        CMD |= XY_BLT_WRITE_RGB;
                     if (clearMask & BUFFER_BIT_STENCIL)
                        CMD |= XY_BLT_WRITE_ALPHA;
                  }
                  else {
                     /* clearing RGBA */
                     CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
                  }
               }
               else {
                  ASSERT(cpp == 2 || cpp == 0);
                  BR13 |= (1 << 24);
               }

#ifndef I915
	       if (irb_region->tiled) {
		  CMD |= XY_DST_TILED;
		  pitch /= 4;
	       }
#endif
	       BR13 |= (pitch * cpp);

               if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
                  clearVal = clear_depth;
               }
               else {
                  clearVal = (cpp == 4)
                     ? intel->ClearColor8888 : intel->ClearColor565;
               }
               /*
                  _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
                  buf, irb->Base.Name);
                */
	       intel_wait_flips(intel);

               assert(b.x1 < b.x2);
               assert(b.y1 < b.y2);

               BEGIN_BATCH(6, REFERENCES_CLIPRECTS);
               OUT_BATCH(CMD);
               OUT_BATCH(BR13);
               OUT_BATCH((b.y1 << 16) | b.x1);
               OUT_BATCH((b.y2 << 16) | b.x2);
               OUT_RELOC(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
                         irb_region->draw_offset);
               OUT_BATCH(clearVal);
               ADVANCE_BATCH();
               clearMask &= ~bufBit;    /* turn off bit, for faster loop exit */
            }
         }
      }
      intel_batchbuffer_flush(intel->batch);
   }

   UNLOCK_HARDWARE(intel);
}
void brw_emit_vertices( struct brw_context *brw,
                        GLuint min_index,
                        GLuint max_index )
{
   GLcontext *ctx = &brw->intel.ctx;
   struct intel_context *intel = intel_context(ctx);
   GLuint tmp = brw->vs.prog_data->inputs_read;
   struct brw_vertex_element *enabled[VERT_ATTRIB_MAX];
   GLuint i;
   GLuint nr_enabled = 0;

  /* Accumulate the list of enabled arrays. */
   while (tmp) {
      i = _mesa_ffsll(tmp)-1;
      struct brw_vertex_element *input = &brw->vb.inputs[i];

      tmp &= ~(1<<i);
      enabled[nr_enabled++] = input;
   }


   /* Now emit VB and VEP state packets.
    *
    * This still defines a hardware VB for each input, even if they
    * are interleaved or from the same VBO.  TBD if this makes a
    * performance difference.
    */
   BEGIN_BATCH(1 + nr_enabled * 4, IGNORE_CLIPRECTS);
   OUT_BATCH((CMD_VERTEX_BUFFER << 16) |
	     ((1 + nr_enabled * 4) - 2));

   for (i = 0; i < nr_enabled; i++) {
      struct brw_vertex_element *input = enabled[i];

      OUT_BATCH((i << BRW_VB0_INDEX_SHIFT) |
		BRW_VB0_ACCESS_VERTEXDATA |
		(input->stride << BRW_VB0_PITCH_SHIFT));
      OUT_RELOC(input->bo,
		DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
		input->offset);
      OUT_BATCH(max_index);
      OUT_BATCH(0); /* Instance data step rate */

      /* Unreference the buffer so it can get freed, now that we won't
       * touch it any more.
       */
      dri_bo_unreference(input->bo);
      input->bo = NULL;
   }
   ADVANCE_BATCH();

   BEGIN_BATCH(1 + nr_enabled * 2, IGNORE_CLIPRECTS);
   OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + nr_enabled * 2) - 2));
   for (i = 0; i < nr_enabled; i++) {
      struct brw_vertex_element *input = enabled[i];
      uint32_t format = get_surface_type(input->glarray->Type,
					 input->glarray->Size,
					 input->glarray->Normalized);
      uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC;
      uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC;
      uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC;
      uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC;

      switch (input->glarray->Size) {
      case 0: comp0 = BRW_VE1_COMPONENT_STORE_0;
      case 1: comp1 = BRW_VE1_COMPONENT_STORE_0;
      case 2: comp2 = BRW_VE1_COMPONENT_STORE_0;
      case 3: comp3 = BRW_VE1_COMPONENT_STORE_1_FLT;
	 break;
      }

      OUT_BATCH((i << BRW_VE0_INDEX_SHIFT) |
		BRW_VE0_VALID |
		(format << BRW_VE0_FORMAT_SHIFT) |
		(0 << BRW_VE0_SRC_OFFSET_SHIFT));
      OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
		(comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
		(comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
		(comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
		((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
   }
   ADVANCE_BATCH();
}
Example #24
0
/**
 * Called by ctx->Driver.Clear.
 */
static void
intelClear(GLcontext *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
   GLbitfield tri_mask = 0;
   GLbitfield blit_mask = 0;
   GLbitfield swrast_mask = 0;
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLuint i;

   if (0)
      fprintf(stderr, "%s\n", __FUNCTION__);

   /* HW color buffers (front, back, aux, generic FBO, etc) */
   if (colorMask == ~0) {
      /* clear all R,G,B,A */
      /* XXX FBO: need to check if colorbuffers are software RBOs! */
      blit_mask |= (mask & BUFFER_BITS_COLOR);
   }
   else {
      /* glColorMask in effect */
      tri_mask |= (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT));
   }

   /* HW stencil */
   if (mask & BUFFER_BIT_STENCIL) {
      const struct intel_region *stencilRegion
         = intel_get_rb_region(fb, BUFFER_STENCIL);
      if (stencilRegion) {
         /* have hw stencil */
         if (IS_965(intel->intelScreen->deviceID) ||
	     (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
	    /* We have to use the 3D engine if we're clearing a partial mask
	     * of the stencil buffer, or if we're on a 965 which has a tiled
	     * depth/stencil buffer in a layout we can't blit to.
	     */
            tri_mask |= BUFFER_BIT_STENCIL;
         }
         else {
            /* clearing all stencil bits, use blitting */
            blit_mask |= BUFFER_BIT_STENCIL;
         }
      }
   }

   /* HW depth */
   if (mask & BUFFER_BIT_DEPTH) {
      /* clear depth with whatever method is used for stencil (see above) */
      if (IS_965(intel->intelScreen->deviceID) ||
	  tri_mask & BUFFER_BIT_STENCIL)
         tri_mask |= BUFFER_BIT_DEPTH;
      else
         blit_mask |= BUFFER_BIT_DEPTH;
   }

   /* If we're doing a tri pass for depth/stencil, include a likely color
    * buffer with it.
    */
   if (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
      int color_bit = _mesa_ffs(mask & TRI_CLEAR_COLOR_BITS);
      if (color_bit != 0) {
	 tri_mask |= blit_mask & (1 << (color_bit - 1));
	 blit_mask &= ~(1 << (color_bit - 1));
      }
   }

   /* SW fallback clearing */
   swrast_mask = mask & ~tri_mask & ~blit_mask;

   for (i = 0; i < BUFFER_COUNT; i++) {
      GLuint bufBit = 1 << i;
      if ((blit_mask | tri_mask) & bufBit) {
         if (!fb->Attachment[i].Renderbuffer->ClassID) {
            blit_mask &= ~bufBit;
            tri_mask &= ~bufBit;
            swrast_mask |= bufBit;
         }
      }
   }

   if (blit_mask) {
      if (INTEL_DEBUG & DEBUG_BLIT) {
	 DBG("blit clear:");
	 for (i = 0; i < BUFFER_COUNT; i++) {
	    if (blit_mask & (1 << i))
	       DBG(" %s", buffer_names[i]);
	 }
	 DBG("\n");
      }
      intelClearWithBlit(ctx, blit_mask);
   }

   if (tri_mask) {
      if (INTEL_DEBUG & DEBUG_BLIT) {
	 DBG("tri clear:");
	 for (i = 0; i < BUFFER_COUNT; i++) {
	    if (tri_mask & (1 << i))
	       DBG(" %s", buffer_names[i]);
	 }
	 DBG("\n");
      }
      intel_clear_tris(ctx, tri_mask);
   }

   if (swrast_mask) {
      if (INTEL_DEBUG & DEBUG_BLIT) {
	 DBG("swrast clear:");
	 for (i = 0; i < BUFFER_COUNT; i++) {
	    if (swrast_mask & (1 << i))
	       DBG(" %s", buffer_names[i]);
	 }
	 DBG("\n");
      }
      _swrast_Clear(ctx, swrast_mask);
   }
}
Example #25
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(struct gl_context * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
    struct intel_context *intel = intel_context(ctx);
    struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
    struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
    struct intel_texture_image *intel_image = intel_texture_image(image);
    struct intel_mipmap_tree *mt = intel_image->mt;
    int layer;

    (void) fb;

    if (att->CubeMapFace > 0) {
        assert(att->Zoffset == 0);
        layer = att->CubeMapFace;
    } else {
        layer = att->Zoffset;
    }

    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);
        _swrast_render_texture(ctx, fb, att);
        return;
    }
    else if (!irb) {
        intel_miptree_check_level_layer(mt, att->TextureLevel, layer);

        irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0);

        if (irb) {
            /* bind the wrapper to the attachment point */
            _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base);
        }
        else {
            /* fallback to software rendering */
            _swrast_render_texture(ctx, fb, att);
            return;
        }
    }

    if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) {
        _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
        _swrast_render_texture(ctx, fb, att);
        return;
    }

    DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n",
        _mesa_get_format_name(image->TexFormat),
        att->Texture->Name, image->Width, image->Height,
        irb->Base.Base.RefCount);

    intel_image->used_as_render_target = true;

#ifndef I915
    if (need_tile_offset_workaround(brw_context(ctx), irb)) {
        /* Original gen4 hardware couldn't draw to a non-tile-aligned
         * destination in a miptree unless you actually setup your
         * renderbuffer as a miptree and used the fragile
         * lod/array_index/etc. controls to select the image.  So,
         * instead, we just make a new single-level miptree and render
         * into that.
         */
        struct intel_context *intel = intel_context(ctx);
        struct intel_mipmap_tree *new_mt;
        int width, height, depth;

        intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);

        new_mt = intel_miptree_create(intel, image->TexObject->Target,
                                      intel_image->base.Base.TexFormat,
                                      intel_image->base.Base.Level,
                                      intel_image->base.Base.Level,
                                      width, height, depth,
                                      true);

        intel_miptree_copy_teximage(intel, intel_image, new_mt);
        intel_renderbuffer_set_draw_offset(irb);

        intel_miptree_reference(&irb->mt, intel_image->mt);
        intel_miptree_release(&new_mt);
    }
#endif
    /* update drawing region, etc */
    intel_draw_buffer(ctx);
}
Example #26
0
/**
 * Replace data in a subrange of buffer object.  If the data range
 * specified by size + offset extends beyond the end of the buffer or
 * if data is NULL, no copy is performed.
 * Called via glBufferSubDataARB().
 */
static void
intel_bufferobj_subdata(struct gl_context * ctx,
                        GLintptrARB offset,
                        GLsizeiptrARB size,
                        const GLvoid * data, struct gl_buffer_object *obj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
   bool busy;

   if (size == 0)
      return;

   assert(intel_obj);

   /* If we have a single copy in system memory, update that */
   if (intel_obj->sys_buffer) {
      if (intel_obj->source)
	 release_buffer(intel_obj);

      if (intel_obj->buffer == NULL) {
	 memcpy((char *)intel_obj->sys_buffer + offset, data, size);
	 return;
      }

      free(intel_obj->sys_buffer);
      intel_obj->sys_buffer = NULL;
   }

   /* Otherwise we need to update the copy in video memory. */
   busy =
      drm_intel_bo_busy(intel_obj->buffer) ||
      drm_intel_bo_references(intel->batch.bo, intel_obj->buffer);

   /* replace the current busy bo with fresh data */
   if (busy && size == intel_obj->Base.Size) {
      drm_intel_bo_unreference(intel_obj->buffer);
      intel_bufferobj_alloc_buffer(intel, intel_obj);
      drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
   } else if (intel->gen < 6) {
      if (busy) {
	 drm_intel_bo *temp_bo;

	 temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64);

	 drm_intel_bo_subdata(temp_bo, 0, size, data);

	 intel_emit_linear_blit(intel,
				intel_obj->buffer, offset,
				temp_bo, 0,
				size);

	 drm_intel_bo_unreference(temp_bo);
      } else {
	 drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
      }
   } else {
      /* Can't use the blit to modify the buffer in the middle of batch. */
      if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) {
	 intel_batchbuffer_flush(intel);
      }
      drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
   }
}
Example #27
0
/**
 * Do additional "completeness" testing of a framebuffer object.
 */
static void
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
    struct intel_context *intel = intel_context(ctx);
    const struct intel_renderbuffer *depthRb =
        intel_get_renderbuffer(fb, BUFFER_DEPTH);
    const struct intel_renderbuffer *stencilRb =
        intel_get_renderbuffer(fb, BUFFER_STENCIL);
    struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
    int i;

    if (depthRb)
        depth_mt = depthRb->mt;
    if (stencilRb) {
        stencil_mt = stencilRb->mt;
        if (stencil_mt->stencil_mt)
            stencil_mt = stencil_mt->stencil_mt;
    }

    if (depth_mt && stencil_mt) {
        if (depth_mt == stencil_mt) {
            /* For true packed depth/stencil (not faked on prefers-separate-stencil
             * hardware) we need to be sure they're the same level/layer, since
             * we'll be emitting a single packet describing the packed setup.
             */
            if (depthRb->mt_level != stencilRb->mt_level ||
                    depthRb->mt_layer != stencilRb->mt_layer) {
                fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
            }
        } else {
            if (!intel->has_separate_stencil)
                fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
            if (stencil_mt->format != MESA_FORMAT_S8)
                fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
            if (intel->gen < 7 && depth_mt->hiz_mt == NULL) {
                /* Before Gen7, separate depth and stencil buffers can be used
                 * only if HiZ is enabled. From the Sandybridge PRM, Volume 2,
                 * Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable:
                 *     [DevSNB]: This field must be set to the same value (enabled
                 *     or disabled) as Hierarchical Depth Buffer Enable.
                 */
                fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
            }
        }
    }

    for (i = 0; i < Elements(fb->Attachment); i++) {
        struct gl_renderbuffer *rb;
        struct intel_renderbuffer *irb;

        if (fb->Attachment[i].Type == GL_NONE)
            continue;

        /* A supported attachment will have a Renderbuffer set either
         * from being a Renderbuffer or being a texture that got the
         * intel_wrap_texture() treatment.
         */
        rb = fb->Attachment[i].Renderbuffer;
        if (rb == NULL) {
            DBG("attachment without renderbuffer\n");
            fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
            continue;
        }

        if (fb->Attachment[i].Type == GL_TEXTURE) {
            const struct gl_texture_image *img =
                _mesa_get_attachment_teximage_const(&fb->Attachment[i]);

            if (img->Border) {
                DBG("texture with border\n");
                fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
                continue;
            }
        }

        irb = intel_renderbuffer(rb);
        if (irb == NULL) {
            DBG("software rendering renderbuffer\n");
            fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
            continue;
        }

        if (!intel->vtbl.render_target_supported(intel, rb)) {
            DBG("Unsupported HW texture/renderbuffer format attached: %s\n",
                _mesa_get_format_name(intel_rb_format(irb)));
            fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
        }
    }
}
Example #28
0
static const GLubyte *
intelGetString(struct gl_context * ctx, GLenum name)
{
   const struct intel_context *const intel = intel_context(ctx);
   const char *chipset;
   static char buffer[128];

   switch (name) {
   case GL_VENDOR:
      return (GLubyte *) "Intel Open Source Technology Center";
      break;

   case GL_RENDERER:
      switch (intel->intelScreen->deviceID) {
      case PCI_CHIP_845_G:
         chipset = "Intel(R) 845G";
         break;
      case PCI_CHIP_I830_M:
         chipset = "Intel(R) 830M";
         break;
      case PCI_CHIP_I855_GM:
         chipset = "Intel(R) 852GM/855GM";
         break;
      case PCI_CHIP_I865_G:
         chipset = "Intel(R) 865G";
         break;
      case PCI_CHIP_I915_G:
         chipset = "Intel(R) 915G";
         break;
      case PCI_CHIP_E7221_G:
	 chipset = "Intel (R) E7221G (i915)";
	 break;
      case PCI_CHIP_I915_GM:
         chipset = "Intel(R) 915GM";
         break;
      case PCI_CHIP_I945_G:
         chipset = "Intel(R) 945G";
         break;
      case PCI_CHIP_I945_GM:
         chipset = "Intel(R) 945GM";
         break;
      case PCI_CHIP_I945_GME:
         chipset = "Intel(R) 945GME";
         break;
      case PCI_CHIP_G33_G:
	 chipset = "Intel(R) G33";
	 break;
      case PCI_CHIP_Q35_G:
	 chipset = "Intel(R) Q35";
	 break;
      case PCI_CHIP_Q33_G:
	 chipset = "Intel(R) Q33";
	 break;
      case PCI_CHIP_IGD_GM:
      case PCI_CHIP_IGD_G:
	 chipset = "Intel(R) IGD";
	 break;
      case PCI_CHIP_I965_Q:
	 chipset = "Intel(R) 965Q";
	 break;
      case PCI_CHIP_I965_G:
      case PCI_CHIP_I965_G_1:
	 chipset = "Intel(R) 965G";
	 break;
      case PCI_CHIP_I946_GZ:
	 chipset = "Intel(R) 946GZ";
	 break;
      case PCI_CHIP_I965_GM:
	 chipset = "Intel(R) 965GM";
	 break;
      case PCI_CHIP_I965_GME:
	 chipset = "Intel(R) 965GME/GLE";
	 break;
      case PCI_CHIP_GM45_GM:
	 chipset = "Mobile Intel® GM45 Express Chipset";
	 break; 
      case PCI_CHIP_IGD_E_G:
	 chipset = "Intel(R) Integrated Graphics Device";
	 break;
      case PCI_CHIP_G45_G:
         chipset = "Intel(R) G45/G43";
         break;
      case PCI_CHIP_Q45_G:
         chipset = "Intel(R) Q45/Q43";
         break;
      case PCI_CHIP_G41_G:
         chipset = "Intel(R) G41";
         break;
      case PCI_CHIP_B43_G:
      case PCI_CHIP_B43_G1:
         chipset = "Intel(R) B43";
         break;
      case PCI_CHIP_ILD_G:
         chipset = "Intel(R) Ironlake Desktop";
         break;
      case PCI_CHIP_ILM_G:
         chipset = "Intel(R) Ironlake Mobile";
         break;
      case PCI_CHIP_SANDYBRIDGE_GT1:
      case PCI_CHIP_SANDYBRIDGE_GT2:
      case PCI_CHIP_SANDYBRIDGE_GT2_PLUS:
	 chipset = "Intel(R) Sandybridge Desktop";
	 break;
      case PCI_CHIP_SANDYBRIDGE_M_GT1:
      case PCI_CHIP_SANDYBRIDGE_M_GT2:
      case PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS:
	 chipset = "Intel(R) Sandybridge Mobile";
	 break;
      case PCI_CHIP_SANDYBRIDGE_S:
	 chipset = "Intel(R) Sandybridge Server";
	 break;
      case PCI_CHIP_IVYBRIDGE_GT1:
      case PCI_CHIP_IVYBRIDGE_GT2:
	 chipset = "Intel(R) Ivybridge Desktop";
	 break;
      case PCI_CHIP_IVYBRIDGE_M_GT1:
      case PCI_CHIP_IVYBRIDGE_M_GT2:
	 chipset = "Intel(R) Ivybridge Mobile";
	 break;
      case PCI_CHIP_IVYBRIDGE_S_GT1:
      case PCI_CHIP_IVYBRIDGE_S_GT2:
	 chipset = "Intel(R) Ivybridge Server";
	 break;
      case PCI_CHIP_HASWELL_GT1:
      case PCI_CHIP_HASWELL_GT2:
      case PCI_CHIP_HASWELL_GT2_PLUS:
      case PCI_CHIP_HASWELL_SDV_GT1:
      case PCI_CHIP_HASWELL_SDV_GT2:
      case PCI_CHIP_HASWELL_SDV_GT2_PLUS:
      case PCI_CHIP_HASWELL_ULT_GT1:
      case PCI_CHIP_HASWELL_ULT_GT2:
      case PCI_CHIP_HASWELL_ULT_GT2_PLUS:
      case PCI_CHIP_HASWELL_CRW_GT1:
      case PCI_CHIP_HASWELL_CRW_GT2:
      case PCI_CHIP_HASWELL_CRW_GT2_PLUS:
	 chipset = "Intel(R) Haswell Desktop";
	 break;
      case PCI_CHIP_HASWELL_M_GT1:
      case PCI_CHIP_HASWELL_M_GT2:
      case PCI_CHIP_HASWELL_M_GT2_PLUS:
      case PCI_CHIP_HASWELL_SDV_M_GT1:
      case PCI_CHIP_HASWELL_SDV_M_GT2:
      case PCI_CHIP_HASWELL_SDV_M_GT2_PLUS:
      case PCI_CHIP_HASWELL_ULT_M_GT1:
      case PCI_CHIP_HASWELL_ULT_M_GT2:
      case PCI_CHIP_HASWELL_ULT_M_GT2_PLUS:
      case PCI_CHIP_HASWELL_CRW_M_GT1:
      case PCI_CHIP_HASWELL_CRW_M_GT2:
      case PCI_CHIP_HASWELL_CRW_M_GT2_PLUS:
	 chipset = "Intel(R) Haswell Mobile";
	 break;
      case PCI_CHIP_HASWELL_S_GT1:
      case PCI_CHIP_HASWELL_S_GT2:
      case PCI_CHIP_HASWELL_S_GT2_PLUS:
      case PCI_CHIP_HASWELL_SDV_S_GT1:
      case PCI_CHIP_HASWELL_SDV_S_GT2:
      case PCI_CHIP_HASWELL_SDV_S_GT2_PLUS:
      case PCI_CHIP_HASWELL_ULT_S_GT1:
      case PCI_CHIP_HASWELL_ULT_S_GT2:
      case PCI_CHIP_HASWELL_ULT_S_GT2_PLUS:
      case PCI_CHIP_HASWELL_CRW_S_GT1:
      case PCI_CHIP_HASWELL_CRW_S_GT2:
      case PCI_CHIP_HASWELL_CRW_S_GT2_PLUS:
	 chipset = "Intel(R) Haswell Server";
	 break;
      default:
         chipset = "Unknown Intel Chipset";
         break;
      }

      (void) driGetRendererString(buffer, chipset, 0);
      return (GLubyte *) buffer;

   default:
      return NULL;
   }
}
/**
 * Do additional "completeness" testing of a framebuffer object.
 */
static void
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_renderbuffer *depthRb =
      intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_renderbuffer *stencilRb =
      intel_get_renderbuffer(fb, BUFFER_STENCIL);
   struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
   int i;

   DBG("%s() on fb %p (%s)\n", __FUNCTION__,
       fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
	    (fb == ctx->ReadBuffer ? "readbuffer" : "other buffer")));

   if (depthRb)
      depth_mt = depthRb->mt;
   if (stencilRb)
      stencil_mt = stencilRb->mt;

   if (depth_mt && stencil_mt) {
      /* Make sure that the depth and stencil buffers are actually the same
       * slice of the same miptree, since we only support packed
       * depth/stencil.
       */
      if (depth_mt == stencil_mt) {
	 if (depthRb->mt_level != stencilRb->mt_level ||
	     depthRb->mt_layer != stencilRb->mt_layer) {
	    fbo_incomplete(fb,
                           "FBO incomplete: depth image level/layer %d/%d != "
                           "stencil image %d/%d\n",
                           depthRb->mt_level,
                           depthRb->mt_layer,
                           stencilRb->mt_level,
                           stencilRb->mt_layer);
	 }
      } else {
         fbo_incomplete(fb, "FBO incomplete: separate stencil unsupported\n");
      }
   }

   for (i = 0; i < Elements(fb->Attachment); i++) {
      struct gl_renderbuffer *rb;
      struct intel_renderbuffer *irb;

      if (fb->Attachment[i].Type == GL_NONE)
	 continue;

      /* A supported attachment will have a Renderbuffer set either
       * from being a Renderbuffer or being a texture that got the
       * intel_wrap_texture() treatment.
       */
      rb = fb->Attachment[i].Renderbuffer;
      if (rb == NULL) {
	 fbo_incomplete(fb, "FBO incomplete: attachment without "
                        "renderbuffer\n");
	 continue;
      }

      if (fb->Attachment[i].Type == GL_TEXTURE) {
	 if (rb->TexImage->Border) {
	    fbo_incomplete(fb, "FBO incomplete: texture with border\n");
	    continue;
	 }
      }

      irb = intel_renderbuffer(rb);
      if (irb == NULL) {
	 fbo_incomplete(fb, "FBO incomplete: software rendering "
                        "renderbuffer\n");
	 continue;
      }

      if (!intel->vtbl.render_target_supported(intel, rb)) {
	 fbo_incomplete(fb, "FBO incomplete: Unsupported HW "
                        "texture/renderbuffer format attached: %s\n",
                        _mesa_get_format_name(intel_rb_format(irb)));
      }
   }
}