void brw_meta_resolve_color(struct brw_context *brw, struct intel_mipmap_tree *mt) { struct gl_context *ctx = &brw->ctx; struct gl_framebuffer *drawFb; struct gl_renderbuffer *rb; struct rect rect; brw_emit_mi_flush(brw); drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (drawFb == NULL) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "in %s", __func__); return; } _mesa_meta_begin(ctx, MESA_META_ALL); rb = brw_get_rb_for_slice(brw, mt, 0, 0, false); _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer); _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, rb); _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); brw_fast_clear_init(brw); use_rectlist(brw, true); brw_bind_rep_write_shader(brw, (float *) fast_clear_color); /* SKL+ also has a resolve mode for compressed render targets and thus more * bits to let us select the type of resolve. For fast clear resolves, it * turns out we can use the same value as pre-SKL though. */ if (intel_miptree_is_lossless_compressed(brw, mt)) set_fast_clear_op(brw, GEN9_PS_RENDER_TARGET_RESOLVE_FULL); else set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE); mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED; get_resolve_rect(brw, mt, &rect); brw_draw_rectlist(brw, &rect, 1); set_fast_clear_op(brw, 0); use_rectlist(brw, false); _mesa_reference_renderbuffer(&rb, NULL); _mesa_reference_framebuffer(&drawFb, NULL); _mesa_meta_end(ctx); /* We're typically called from intel_update_state() and we're supposed to * return with the state all updated to what it was before * brw_meta_resolve_color() was called. The meta rendering will have * messed up the state and we need to call _mesa_update_state() again to * get back to where we were supposed to be when resolve was called. */ if (ctx->NewState) _mesa_update_state(ctx); }
bool _mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *tex_image, int xoffset, int yoffset, int zoffset, int width, int height, int depth, GLenum format, GLenum type, const void *pixels, bool create_pbo, const struct gl_pixelstore_attrib *packing) { struct gl_buffer_object *pbo = NULL; GLuint pbo_tex = 0; struct gl_framebuffer *readFb = NULL; struct gl_framebuffer *drawFb = NULL; int image_height; struct gl_texture_image *pbo_tex_image; GLenum status; bool success = false; int z; if (!_mesa_is_bufferobj(packing->BufferObj) && (!create_pbo || pixels == NULL)) return false; if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL || format == GL_STENCIL_INDEX || format == GL_COLOR_INDEX) return false; if (ctx->_ImageTransferState) return false; /* This function rely on BlitFramebuffer to fill in the pixel data for * glTex[Sub]Image*D. But, BlitFrameBuffer doesn't support signed to * unsigned or unsigned to signed integer conversions. */ if (need_signed_unsigned_int_conversion(tex_image->TexFormat, format, type)) return false; /* For arrays, use a tall (height * depth) 2D texture but taking into * account the inter-image padding specified with the image height packing * property. */ image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight; _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER | MESA_META_PIXEL_STORE)); pbo_tex_image = create_texture_for_pbo(ctx, create_pbo, GL_PIXEL_UNPACK_BUFFER, dims, width, height, depth, format, type, pixels, packing, &pbo, &pbo_tex); if (!pbo_tex_image) { _mesa_meta_end(ctx); return false; } readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (readFb == NULL) goto fail; drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (drawFb == NULL) goto fail; _mesa_bind_framebuffers(ctx, drawFb, tex_image ? readFb : ctx->ReadBuffer); if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) { assert(depth == 1); assert(zoffset == 0); depth = height; height = 1; image_height = 1; zoffset = yoffset; yoffset = 0; } _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, GL_COLOR_ATTACHMENT0, pbo_tex_image, 0); /* If this passes on the first layer it should pass on the others */ status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, tex_image, zoffset); /* If this passes on the first layer it should pass on the others */ status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; /* Explicitly disable sRGB encoding */ ctx->DrawBuffer->Visual.sRGBCapable = false; _mesa_update_state(ctx); if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 0, 0, width, height, xoffset, yoffset, xoffset + width, yoffset + height, GL_COLOR_BUFFER_BIT, GL_NEAREST)) goto fail; for (z = 1; z < depth; z++) { _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, tex_image, zoffset + z); _mesa_update_state(ctx); _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 0, z * image_height, width, z * image_height + height, xoffset, yoffset, xoffset + width, yoffset + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); } success = true; fail: _mesa_reference_framebuffer(&readFb, NULL); _mesa_reference_framebuffer(&drawFb, NULL); _mesa_DeleteTextures(1, &pbo_tex); _mesa_reference_buffer_object(ctx, &pbo, NULL); _mesa_meta_end(ctx); return success; }
/** * Blit rectangular region, optionally from one framebuffer to another. * * Note, if the src buffer is multisampled and the dest is not, this is * when the samples must be resolved to a single color. */ void GLAPIENTRY _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); const struct gl_framebuffer *readFb, *drawFb; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, _mesa_lookup_enum_by_nr(filter)); if (ctx->NewState) { _mesa_update_state(ctx); } readFb = ctx->ReadBuffer; drawFb = ctx->DrawBuffer; if (!readFb || !drawFb) { /* This will normally never happen but someday we may want to * support MakeCurrent() with no drawables. */ return; } /* check for complete framebuffers */ if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glBlitFramebufferEXT(incomplete draw/read buffers)"); return; } if (!is_valid_blit_filter(ctx, filter)) { _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)", _mesa_lookup_enum_by_nr(filter)); return; } if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT || filter == GL_SCALED_RESOLVE_NICEST_EXT) && (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)", _mesa_lookup_enum_by_nr(filter)); return; } if (mask & ~legalMaskBits) { _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); return; } /* depth/stencil must be blitted with nearest filtering */ if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) && filter != GL_NEAREST) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); return; } /* get color read/draw renderbuffers */ if (mask & GL_COLOR_BUFFER_BIT) { const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers; const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if (!colorReadRb || numColorDrawBuffers == 0) { mask &= ~GL_COLOR_BUFFER_BIT; } else { for (i = 0; i < numColorDrawBuffers; i++) { colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL * ES 3.0.1 spec says: * * "If the source and destination buffers are identical, an * INVALID_OPERATION error is generated. Different mipmap * levels of a texture, different layers of a three- * dimensional texture or two-dimensional array texture, and * different faces of a cube map texture do not constitute * identical buffers." */ if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer(source and destination color " "buffer cannot be the same)"); return; } if (!compatible_color_datatypes(colorReadRb->Format, colorDrawRb->Format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(color buffer datatypes mismatch)"); return; } /* extra checks for multisample copies... */ if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { /* color formats must match */ if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); return; } } } if (filter != GL_NEAREST) { /* From EXT_framebuffer_multisample_blit_scaled specification: * "Calling BlitFramebuffer will result in an INVALID_OPERATION error * if filter is not NEAREST and read buffer contains integer data." */ GLenum type = _mesa_get_format_datatype(colorReadRb->Format); if (type == GL_INT || type == GL_UNSIGNED_INT) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(integer color type)"); return; } } } } if (mask & GL_STENCIL_BUFFER_BIT) { struct gl_renderbuffer *readRb = readFb->Attachment[BUFFER_STENCIL].Renderbuffer; struct gl_renderbuffer *drawRb = drawFb->Attachment[BUFFER_STENCIL].Renderbuffer; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_STENCIL_BUFFER_BIT; } else { int read_z_bits, draw_z_bits; if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer(source and destination stencil " "buffer cannot be the same)"); return; } if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { /* There is no need to check the stencil datatype here, because * there is only one: GL_UNSIGNED_INT. */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer(stencil attachment format mismatch)"); return; } read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS); draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS); /* If both buffers also have depth data, the depth formats must match * as well. If one doesn't have depth, it's not blitted, so we should * ignore the depth format check. */ if (read_z_bits > 0 && draw_z_bits > 0 && (read_z_bits != draw_z_bits || _mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" "(stencil attachment depth format mismatch)"); return; } } } if (mask & GL_DEPTH_BUFFER_BIT) { struct gl_renderbuffer *readRb = readFb->Attachment[BUFFER_DEPTH].Renderbuffer; struct gl_renderbuffer *drawRb = drawFb->Attachment[BUFFER_DEPTH].Renderbuffer; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_DEPTH_BUFFER_BIT; } else { int read_s_bit, draw_s_bit; if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer(source and destination depth " "buffer cannot be the same)"); return; } if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || (_mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer(depth attachment format mismatch)"); return; } read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS); draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS); /* If both buffers also have stencil data, the stencil formats must * match as well. If one doesn't have stencil, it's not blitted, so * we should ignore the stencil format check. */ if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" "(depth attachment stencil bits mismatch)"); return; } } } if (_mesa_is_gles3(ctx)) { /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES * 3.0.1 spec says: * * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero, * an INVALID_OPERATION error is generated." */ if (drawFb->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer(destination samples must be 0)"); return; } /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES * 3.0.1 spec says: * * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero, * no copy is performed and an INVALID_OPERATION error is generated * if the formats of the read and draw framebuffers are not * identical or if the source and destination rectangles are not * defined with the same (X0, Y0) and (X1, Y1) bounds." * * The format check was made above because desktop OpenGL has the same * requirement. */ if (readFb->Visual.samples > 0 && (srcX0 != dstX0 || srcY0 != dstY0 || srcX1 != dstX1 || srcY1 != dstY1)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer(bad src/dst multisample region)"); return; } } else { if (readFb->Visual.samples > 0 && drawFb->Visual.samples > 0 && readFb->Visual.samples != drawFb->Visual.samples) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(mismatched samples)"); return; } /* extra checks for multisample copies... */ if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) && (filter == GL_NEAREST || filter == GL_LINEAR)) { /* src and dest region sizes must be the same */ if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) || abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); return; } } } /* Debug code */ if (DEBUG_BLIT) { const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i = 0; printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," " 0x%x, 0x%x)\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); if (colorReadRb) { const struct gl_renderbuffer_attachment *att; att = find_attachment(readFb, colorReadRb); printf(" Src FBO %u RB %u (%dx%d) ", readFb->Name, colorReadRb->Name, colorReadRb->Width, colorReadRb->Height); if (att && att->Texture) { printf("Tex %u tgt 0x%x level %u face %u", att->Texture->Name, att->Texture->Target, att->TextureLevel, att->CubeMapFace); } printf("\n"); /* Print all active color render buffers */ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; att = find_attachment(drawFb, colorDrawRb); printf(" Dst FBO %u RB %u (%dx%d) ", drawFb->Name, colorDrawRb->Name, colorDrawRb->Width, colorDrawRb->Height); if (att && att->Texture) { printf("Tex %u tgt 0x%x level %u face %u", att->Texture->Name, att->Texture->Target, att->TextureLevel, att->CubeMapFace); } printf("\n"); } } } if (!mask || (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 || (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) { return; } ASSERT(ctx->Driver.BlitFramebuffer); ctx->Driver.BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); }
/** * Prior to drawing anything with glBegin, glDrawArrays, etc. this function * is called to see if it's valid to render. This involves checking that * the current shader is valid and the framebuffer is complete. * It also check the current pipeline object is valid if any. * If an error is detected it'll be recorded here. * \return GL_TRUE if OK to render, GL_FALSE if not */ GLboolean _mesa_valid_to_render(struct gl_context *ctx, const char *where) { /* This depends on having up to date derived state (shaders) */ if (ctx->NewState) _mesa_update_state(ctx); if (ctx->API == API_OPENGL_COMPAT) { /* Any shader stages that are not supplied by the GLSL shader and have * assembly shaders enabled must now be validated. */ if (!ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(vertex program not valid)", where); return GL_FALSE; } if (!ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) { if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(fragment program not valid)", where); return GL_FALSE; } /* If drawing to integer-valued color buffers, there must be an * active fragment shader (GL_EXT_texture_integer). */ if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(integer format but no fragment shader)", where); return GL_FALSE; } } } /* A pipeline object is bound */ if (ctx->_Shader->Name && !ctx->_Shader->Validated) { if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glValidateProgramPipeline failed to validate the " "pipeline"); return GL_FALSE; } } /* If a program is active and SSO not in use, check if validation of * samplers succeeded for the active program. */ if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) { char errMsg[100]; if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram, errMsg, 100)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg); return GL_FALSE; } } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "%s(incomplete framebuffer)", where); return GL_FALSE; } if (!check_blend_func_error(ctx)) { return GL_FALSE; } #ifdef DEBUG if (ctx->_Shader->Flags & GLSL_LOG) { struct gl_shader_program **shProg = ctx->_Shader->CurrentProgram; gl_shader_stage i; for (i = 0; i < MESA_SHADER_STAGES; i++) { if (shProg[i] == NULL || shProg[i]->_Used || shProg[i]->_LinkedShaders[i] == NULL) continue; /* This is the first time this shader is being used. * Append shader's constants/uniforms to log file. * * Only log data for the program target that matches the shader * target. It's possible to have a program bound to the vertex * shader target that also supplied a fragment shader. If that * program isn't also bound to the fragment shader target we don't * want to log its fragment data. */ _mesa_append_uniforms_to_file(shProg[i]->_LinkedShaders[i]); } for (i = 0; i < MESA_SHADER_STAGES; i++) { if (shProg[i] != NULL) shProg[i]->_Used = GL_TRUE; } } #endif return GL_TRUE; }
/* 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; }
void GLAPIENTRY _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) { GLuint maxUnit; const struct gl_texture_unit *texUnit; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)"); return; } texUnit = _mesa_get_current_tex_unit(ctx); if (target == GL_TEXTURE_ENV) { if (pname == GL_TEXTURE_ENV_COLOR) { if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state(ctx); if(ctx->Color._ClampFragmentColor) COPY_4FV( params, texUnit->EnvColor ); else COPY_4FV( params, texUnit->EnvColorUnclamped ); } else { GLint val = get_texenvi(ctx, texUnit, pname); if (val >= 0) { *params = (GLfloat) val; } } } else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { if (pname == GL_TEXTURE_LOD_BIAS_EXT) { *params = texUnit->LodBias; } else { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); return; } } else if (target == GL_POINT_SPRITE_NV) { /* GL_ARB_point_sprite / GL_NV_point_sprite */ if (!ctx->Extensions.NV_point_sprite && !ctx->Extensions.ARB_point_sprite) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); return; } if (pname == GL_COORD_REPLACE_NV) { *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit]; } else { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); return; } } else { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); return; } }
/* * Render a bitmap. */ static bool do_blit_bitmap( struct gl_context *ctx, GLint dstx, GLint dsty, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { struct brw_context *brw = brw_context(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; struct intel_renderbuffer *irb; GLfloat tmpColor[4]; GLubyte ubcolor[4]; GLuint color; GLsizei bitmap_width = width; GLsizei bitmap_height = height; GLint px, py; GLuint stipple[32]; GLint orig_dstx = dstx; GLint orig_dsty = dsty; /* Update draw buffer bounds */ _mesa_update_state(ctx); if (ctx->Depth.Test) { /* The blit path produces incorrect results when depth testing is on. * It seems the blit Z coord is always 1.0 (the far plane) so fragments * will likely be obscured by other, closer geometry. */ return false; } intel_prepare_render(brw); if (fb->_NumColorDrawBuffers != 1) { perf_debug("accelerated glBitmap() only supports rendering to a " "single color buffer\n"); return false; } irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); if (_mesa_is_bufferobj(unpack->BufferObj)) { bitmap = map_pbo(ctx, width, height, unpack, bitmap); if (bitmap == NULL) return true; /* even though this is an error, we're done */ } COPY_4V(tmpColor, ctx->Current.RasterColor); if (_mesa_need_secondary_color(ctx)) { ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor); } UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]); UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]); UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]); UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]); switch (_mesa_get_render_format(ctx, intel_rb_format(irb))) { case MESA_FORMAT_B8G8R8A8_UNORM: case MESA_FORMAT_B8G8R8X8_UNORM: color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]); break; case MESA_FORMAT_B5G6R5_UNORM: color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]); break; default: perf_debug("Unsupported format %s in accelerated glBitmap()\n", _mesa_get_format_name(irb->mt->format)); return false; } if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) return false; /* Clip to buffer bounds and scissor. */ if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax, &dstx, &dsty, &width, &height)) goto out; dsty = y_flip(fb, dsty, height); #define DY 32 #define DX 32 /* The blitter has no idea about fast color clears, so we need to resolve * the miptree before we do anything. */ intel_miptree_all_slices_resolve_color(brw, irb->mt, 0); /* Chop it all into chunks that can be digested by hardware: */ for (py = 0; py < height; py += DY) { for (px = 0; px < width; px += DX) { int h = MIN2(DY, height - py); int w = MIN2(DX, width - px); GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8; GLenum logic_op = ctx->Color.ColorLogicOpEnabled ? ctx->Color.LogicOp : GL_COPY; assert(sz <= sizeof(stipple)); memset(stipple, 0, sz); /* May need to adjust this when padding has been introduced in * sz above: * * Have to translate destination coordinates back into source * coordinates. */ int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack, bitmap, -orig_dstx + (dstx + px), -orig_dsty + y_flip(fb, dsty + py, h), w, h, (GLubyte *)stipple, 8, _mesa_is_winsys_fbo(fb)); if (count == 0) continue; if (!intelEmitImmediateColorExpandBlit(brw, irb->mt->cpp, (GLubyte *)stipple, sz, color, irb->mt->pitch, irb->mt->bo, 0, irb->mt->tiling, dstx + px, dsty + py, w, h, logic_op)) { return false; } if (ctx->Query.CurrentOcclusionObject) ctx->Query.CurrentOcclusionObject->Result += count; } } out: if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) intel_batchbuffer_flush(brw); if (_mesa_is_bufferobj(unpack->BufferObj)) { /* done with PBO so unmap it now */ ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } return true; }