diff options
Diffstat (limited to 'src/i830_video.c')
-rw-r--r-- | src/i830_video.c | 247 |
1 files changed, 245 insertions, 2 deletions
diff --git a/src/i830_video.c b/src/i830_video.c index 1a133b9a..d13b75fd 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -83,6 +83,8 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xaalocal.h" #include "dixstruct.h" #include "fourcc.h" +#include "brw_defines.h" +#include "brw_structs.h" #ifndef USE_USLEEP_FOR_VIDEO #define USE_USLEEP_FOR_VIDEO 0 @@ -488,7 +490,7 @@ I830InitVideo(ScreenPtr pScreen) /* Set up textured video if we can do it at this depth and we are on * supported hardware. */ - if (pScrn->bitsPerPixel >= 16 && IS_I9XX(pI830)) { + if (pScrn->bitsPerPixel >= 16 && IS_I9XX(pI830) || IS_BROADWATER(pI830)) { texturedAdaptor = I830SetupImageVideoTextured(pScreen); if (texturedAdaptor != NULL) { adaptors[num_adaptors++] = texturedAdaptor; @@ -2607,6 +2609,247 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, pI830->AccelInfoRec->NeedToSync = TRUE; } +static void +BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, + RegionPtr dstRegion, + short width, short height, int video_pitch, + int x1, int y1, int x2, int y2, + short src_w, short src_h, + short drw_w, short drw_h, + DrawablePtr pDraw) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 format, ms3, s2; + BoxPtr pbox; + int nbox, dxo, dyo; + Bool planar; + int urb_vs_start, urb_vs_size; + int urb_gs_start, urb_gs_size; + int urb_clip_start, urb_clip_size; + int urb_sf_start, urb_sf_size; + int urb_cs_start, urb_cs_size; + struct brw_surface_state *dest_surf_state; + struct brw_surface_state *src_surf_state; + struct brw_sampler_state *src_sampler_state; + struct brw_cc_unit_state *cc_state; + + ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height, + video_pitch); + + assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2)); + + /* Tell the rotation code that we have stomped its invariant state by + * setting a high bit. We don't use any invariant 3D state for video, so we + * don't have to worry about it ourselves. + */ + *pI830->used3D |= 1 << 30; + + /* Set up a default static partitioning of the URB, which is supposed to + * allow anything we would want to do, at potentially lower performance. + */ + urb_vs_start = 0; + urb_vs_size = 8 * 5; + urb_gs_start = urb_vs_start + urb_vs_size; + urb_gs_size = 4 * 5; + urb_clip_start = urb_gs_start + urb_gs_size; + urb_clip_size = 6 * 5; + urb_sf_start = urb_clip_start + urb_clip_size; + urb_sf_size = 8 * 11; + urb_cs_start = urb_sf_start + urb_sf_size; + urb_cs_size = 2 * 32; + + /* We'll be poking the state buffers that could be in use by the 3d hardware + * here, but we should have synced the 3D engine if we've reached this point. + */ + + /* XXX: Allocate space for our state buffers, and set up the state structure + * pointers. + */ + + /* Set up the state buffer for the destination surface */ + memset(dest_surf_state, 0, sizeof(*dest_surf_state)); + dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; + if (pI830->cpp == 2) { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; + } else { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8X8_UNORM; + } + dest_surf_state->ss1.base_addr = pI830->bufferOffset; + dest_surf_state->ss2.width = pScrn->virtualX - 1; + dest_surf_state->ss2.height = pScrn->virtualY - 1; + dest_surf_state->ss3.pitch = pI830->displayWidth * pI830->cpp; + + /* Set up the source surface state buffer */ + memset(src_surf_state, 0, sizeof(*src_surf_state)); + src_surf_state->ss0.surface_type = BRW_SURFACE_2D; + switch (id) { + case FOURCC_YUY2: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL; + break; + case FOURCC_UYVY: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY; + break; + } + src_surf_state->ss1.base_addr = pPriv->YBuf0offset; + src_surf_state->ss2.width = width; + src_surf_state->ss2.height = height; + src_surf_state->ss3.pitch = video_pitch - 1; + + /* Set up the packed YUV source sampler. Doesn't do colorspace conversion. + */ + memset(src_sampler_state, 0, sizeof(*src_sampler_state)); + src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + + /* XXX: Set up binding table state */ + /* XXX: Set up the VF for however we send our prims */ + /* XXX: Set up the SF kernel to do coord interp */ + /* XXX: Set up the SF state */ + /* XXX: Set up the clipper to do nothing for us, I think */ + + /* XXX: Set up the PS kernel (dispatched by WM) for convertiny YUV to RGB. + * The 3D driver does this as: + * + CONST C0 = { -.5, -.0625, -.5, 1.164 } + CONST C1 = { 1.596, -0.813, 2.018, -.391 } + UYV = TEX ... + UYV.xyz = ADD UYV, C0 + UYV.y = MUL UYV.y, C0.w + RGB.xyz = MAD UYV.xxz, C1, UYV.y + RGB.y = MAD UYV.z, C1.w, RGB.y + * + */ + + /* XXX: Set up the WM state. */ + + /* XXX: Set up CC_VIEWPORT, though we really don't care about its behavior. + */ + + memset(cc_state, 0, sizeof(*cc_state)); + /* XXX: Set pointer to CC_VIEWPORT */ + + BEGIN_LP_RING(XXX); + OUT_RING(MI_FLUSH | MI_STATE_INSTRUCTION_CACHE_FLUSH); + + OUT_RING(STATE3D_PIPELINE_SELECT | PIPELINE_SELECT_3D); + + OUT_RING(STATE3D_URB_FENCE | + UF0_CS_REALLOC | + UF0_VFE_REALLOC | + UF0_SF_REALLOC | + UF0_CLIP_REALLOC | + UF0_GS_REALLOC | + UF0_VS_REALLOC); + OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | + ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | + ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); + OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | + ((urb_vfe_start + urb_vfe_size) << UF2_VFE_FENCE_SHIFT) | + ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); + + OUT_RING(STATE3D_DRAWING_RECTANGLE_BRW | 2); + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING((pScrn->virtualX - 1) | + (pScrn->virtualY - 1) << 16); /* ymax, xmax */ + OUT_RING(0x00000000); /* yorigin, xorigin */ + + /* XXX: Set the locations of the sampler/surface/etc. state */ + + ADVANCE_LP_RING(); + + /* XXX: Finally, emit some prims */ + + dxo = dstRegion->extents.x1; + dyo = dstRegion->extents.y1; + +#if 0 + pbox = REGION_RECTS(dstRegion); + nbox = REGION_NUM_RECTS(dstRegion); + while (nbox--) + { + int box_x1 = pbox->x1; + int box_y1 = pbox->y1; + int box_x2 = pbox->x2; + int box_y2 = pbox->y2; + int j; + float src_scale_x, src_scale_y; + CARD32 vb[40]; + float verts[4][2], tex[4][2], tex2[4][2]; + int vert_data_count; + + pbox++; + + src_scale_x = (float)src_w / (float)drw_w; + src_scale_y = (float)src_h / (float)drw_h; + + if (!planar) + vert_data_count = 32; + else + vert_data_count = 40; + + BEGIN_LP_RING(vert_data_count + 8); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + + /* vertex data */ + OUT_RING(PRIMITIVE3D | PRIM3D_INLINE | PRIM3D_TRIFAN | + (vert_data_count - 1)); + verts[0][0] = box_x1; verts[0][1] = box_y1; + verts[1][0] = box_x2; verts[1][1] = box_y1; + verts[2][0] = box_x2; verts[2][1] = box_y2; + verts[3][0] = box_x1; verts[3][1] = box_y2; + + if (!planar) { + tex[0][0] = (box_x1 - dxo) * src_scale_x; + tex[0][1] = (box_y1 - dyo) * src_scale_y; + tex[1][0] = (box_x2 - dxo) * src_scale_x; + tex[1][1] = (box_y1 - dyo) * src_scale_y; + tex[2][0] = (box_x2 - dxo) * src_scale_x; + tex[2][1] = (box_y2 - dyo) * src_scale_y; + tex[3][0] = (box_x1 - dxo) * src_scale_x; + tex[3][1] = (box_y2 - dyo) * src_scale_y; + /* emit vertex buffer */ + draw_poly(vb, verts, tex, NULL); + for (j = 0; j < vert_data_count; j++) + OUT_RING(vb[j]); + } else { + tex[0][0] = (box_x1 - dxo) * src_scale_x / 2.0; + tex[0][1] = (box_y1 - dyo) * src_scale_y / 2.0; + tex[1][0] = (box_x2 - dxo) * src_scale_x / 2.0; + tex[1][1] = (box_y1 - dyo) * src_scale_y / 2.0; + tex[2][0] = (box_x2 - dxo) * src_scale_x / 2.0; + tex[2][1] = (box_y2 - dyo) * src_scale_y / 2.0; + tex[3][0] = (box_x1 - dxo) * src_scale_x / 2.0; + tex[3][1] = (box_y2 - dyo) * src_scale_y / 2.0; + tex2[0][0] = (box_x1 - dxo) * src_scale_x; + tex2[0][1] = (box_y1 - dyo) * src_scale_y; + tex2[1][0] = (box_x2 - dxo) * src_scale_x; + tex2[1][1] = (box_y1 - dyo) * src_scale_y; + tex2[2][0] = (box_x2 - dxo) * src_scale_x; + tex2[2][1] = (box_y2 - dyo) * src_scale_y; + tex2[3][0] = (box_x1 - dxo) * src_scale_x; + tex2[3][1] = (box_y2 - dyo) * src_scale_y; + /* emit vertex buffer */ + draw_poly(vb, verts, tex, tex2); + for (j = 0; j < vert_data_count; j++) + OUT_RING(vb[j]); + } + + ADVANCE_LP_RING(); + } +#endif + + if (pI830->AccelInfoRec) + pI830->AccelInfoRec->NeedToSync = TRUE; +} + static FBLinearPtr I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) { @@ -2749,7 +2992,7 @@ I830PutImage(ScrnInfoPtr pScrn, if (pPriv->textured) { pitchAlignMask = 3; } else { - if (IS_BROADWATER(pI830)) { + if (IS_BROADWATER(pI830)) pitchAlignMask = 255; else pitchAlignMask = 63; |