static void brw_update_texture_surface( GLcontext *ctx, GLuint unit, struct brw_surface_state *surf ) { struct intel_context *intel = intel_context(ctx); struct brw_context *brw = brw_context(ctx); struct gl_texture_object *tObj = brw->attribs.Texture->Unit[unit]._Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage = tObj->Image[0][intelObj->firstLevel]; memset(surf, 0, sizeof(*surf)); surf->ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; surf->ss0.surface_type = translate_tex_target(tObj->Target); surf->ss0.surface_format = translate_tex_format(firstImage->TexFormat->MesaFormat, tObj->DepthMode); /* This is ok for all textures with channel width 8bit or less: */ /* surf->ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ /* BRW_NEW_LOCK */ surf->ss1.base_addr = bmBufferOffset(intel, intelObj->mt->region->buffer); surf->ss2.mip_count = intelObj->lastLevel - intelObj->firstLevel; surf->ss2.width = firstImage->Width - 1; surf->ss2.height = firstImage->Height - 1; surf->ss3.tile_walk = BRW_TILEWALK_XMAJOR; surf->ss3.tiled_surface = intelObj->mt->region->tiled; /* always zero */ surf->ss3.pitch = (intelObj->mt->pitch * intelObj->mt->cpp) - 1; surf->ss3.depth = firstImage->Depth - 1; surf->ss4.min_lod = 0; if (tObj->Target == GL_TEXTURE_CUBE_MAP) { surf->ss0.cube_pos_x = 1; surf->ss0.cube_pos_y = 1; surf->ss0.cube_pos_z = 1; surf->ss0.cube_neg_x = 1; surf->ss0.cube_neg_y = 1; surf->ss0.cube_neg_z = 1; } }
void intelEmitFillBlit( struct intel_context *intel, GLuint cpp, GLshort dst_pitch, struct buffer *dst_buffer, GLuint dst_offset, GLboolean dst_tiled, GLshort x, GLshort y, GLshort w, GLshort h, GLuint color ) { GLuint BR13, CMD; BATCH_LOCALS; dst_pitch *= cpp; switch(cpp) { case 1: case 2: case 3: BR13 = (0xF0 << 16) | (1<<24); CMD = XY_COLOR_BLT_CMD; break; case 4: BR13 = (0xF0 << 16) | (1<<24) | (1<<25); CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); break; default: return; } if (dst_tiled) { CMD |= XY_DST_TILED; dst_pitch /= 4; } BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); OUT_BATCH( CMD ); OUT_BATCH( dst_pitch | BR13 ); OUT_BATCH( (y << 16) | x ); OUT_BATCH( ((y+h) << 16) | (x+w) ); OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset ); OUT_BATCH( color ); ADVANCE_BATCH(); }
/*********************************************************************** * Emit all state: */ void brw_validate_state( struct brw_context *brw ) { struct brw_state_flags *state = &brw->state.dirty; GLuint i; state->mesa |= brw->intel.NewGLState; brw->intel.NewGLState = 0; if (brw->wrap) state->brw |= BRW_NEW_CONTEXT; if (brw->emit_state_always) { state->mesa |= ~0; state->brw |= ~0; } /* texenv program needs to notify us somehow when this happens: * Some confusion about which state flag should represent this change. */ if (brw->fragment_program != brw->attribs.FragmentProgram->_Current) { brw->fragment_program = brw->attribs.FragmentProgram->_Current; brw->state.dirty.mesa |= _NEW_PROGRAM; brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM; } if (state->mesa == 0 && state->cache == 0 && state->brw == 0) return; if (brw->state.dirty.brw & BRW_NEW_CONTEXT) brw_clear_batch_cache_flush(brw); /* Make an early reference to the state pools, as we don't cope * well with them being evicted from here down. */ (void)bmBufferOffset(&brw->intel, brw->pool[BRW_GS_POOL].buffer); (void)bmBufferOffset(&brw->intel, brw->pool[BRW_SS_POOL].buffer); (void)bmBufferOffset(&brw->intel, brw->intel.batch->buffer); if (INTEL_DEBUG) { /* Debug version which enforces various sanity checks on the * state flags which are generated and checked to help ensure * state atoms are ordered correctly in the list. */ struct brw_state_flags examined, prev; _mesa_memset(&examined, 0, sizeof(examined)); prev = *state; for (i = 0; i < brw->state.nr_atoms; i++) { const struct brw_tracked_state *atom = brw->state.atoms[i]; struct brw_state_flags generated; assert(atom->dirty.mesa || atom->dirty.brw || atom->dirty.cache); assert(atom->update); if (check_state(state, &atom->dirty)) { brw->state.atoms[i]->update( brw ); /* emit_foo(brw); */ } accumulate_state(&examined, &atom->dirty); /* generated = (prev ^ state) * if (examined & generated) * fail; */ xor_states(&generated, &prev, state); assert(!check_state(&examined, &generated)); prev = *state; } } else { for (i = 0; i < Elements(atoms); i++) { if (check_state(state, &brw->state.atoms[i]->dirty)) brw->state.atoms[i]->update( brw ); } } memset(state, 0, sizeof(*state)); }
static void upload_wm_surfaces(struct brw_context *brw ) { GLcontext *ctx = &brw->intel.ctx; struct intel_context *intel = &brw->intel; GLuint i; { struct brw_surface_state surf; struct intel_region *region = brw->state.draw_region; memset(&surf, 0, sizeof(surf)); if (region->cpp == 4) surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; else surf.ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; surf.ss0.surface_type = BRW_SURFACE_2D; /* _NEW_COLOR */ surf.ss0.color_blend = (!brw->attribs.Color->_LogicOpEnabled && brw->attribs.Color->BlendEnabled); surf.ss0.writedisable_red = !brw->attribs.Color->ColorMask[0]; surf.ss0.writedisable_green = !brw->attribs.Color->ColorMask[1]; surf.ss0.writedisable_blue = !brw->attribs.Color->ColorMask[2]; surf.ss0.writedisable_alpha = !brw->attribs.Color->ColorMask[3]; /* BRW_NEW_LOCK */ surf.ss1.base_addr = bmBufferOffset(&brw->intel, region->buffer); surf.ss2.width = region->pitch - 1; /* XXX: not really! */ surf.ss2.height = region->height - 1; surf.ss3.tile_walk = BRW_TILEWALK_XMAJOR; surf.ss3.tiled_surface = region->tiled; surf.ss3.pitch = (region->pitch * region->cpp) - 1; brw->wm.bind.surf_ss_offset[0] = brw_cache_data( &brw->cache[BRW_SS_SURFACE], &surf ); brw->wm.nr_surfaces = 1; } for (i = 0; i < BRW_MAX_TEX_UNIT; i++) { struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i]; /* _NEW_TEXTURE, BRW_NEW_TEXDATA */ if (texUnit->_ReallyEnabled && intel_finalize_mipmap_tree(intel,texUnit->_Current)) { struct brw_surface_state surf; brw_update_texture_surface(ctx, i, &surf); brw->wm.bind.surf_ss_offset[i+1] = brw_cache_data( &brw->cache[BRW_SS_SURFACE], &surf ); brw->wm.nr_surfaces = i+2; } else if( texUnit->_ReallyEnabled && texUnit->_Current == intel->frame_buffer_texobj ) { brw->wm.bind.surf_ss_offset[i+1] = brw->wm.bind.surf_ss_offset[0]; brw->wm.nr_surfaces = i+2; } else { brw->wm.bind.surf_ss_offset[i+1] = 0; } } brw->wm.bind_ss_offset = brw_cache_data( &brw->cache[BRW_SS_SURF_BIND], &brw->wm.bind ); }
void brw_upload_indices( struct brw_context *brw, const struct _mesa_index_buffer *index_buffer ) { GLcontext *ctx = &brw->intel.ctx; struct intel_context *intel = &brw->intel; GLuint ib_size = get_size(index_buffer->type) * index_buffer->count; struct gl_buffer_object *bufferobj = index_buffer->obj; GLuint offset = (GLuint)index_buffer->ptr; /* Turn into a proper VBO: */ if (!bufferobj->Name) { /* Get new bufferobj, offset: */ get_space(brw, ib_size, &bufferobj, &offset); /* Straight upload */ ctx->Driver.BufferSubData( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, offset, ib_size, index_buffer->ptr, bufferobj); } else { /* If the index buffer isn't aligned to its element size, we have to * rebase it into a temporary. */ if ((get_size(index_buffer->type) - 1) & offset) { struct gl_buffer_object *vbo; GLuint voffset; GLubyte *map = ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, GL_DYNAMIC_DRAW_ARB, bufferobj); map += offset; get_space(brw, ib_size, &vbo, &voffset); ctx->Driver.BufferSubData(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, voffset, ib_size, map, vbo); ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobj); bufferobj = vbo; offset = voffset; } } /* Emit the indexbuffer packet: */ { struct brw_indexbuffer ib; struct buffer *buffer = intel_bufferobj_buffer(intel_buffer_object(bufferobj)); memset(&ib, 0, sizeof(ib)); ib.header.bits.opcode = CMD_INDEX_BUFFER; ib.header.bits.length = sizeof(ib)/4 - 2; ib.header.bits.index_format = get_index_type(index_buffer->type); ib.header.bits.cut_index_enable = 0; BEGIN_BATCH(4, 0); OUT_BATCH( ib.header.dword ); OUT_BATCH( bmBufferOffset(intel, buffer) + offset ); OUT_BATCH( bmBufferOffset(intel, buffer) + offset + ib_size ); OUT_BATCH( 0 ); ADVANCE_BATCH(); } }
GLboolean brw_upload_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_packet vep; struct brw_array_state vbp; GLuint i; const void *ptr = NULL; GLuint interleave = 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; memset(&vbp, 0, sizeof(vbp)); memset(&vep, 0, sizeof(vep)); /* 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); while (tmp) { GLuint i = _mesa_ffsll(tmp)-1; struct brw_vertex_element *input = &brw->vb.inputs[i]; tmp &= ~(1<<i); enabled[nr_enabled++] = input; input->index = 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) { if (i == 0) { /* Position array not properly enabled: */ if (input->glarray->StrideB == 0) return GL_FALSE; interleave = input->glarray->StrideB; ptr = input->glarray->Ptr; } else if (interleave != input->glarray->StrideB || (const char *)input->glarray->Ptr - (const char *)ptr < 0 || (const char *)input->glarray->Ptr - (const char *)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); } } /* Upload interleaved arrays if all uploads are interleaved */ if (nr_uploads > 1 && interleave && interleave <= 256) { struct brw_vertex_element *input0 = upload[0]; input0->glarray = copy_array_to_vbo_array(brw, 0, input0->glarray, interleave, input0->count); for (i = 1; i < nr_uploads; i++) { upload[i]->glarray = interleaved_vbo_array(brw, i, input0->glarray, upload[i]->glarray, ptr); } } else { for (i = 0; i < nr_uploads; i++) { struct brw_vertex_element *input = upload[i]; input->glarray = copy_array_to_vbo_array(brw, i, input->glarray, input->element_size, input->count); } } /* 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 GL_FALSE; /* 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. */ for (i = 0; i < nr_enabled; i++) { struct brw_vertex_element *input = enabled[i]; input->vep = &vep.ve[i]; input->vep->ve0.src_format = get_surface_type(input->glarray->Type, input->glarray->Size, input->glarray->Normalized); input->vep->ve0.valid = 1; input->vep->ve1.dst_offset = (i) * 4; input->vep->ve1.vfcomponent3 = BRW_VFCOMPONENT_STORE_SRC; input->vep->ve1.vfcomponent2 = BRW_VFCOMPONENT_STORE_SRC; input->vep->ve1.vfcomponent1 = BRW_VFCOMPONENT_STORE_SRC; input->vep->ve1.vfcomponent0 = BRW_VFCOMPONENT_STORE_SRC; switch (input->glarray->Size) { case 0: input->vep->ve1.vfcomponent0 = BRW_VFCOMPONENT_STORE_0; case 1: input->vep->ve1.vfcomponent1 = BRW_VFCOMPONENT_STORE_0; case 2: input->vep->ve1.vfcomponent2 = BRW_VFCOMPONENT_STORE_0; case 3: input->vep->ve1.vfcomponent3 = BRW_VFCOMPONENT_STORE_1_FLT; break; } input->vep->ve0.vertex_buffer_index = i; input->vep->ve0.src_offset = 0; vbp.vb[i].vb0.bits.pitch = input->glarray->StrideB; vbp.vb[i].vb0.bits.pad = 0; vbp.vb[i].vb0.bits.access_type = BRW_VERTEXBUFFER_ACCESS_VERTEXDATA; vbp.vb[i].vb0.bits.vb_index = i; vbp.vb[i].offset = (GLuint)input->glarray->Ptr; vbp.vb[i].buffer = array_buffer(input->glarray); vbp.vb[i].max_index = max_index; } /* Now emit VB and VEP state packets: */ vbp.header.bits.length = (1 + nr_enabled * 4) - 2; vbp.header.bits.opcode = CMD_VERTEX_BUFFER; BEGIN_BATCH(vbp.header.bits.length+2, 0); OUT_BATCH( vbp.header.dword ); for (i = 0; i < nr_enabled; i++) { OUT_BATCH( vbp.vb[i].vb0.dword ); OUT_BATCH( bmBufferOffset(&brw->intel, vbp.vb[i].buffer) + vbp.vb[i].offset); OUT_BATCH( vbp.vb[i].max_index ); OUT_BATCH( vbp.vb[i].instance_data_step_rate ); } ADVANCE_BATCH(); vep.header.length = (1 + nr_enabled * sizeof(vep.ve[0])/4) - 2; vep.header.opcode = CMD_VERTEX_ELEMENT; brw_cached_batch_struct(brw, &vep, 4 + nr_enabled * sizeof(vep.ve[0])); return GL_TRUE; }
void intelEmitImmediateColorExpandBlit(struct intel_context *intel, GLuint cpp, GLubyte *src_bits, GLuint src_size, GLuint fg_color, GLshort dst_pitch, struct buffer *dst_buffer, GLuint dst_offset, GLboolean dst_tiled, GLshort x, GLshort y, GLshort w, GLshort h, GLenum logic_op) { struct xy_setup_blit setup; struct xy_text_immediate_blit text; int dwords = ((src_size + 7) & ~7) / 4; assert( logic_op - GL_CLEAR >= 0 ); assert( logic_op - GL_CLEAR < 0x10 ); if (w < 0 || h < 0) return; dst_pitch *= cpp; if (dst_tiled) dst_pitch /= 4; DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n", __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords); memset(&setup, 0, sizeof(setup)); setup.br0.client = CLIENT_2D; setup.br0.opcode = OPCODE_XY_SETUP_BLT; setup.br0.write_alpha = (cpp == 4); setup.br0.write_rgb = (cpp == 4); setup.br0.dst_tiled = dst_tiled; setup.br0.length = (sizeof(setup) / sizeof(int)) - 2; setup.br13.dest_pitch = dst_pitch; setup.br13.rop = translate_raster_op(logic_op); setup.br13.color_depth = (cpp == 4) ? BR13_8888 : BR13_565; setup.br13.clipping_enable = 0; setup.br13.mono_source_transparency = 1; setup.dw2.clip_y1 = 0; setup.dw2.clip_x1 = 0; setup.dw3.clip_y2 = 100; setup.dw3.clip_x2 = 100; setup.dest_base_addr = bmBufferOffset(intel, dst_buffer) + dst_offset; setup.background_color = 0; setup.foreground_color = fg_color; setup.pattern_base_addr = 0; memset(&text, 0, sizeof(text)); text.dw0.client = CLIENT_2D; text.dw0.opcode = OPCODE_XY_TEXT_IMMEDIATE_BLT; text.dw0.pad0 = 0; text.dw0.byte_packed = 1; /* ?maybe? */ text.dw0.pad1 = 0; text.dw0.dst_tiled = dst_tiled; text.dw0.pad2 = 0; text.dw0.length = (sizeof(text)/sizeof(int)) - 2 + dwords; text.dw1.dest_y1 = y; /* duplicates info in setup blit */ text.dw1.dest_x1 = x; text.dw2.dest_y2 = y + h; text.dw2.dest_x2 = x + w; intel_batchbuffer_require_space( intel->batch, sizeof(setup) + sizeof(text) + dwords, INTEL_BATCH_NO_CLIPRECTS ); intel_batchbuffer_data( intel->batch, &setup, sizeof(setup), INTEL_BATCH_NO_CLIPRECTS ); intel_batchbuffer_data( intel->batch, &text, sizeof(text), INTEL_BATCH_NO_CLIPRECTS ); intel_batchbuffer_data( intel->batch, src_bits, dwords * 4, INTEL_BATCH_NO_CLIPRECTS ); }
/* * Copy the back buffer to the front buffer. */ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv, const drm_clip_rect_t *rect ) { struct intel_context *intel; GLboolean missed_target; int64_t ust; DBG("%s\n", __FUNCTION__); assert(dPriv); assert(dPriv->driContextPriv); assert(dPriv->driContextPriv->driverPrivate); intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; intelFlush( &intel->ctx ); bmFinishFenceLock(intel, intel->last_swap_fence); /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets * should work regardless. */ LOCK_HARDWARE( intel ); if (!rect) { UNLOCK_HARDWARE( intel ); driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target ); LOCK_HARDWARE( intel ); } { intelScreenPrivate *intelScreen = intel->intelScreen; __DRIdrawablePrivate *dPriv = intel->driDrawable; int nbox = dPriv->numClipRects; drm_clip_rect_t *pbox = dPriv->pClipRects; int cpp = intelScreen->cpp; struct intel_region *src, *dst; int BR13, CMD; int i; int src_pitch, dst_pitch; if (intel->sarea->pf_current_page == 0) { dst = intel->front_region; src = intel->back_region; } else { assert(0); src = intel->front_region; dst = intel->back_region; } src_pitch = src->pitch * src->cpp; dst_pitch = dst->pitch * dst->cpp; if (cpp == 2) { BR13 = (0xCC << 16) | (1<<24); CMD = XY_SRC_COPY_BLT_CMD; } else { BR13 = (0xCC << 16) | (1<<24) | (1<<25); CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB); } if (src->tiled) { CMD |= XY_SRC_TILED; src_pitch /= 4; } if (dst->tiled) { CMD |= XY_DST_TILED; dst_pitch /= 4; } for (i = 0 ; i < nbox; i++, pbox++) { drm_clip_rect_t tmp = *pbox; if (rect) { if (!intel_intersect_cliprects(&tmp, &tmp, rect)) continue; } if (tmp.x1 > tmp.x2 || tmp.y1 > tmp.y2 || tmp.x2 > intelScreen->width || tmp.y2 > intelScreen->height) continue; BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); OUT_BATCH( CMD ); OUT_BATCH( dst_pitch | BR13 ); OUT_BATCH( (tmp.y1 << 16) | tmp.x1 ); OUT_BATCH( (tmp.y2 << 16) | tmp.x2 ); OUT_BATCH( bmBufferOffset(intel, dst->buffer) ); OUT_BATCH( (tmp.y1 << 16) | tmp.x1 ); OUT_BATCH( src_pitch ); OUT_BATCH( bmBufferOffset(intel, src->buffer) ); ADVANCE_BATCH(); } } intel_batchbuffer_flush( intel->batch ); intel->second_last_swap_fence = intel->last_swap_fence; intel->last_swap_fence = bmSetFenceLock( intel ); UNLOCK_HARDWARE( intel ); if (!rect) { intel->swap_count++; (*dri_interface->getUST)(&ust); if (missed_target) { intel->swap_missed_count++; intel->swap_missed_ust = ust - intel->swap_ust; } intel->swap_ust = ust; } }
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 ); }
/* Copy BitBlt */ void intelEmitCopyBlit( struct intel_context *intel, GLuint cpp, GLshort src_pitch, struct buffer *src_buffer, GLuint src_offset, GLboolean src_tiled, GLshort dst_pitch, struct buffer *dst_buffer, GLuint dst_offset, GLboolean dst_tiled, GLshort src_x, GLshort src_y, GLshort dst_x, GLshort dst_y, GLshort w, GLshort h, GLenum logic_op ) { GLuint CMD, BR13; int dst_y2 = dst_y + h; int dst_x2 = dst_x + w; BATCH_LOCALS; DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d op:%d\n", __FUNCTION__, src_buffer, src_pitch, src_x, src_y, dst_buffer, dst_pitch, dst_x, dst_y, w,h,logic_op); assert( logic_op - GL_CLEAR >= 0 ); assert( logic_op - GL_CLEAR < 0x10 ); src_pitch *= cpp; dst_pitch *= cpp; switch(cpp) { case 1: case 2: case 3: BR13 = (translate_raster_op(logic_op) << 16) | (1<<24); CMD = XY_SRC_COPY_BLT_CMD; break; case 4: BR13 = (translate_raster_op(logic_op) << 16) | (1<<24) | (1<<25); CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB); break; default: return; } if (src_tiled) { CMD |= XY_SRC_TILED; src_pitch /= 4; } if (dst_tiled) { CMD |= XY_DST_TILED; dst_pitch /= 4; } if (dst_y2 < dst_y || dst_x2 < dst_x) { return; } dst_pitch &= 0xffff; src_pitch &= 0xffff; /* Initial y values don't seem to work with negative pitches. If * we adjust the offsets manually (below), it seems to work fine. * * On the other hand, if we always adjust, the hardware doesn't * know which blit directions to use, so overlapping copypixels get * the wrong result. */ if (dst_pitch > 0 && src_pitch > 0) { BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); OUT_BATCH( CMD ); OUT_BATCH( dst_pitch | BR13 ); OUT_BATCH( (dst_y << 16) | dst_x ); OUT_BATCH( (dst_y2 << 16) | dst_x2 ); OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset ); OUT_BATCH( (src_y << 16) | src_x ); OUT_BATCH( src_pitch ); OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset ); ADVANCE_BATCH(); } else { BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); OUT_BATCH( CMD ); OUT_BATCH( (dst_pitch & 0xffff) | BR13 ); OUT_BATCH( (0 << 16) | dst_x ); OUT_BATCH( (h << 16) | dst_x2 ); OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset + dst_y * dst_pitch ); OUT_BATCH( (0 << 16) | src_x ); OUT_BATCH( (src_pitch & 0xffff) ); OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset + src_y * src_pitch ); ADVANCE_BATCH(); } }