int xa_surface_dma(struct xa_context *ctx, struct xa_surface *srf, void *data, unsigned int pitch, int to_surface, struct xa_box *boxes, unsigned int num_boxes) { struct pipe_transfer *transfer; void *map; int w, h, i; enum pipe_transfer_usage transfer_direction; struct pipe_context *pipe = ctx->pipe; transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE : PIPE_TRANSFER_READ); for (i = 0; i < num_boxes; ++i, ++boxes) { w = boxes->x2 - boxes->x1; h = boxes->y2 - boxes->y1; transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, transfer_direction, boxes->x1, boxes->y1, w, h); if (!transfer) return -XA_ERR_NORES; map = pipe_transfer_map(ctx->pipe, transfer); if (!map) goto out_no_map; if (to_surface) { util_copy_rect(map, srf->tex->format, transfer->stride, 0, 0, w, h, data, pitch, boxes->x1, boxes->y1); } else { util_copy_rect(data, srf->tex->format, pitch, boxes->x1, boxes->y1, w, h, map, transfer->stride, 0, 0); } pipe->transfer_unmap(pipe, transfer); pipe->transfer_destroy(pipe, transfer); if (to_surface) pipe->flush(pipe, &ctx->last_fence); } return XA_ERR_NONE; out_no_map: pipe->transfer_destroy(pipe, transfer); return -XA_ERR_NORES; }
/** * Copy 3D box from one place to another. * Position and sizes are in pixels. */ void util_copy_box(ubyte * dst, enum pipe_format format, unsigned dst_stride, unsigned dst_slice_stride, unsigned dst_x, unsigned dst_y, unsigned dst_z, unsigned width, unsigned height, unsigned depth, const ubyte * src, int src_stride, unsigned src_slice_stride, unsigned src_x, unsigned src_y, unsigned src_z) { unsigned z; dst += dst_z * dst_slice_stride; src += src_z * src_slice_stride; for (z = 0; z < depth; ++z) { util_copy_rect(dst, format, dst_stride, dst_x, dst_y, width, height, src, src_stride, src_x, src_y); dst += dst_slice_stride; src += src_slice_stride; } }
void NineSurface9_CopyDefaultToMem( struct NineSurface9 *This, struct NineSurface9 *From ) { struct pipe_context *pipe = This->pipe; struct pipe_resource *r_src = From->base.resource; struct pipe_transfer *transfer; struct pipe_box src_box; uint8_t *p_dst; const uint8_t *p_src; assert(This->base.pool == D3DPOOL_SYSTEMMEM && From->base.pool == D3DPOOL_DEFAULT); assert(This->desc.Width == From->desc.Width); assert(This->desc.Height == From->desc.Height); u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box); src_box.z = From->layer; p_src = pipe->transfer_map(pipe, r_src, From->level, PIPE_TRANSFER_READ, &src_box, &transfer); p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0); assert (p_src && p_dst); util_copy_rect(p_dst, This->base.info.format, This->stride, 0, 0, This->desc.Width, This->desc.Height, p_src, transfer->stride, 0, 0); pipe->transfer_unmap(pipe, transfer); }
static Bool ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst, int dst_pitch) { ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); struct pipe_transfer *transfer; if (!priv || !priv->tex) return FALSE; transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0, PIPE_TRANSFER_READ, x, y, w, h); if (!transfer) return FALSE; exa_debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n", x, y, w, h, dst_pitch); util_copy_rect((unsigned char*)dst, priv->tex->format, dst_pitch, 0, 0, w, h, exa->pipe->transfer_map(exa->pipe, transfer), transfer->stride, 0, 0); exa->pipe->transfer_unmap(exa->pipe, transfer); exa->pipe->transfer_destroy(exa->pipe, transfer); return TRUE; }
static Bool ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, int src_pitch) { ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); struct pipe_transfer *transfer; void *map; if (!priv || !priv->tex) return FALSE; map = pipe_transfer_map(exa->pipe, priv->tex, 0, 0, PIPE_TRANSFER_WRITE, x, y, w, h, &transfer); if (!map) return FALSE; exa_debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n", x, y, w, h, src_pitch); util_copy_rect(map, priv->tex->format, transfer->stride, 0, 0, w, h, (unsigned char*)src, src_pitch, 0, 0); exa->pipe->transfer_unmap(exa->pipe, transfer); return TRUE; }
/* One-shot transfer operation with data supplied in a user * pointer. XXX: strides?? */ void u_default_transfer_inline_write( struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, unsigned layer_stride) { struct pipe_transfer *transfer = NULL; uint8_t *map = NULL; assert(!(usage & PIPE_TRANSFER_READ)); /* the write flag is implicit by the nature of transfer_inline_write */ usage |= PIPE_TRANSFER_WRITE; /* transfer_inline_write implicitly discards the rewritten buffer range */ if (box->x == 0 && box->width == resource->width0) { usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; } else { usage |= PIPE_TRANSFER_DISCARD_RANGE; } map = pipe->transfer_map(pipe, resource, level, usage, box, &transfer); if (map == NULL) return; if (resource->target == PIPE_BUFFER) { assert(box->height == 1); assert(box->depth == 1); memcpy(map, data, box->width); } else { const uint8_t *src_data = data; unsigned i; for (i = 0; i < box->depth; i++) { util_copy_rect(map, resource->format, transfer->stride, /* bytes */ 0, 0, box->width, box->height, src_data, stride, /* bytes */ 0, 0); map += transfer->layer_stride; src_data += layer_stride; } } pipe_transfer_unmap(pipe, transfer); }
static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf, OMX_BUFFERHEADERTYPE* output) { omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; struct pipe_sampler_view **views; struct pipe_transfer *transfer; struct pipe_box box = { }; uint8_t *src, *dst; views = buf->get_sampler_view_planes(buf); dst = output->pBuffer; box.width = def->nFrameWidth; box.height = def->nFrameHeight; box.depth = 1; src = priv->pipe->transfer_map(priv->pipe, views[0]->texture, 0, PIPE_TRANSFER_READ, &box, &transfer); util_copy_rect(dst, views[0]->texture->format, def->nStride, 0, 0, box.width, box.height, src, transfer->stride, 0, 0); pipe_transfer_unmap(priv->pipe, transfer); dst = ((uint8_t*)output->pBuffer) + (def->nStride * box.height); box.width = def->nFrameWidth / 2; box.height = def->nFrameHeight / 2; src = priv->pipe->transfer_map(priv->pipe, views[1]->texture, 0, PIPE_TRANSFER_READ, &box, &transfer); util_copy_rect(dst, views[1]->texture->format, def->nStride, 0, 0, box.width, box.height, src, transfer->stride, 0, 0); pipe_transfer_unmap(priv->pipe, transfer); }
static void crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) { unsigned char *ptr; modesettingPtr ms = modesettingPTR(crtc->scrn); struct crtc_private *crtcp = crtc->driver_private; struct pipe_transfer *transfer; if (!crtcp->cursor_tex) { struct pipe_resource templat; struct winsys_handle whandle; memset(&templat, 0, sizeof(templat)); templat.bind |= PIPE_BIND_RENDER_TARGET; templat.bind |= PIPE_BIND_SCANOUT; templat.target = PIPE_TEXTURE_2D; templat.last_level = 0; templat.depth0 = 1; templat.array_size = 1; templat.format = PIPE_FORMAT_B8G8R8A8_UNORM; templat.width0 = 64; templat.height0 = 64; memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_KMS; crtcp->cursor_tex = ms->screen->resource_create(ms->screen, &templat); ms->screen->resource_get_handle(ms->screen, crtcp->cursor_tex, &whandle); crtcp->cursor_handle = whandle.handle; } transfer = pipe_get_transfer(ms->ctx, crtcp->cursor_tex, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, 64, 64); ptr = ms->ctx->transfer_map(ms->ctx, transfer); util_copy_rect(ptr, crtcp->cursor_tex->format, transfer->stride, 0, 0, 64, 64, (void*)image, 64 * 4, 0, 0); ms->ctx->transfer_unmap(ms->ctx, transfer); ms->ctx->transfer_destroy(ms->ctx, transfer); if (crtc->cursor_shown) drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, crtcp->cursor_handle, 64, 64); }
static void upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, const struct pipe_box *dst_box, const void *src, unsigned src_stride, unsigned src_x, unsigned src_y) { struct pipe_transfer *transfer; void *map; map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, dst_box, &transfer); if (!map) return; util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, dst_box->width, dst_box->height, src, src_stride, src_x, src_y); pipe->transfer_unmap(pipe, transfer); }
/** * Upload data to a rectangular sub-region. Lots of choices how to do this: * * - memcpy by span to current destination * - upload data as new buffer and blit * * Currently always memcpy. */ static void st_surface_data(struct pipe_context *pipe, struct pipe_transfer *dst, unsigned dstx, unsigned dsty, const void *src, unsigned src_stride, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { void *map = pipe_transfer_map(pipe, dst); assert(dst->resource); util_copy_rect(map, dst->resource->format, dst->stride, dstx, dsty, width, height, src, src_stride, srcx, srcy); pipe_transfer_unmap(pipe, dst); }
/** * Upload data to a rectangular sub-region. Lots of choices how to do this: * * - memcpy by span to current destination * - upload data as new buffer and blit * * Currently always memcpy. */ static void st_surface_data(struct pipe_context *pipe, struct pipe_transfer *dst, unsigned dstx, unsigned dsty, const void *src, unsigned src_stride, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { struct pipe_screen *screen = pipe->screen; void *map = screen->transfer_map(screen, dst); util_copy_rect(map, &dst->block, dst->stride, dstx, dsty, width, height, src, src_stride, srcx, srcy); screen->transfer_unmap(screen, dst); }
/** * Copy image data from a VdpOutputSurface to application memory in the * surface's native format. */ VdpStatus vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, VdpRect const *source_rect, void *const *destination_data, uint32_t const *destination_pitches) { vlVdpOutputSurface *vlsurface; struct pipe_context *pipe; struct pipe_resource *res; struct pipe_box box; struct pipe_transfer *transfer; uint8_t *map; vlsurface = vlGetDataHTAB(surface); if (!vlsurface) return VDP_STATUS_INVALID_HANDLE; pipe = vlsurface->device->context; if (!pipe) return VDP_STATUS_INVALID_HANDLE; pipe_mutex_lock(vlsurface->device->mutex); vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); res = vlsurface->sampler_view->texture; box = RectToPipeBox(source_rect, res); map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer); if (!map) { pipe_mutex_unlock(vlsurface->device->mutex); return VDP_STATUS_RESOURCES; } util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0, box.width, box.height, map, transfer->stride, 0, 0); pipe_transfer_unmap(pipe, transfer); pipe_mutex_unlock(vlsurface->device->mutex); return VDP_STATUS_OK; }
static Bool ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, int src_pitch) { ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); struct pipe_transfer *transfer; if (!priv || !priv->tex) return FALSE; /* make sure that any pending operations are flushed to hardware */ if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & (PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE)) xorg_exa_flush(exa, 0, NULL); transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, PIPE_TRANSFER_WRITE, x, y, w, h); if (!transfer) return FALSE; #if DEBUG_PRINT debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n", x, y, w, h, src_pitch); #endif util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), priv->tex->format, transfer->stride, 0, 0, w, h, (unsigned char*)src, src_pitch, 0, 0); exa->scrn->transfer_unmap(exa->scrn, transfer); exa->scrn->tex_transfer_destroy(transfer); return TRUE; }
static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf, OMX_BUFFERHEADERTYPE* output) { omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; struct pipe_sampler_view **views; unsigned i, j; unsigned width, height; views = buf->get_sampler_view_planes(buf); for (i = 0; i < 2 /* NV12 */; i++) { if (!views[i]) continue; width = def->nFrameWidth; height = def->nFrameHeight; vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced); for (j = 0; j < views[i]->texture->array_size; ++j) { struct pipe_box box = {0, 0, j, width, height, 1}; struct pipe_transfer *transfer; uint8_t *map, *dst; map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0, PIPE_TRANSFER_READ, &box, &transfer); if (!map) return; dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride + i * def->nFrameWidth * def->nFrameHeight; util_copy_rect(dst, views[i]->texture->format, def->nStride * views[i]->texture->array_size, 0, 0, box.width, box.height, map, transfer->stride, 0, 0); pipe_transfer_unmap(priv->pipe, transfer); } } }
HRESULT NineSurface9_CopySurface( struct NineSurface9 *This, struct NineSurface9 *From, const POINT *pDestPoint, const RECT *pSourceRect ) { struct pipe_context *pipe = This->pipe; struct pipe_resource *r_dst = This->base.resource; struct pipe_resource *r_src = From->base.resource; struct pipe_transfer *transfer; struct pipe_box src_box; struct pipe_box dst_box; uint8_t *p_dst; const uint8_t *p_src; DBG("This=%p From=%p pDestPoint=%p pSourceRect=%p\n", This, From, pDestPoint, pSourceRect); assert(This->base.pool != D3DPOOL_MANAGED && From->base.pool != D3DPOOL_MANAGED); user_assert(This->desc.Format == From->desc.Format, D3DERR_INVALIDCALL); dst_box.x = pDestPoint ? pDestPoint->x : 0; dst_box.y = pDestPoint ? pDestPoint->y : 0; user_assert(dst_box.x >= 0 && dst_box.y >= 0, D3DERR_INVALIDCALL); dst_box.z = This->layer; src_box.z = From->layer; dst_box.depth = 1; src_box.depth = 1; if (pSourceRect) { /* make sure it doesn't range outside the source surface */ user_assert(pSourceRect->left >= 0 && pSourceRect->right <= From->desc.Width && pSourceRect->top >= 0 && pSourceRect->bottom <= From->desc.Height, D3DERR_INVALIDCALL); if (rect_to_pipe_box_xy_only_clamp(&src_box, pSourceRect)) return D3D_OK; } else { src_box.x = 0; src_box.y = 0; src_box.width = From->desc.Width; src_box.height = From->desc.Height; } /* limits */ dst_box.width = This->desc.Width - dst_box.x; dst_box.height = This->desc.Height - dst_box.y; user_assert(src_box.width <= dst_box.width && src_box.height <= dst_box.height, D3DERR_INVALIDCALL); dst_box.width = src_box.width; dst_box.height = src_box.height; /* check source block align for compressed textures */ if (util_format_is_compressed(From->base.info.format) && ((src_box.width != From->desc.Width) || (src_box.height != From->desc.Height))) { const unsigned w = util_format_get_blockwidth(From->base.info.format); const unsigned h = util_format_get_blockheight(From->base.info.format); user_assert(!(src_box.width % w) && !(src_box.height % h), D3DERR_INVALIDCALL); } /* check destination block align for compressed textures */ if (util_format_is_compressed(This->base.info.format) && ((dst_box.width != This->desc.Width) || (dst_box.height != This->desc.Height) || dst_box.x != 0 || dst_box.y != 0)) { const unsigned w = util_format_get_blockwidth(This->base.info.format); const unsigned h = util_format_get_blockheight(This->base.info.format); user_assert(!(dst_box.x % w) && !(dst_box.width % w) && !(dst_box.y % h) && !(dst_box.height % h), D3DERR_INVALIDCALL); } if (r_dst && r_src) { pipe->resource_copy_region(pipe, r_dst, This->level, dst_box.x, dst_box.y, dst_box.z, r_src, From->level, &src_box); } else if (r_dst) { p_src = NineSurface9_GetSystemMemPointer(From, src_box.x, src_box.y); pipe->transfer_inline_write(pipe, r_dst, This->level, 0, /* WRITE|DISCARD are implicit */ &dst_box, p_src, From->stride, 0); } else if (r_src) { p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0); p_src = pipe->transfer_map(pipe, r_src, From->level, PIPE_TRANSFER_READ, &src_box, &transfer); if (!p_src) return D3DERR_DRIVERINTERNALERROR; util_copy_rect(p_dst, This->base.info.format, This->stride, dst_box.x, dst_box.y, dst_box.width, dst_box.height, p_src, transfer->stride, src_box.x, src_box.y); pipe->transfer_unmap(pipe, transfer); } else { p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0); p_src = NineSurface9_GetSystemMemPointer(From, 0, 0); util_copy_rect(p_dst, This->base.info.format, This->stride, dst_box.x, dst_box.y, dst_box.width, dst_box.height, p_src, From->stride, src_box.x, src_box.y); } if (This->base.pool == D3DPOOL_DEFAULT) NineSurface9_MarkContainerDirty(This); if (!r_dst && This->base.resource) NineSurface9_AddDirtyRect(This, &dst_box); return D3D_OK; }
/** * Fallback function for pipe->surface_copy(). * Note: (X,Y)=(0,0) is always the upper-left corner. * if do_flip, flip the image vertically on its way from src rect to dst rect. * XXX should probably put this in new u_surface.c file... */ void util_surface_copy(struct pipe_context *pipe, boolean do_flip, struct pipe_surface *dst, unsigned dst_x, unsigned dst_y, struct pipe_surface *src, unsigned src_x, unsigned src_y, unsigned w, unsigned h) { struct pipe_screen *screen = pipe->screen; struct pipe_transfer *src_trans, *dst_trans; void *dst_map; const void *src_map; enum pipe_format src_format, dst_format; assert(src->texture && dst->texture); if (!src->texture || !dst->texture) return; src_format = src->texture->format; dst_format = dst->texture->format; src_trans = screen->get_tex_transfer(screen, src->texture, src->face, src->level, src->zslice, PIPE_TRANSFER_READ, src_x, src_y, w, h); dst_trans = screen->get_tex_transfer(screen, dst->texture, dst->face, dst->level, dst->zslice, PIPE_TRANSFER_WRITE, dst_x, dst_y, w, h); assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); src_map = pipe->screen->transfer_map(screen, src_trans); dst_map = pipe->screen->transfer_map(screen, dst_trans); assert(src_map); assert(dst_map); if (src_map && dst_map) { /* If do_flip, invert src_y position and pass negative src stride */ util_copy_rect(dst_map, dst_format, dst_trans->stride, 0, 0, w, h, src_map, do_flip ? -(int) src_trans->stride : src_trans->stride, 0, do_flip ? h - 1 : 0); } pipe->screen->transfer_unmap(pipe->screen, src_trans); pipe->screen->transfer_unmap(pipe->screen, dst_trans); screen->tex_transfer_destroy(src_trans); screen->tex_transfer_destroy(dst_trans); }
/** * Copy image data from a VdpVideoSurface to application memory in a specified * YCbCr format. */ VdpStatus vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface, VdpYCbCrFormat destination_ycbcr_format, void *const *destination_data, uint32_t const *destination_pitches) { vlVdpSurface *vlsurface; struct pipe_context *pipe; enum pipe_format format; struct pipe_sampler_view **sampler_views; unsigned i, j; vlsurface = vlGetDataHTAB(surface); if (!vlsurface) return VDP_STATUS_INVALID_HANDLE; pipe = vlsurface->device->context; if (!pipe) return VDP_STATUS_INVALID_HANDLE; format = FormatYCBCRToPipe(destination_ycbcr_format); if (format == PIPE_FORMAT_NONE) return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; if (vlsurface->video_buffer == NULL || format != vlsurface->video_buffer->buffer_format) return VDP_STATUS_NO_IMPLEMENTATION; /* TODO We don't support conversion (yet) */ pipe_mutex_lock(vlsurface->device->mutex); sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer); if (!sampler_views) { pipe_mutex_unlock(vlsurface->device->mutex); return VDP_STATUS_RESOURCES; } for (i = 0; i < 3; ++i) { unsigned width, height; struct pipe_sampler_view *sv = sampler_views[i]; if (!sv) continue; vlVdpVideoSurfaceSize(vlsurface, i, &width, &height); for (j = 0; j < sv->texture->array_size; ++j) { struct pipe_box box = { 0, 0, j, width, height, 1 }; struct pipe_transfer *transfer; uint8_t *map; map = pipe->transfer_map(pipe, sv->texture, 0, PIPE_TRANSFER_READ, &box, &transfer); if (!map) { pipe_mutex_unlock(vlsurface->device->mutex); return VDP_STATUS_RESOURCES; } util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format, destination_pitches[i] * sv->texture->array_size, 0, 0, box.width, box.height, map, transfer->stride, 0, 0); pipe_transfer_unmap(pipe, transfer); } } pipe_mutex_unlock(vlsurface->device->mutex); return VDP_STATUS_OK; }
/** * Copy image data from a VdpVideoSurface to application memory in a specified * YCbCr format. */ VdpStatus vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface, VdpYCbCrFormat destination_ycbcr_format, void *const *destination_data, uint32_t const *destination_pitches) { vlVdpSurface *vlsurface; struct pipe_context *pipe; enum pipe_format format, buffer_format; struct pipe_sampler_view **sampler_views; enum getbits_conversion conversion = CONVERSION_NONE; unsigned i, j; vlsurface = vlGetDataHTAB(surface); if (!vlsurface) return VDP_STATUS_INVALID_HANDLE; pipe = vlsurface->device->context; if (!pipe) return VDP_STATUS_INVALID_HANDLE; if (!destination_data || !destination_pitches) return VDP_STATUS_INVALID_POINTER; format = FormatYCBCRToPipe(destination_ycbcr_format); if (format == PIPE_FORMAT_NONE) return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; if (vlsurface->video_buffer == NULL) return VDP_STATUS_INVALID_VALUE; buffer_format = vlsurface->video_buffer->buffer_format; if (format != buffer_format) { if (format == PIPE_FORMAT_YV12 && buffer_format == PIPE_FORMAT_NV12) conversion = CONVERSION_NV12_TO_YV12; else if (format == PIPE_FORMAT_NV12 && buffer_format == PIPE_FORMAT_YV12) conversion = CONVERSION_YV12_TO_NV12; else if ((format == PIPE_FORMAT_YUYV && buffer_format == PIPE_FORMAT_UYVY) || (format == PIPE_FORMAT_UYVY && buffer_format == PIPE_FORMAT_YUYV)) conversion = CONVERSION_SWAP_YUYV_UYVY; else return VDP_STATUS_NO_IMPLEMENTATION; } pipe_mutex_lock(vlsurface->device->mutex); sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer); if (!sampler_views) { pipe_mutex_unlock(vlsurface->device->mutex); return VDP_STATUS_RESOURCES; } for (i = 0; i < 3; ++i) { unsigned width, height; struct pipe_sampler_view *sv = sampler_views[i]; if (!sv) continue; vlVdpVideoSurfaceSize(vlsurface, i, &width, &height); for (j = 0; j < sv->texture->array_size; ++j) { struct pipe_box box = { 0, 0, j, width, height, 1 }; struct pipe_transfer *transfer; uint8_t *map; map = pipe->transfer_map(pipe, sv->texture, 0, PIPE_TRANSFER_READ, &box, &transfer); if (!map) { pipe_mutex_unlock(vlsurface->device->mutex); return VDP_STATUS_RESOURCES; } if (conversion == CONVERSION_NV12_TO_YV12 && i == 1) { u_copy_nv12_to_yv12(destination_data, destination_pitches, i, j, transfer->stride, sv->texture->array_size, map, box.width, box.height); } else if (conversion == CONVERSION_YV12_TO_NV12 && i > 0) { u_copy_yv12_to_nv12(destination_data, destination_pitches, i, j, transfer->stride, sv->texture->array_size, map, box.width, box.height); } else if (conversion == CONVERSION_SWAP_YUYV_UYVY) { u_copy_swap422_packed(destination_data, destination_pitches, i, j, transfer->stride, sv->texture->array_size, map, box.width, box.height); } else { util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format, destination_pitches[i] * sv->texture->array_size, 0, 0, box.width, box.height, map, transfer->stride, 0, 0); } pipe_transfer_unmap(pipe, transfer); } } pipe_mutex_unlock(vlsurface->device->mutex); return VDP_STATUS_OK; }
static void lp_resource_copy(struct pipe_context *pipe, struct pipe_resource *dst, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, unsigned src_level, const struct pipe_box *src_box) { /* XXX this used to ignore srcz/dstz * assume it works the same for cube and 3d */ struct llvmpipe_resource *src_tex = llvmpipe_resource(src); struct llvmpipe_resource *dst_tex = llvmpipe_resource(dst); const enum pipe_format format = src_tex->base.format; unsigned width = src_box->width; unsigned height = src_box->height; assert(src_box->depth == 1); /* Fallback for buffers. */ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); return; } llvmpipe_flush_resource(pipe, dst, dst_level, dstz, FALSE, /* read_only */ TRUE, /* cpu_access */ FALSE, /* do_not_block */ "blit dest"); llvmpipe_flush_resource(pipe, src, src_level, src_box->z, TRUE, /* read_only */ TRUE, /* cpu_access */ FALSE, /* do_not_block */ "blit src"); /* printf("surface copy from %u lvl %u to %u lvl %u: %u,%u,%u to %u,%u,%u %u x %u x %u\n", src_tex->id, src_level, dst_tex->id, dst_level, src_box->x, src_box->y, src_box->z, dstx, dsty, dstz, src_box->width, src_box->height, src_box->depth); */ /* set src tiles to linear layout */ { unsigned tx, ty, tw, th; unsigned x, y; adjust_to_tile_bounds(src_box->x, src_box->y, width, height, &tx, &ty, &tw, &th); for (y = 0; y < th; y += TILE_SIZE) { for (x = 0; x < tw; x += TILE_SIZE) { (void) llvmpipe_get_texture_tile_linear(src_tex, src_box->z, src_level, LP_TEX_USAGE_READ, tx + x, ty + y); } } } /* set dst tiles to linear layout */ { unsigned tx, ty, tw, th; unsigned x, y; enum lp_texture_usage usage; adjust_to_tile_bounds(dstx, dsty, width, height, &tx, &ty, &tw, &th); for (y = 0; y < th; y += TILE_SIZE) { boolean contained_y = ty + y >= dsty && ty + y + TILE_SIZE <= dsty + height ? TRUE : FALSE; for (x = 0; x < tw; x += TILE_SIZE) { boolean contained_x = tx + x >= dstx && tx + x + TILE_SIZE <= dstx + width ? TRUE : FALSE; /* * Set the usage mode to WRITE_ALL for the tiles which are * completely contained by the dest rectangle. */ if (contained_y && contained_x) usage = LP_TEX_USAGE_WRITE_ALL; else usage = LP_TEX_USAGE_READ_WRITE; (void) llvmpipe_get_texture_tile_linear(dst_tex, dstz, dst_level, usage, tx + x, ty + y); } } } /* copy */ { const ubyte *src_linear_ptr = llvmpipe_get_texture_image_address(src_tex, src_box->z, src_level, LP_TEX_LAYOUT_LINEAR); ubyte *dst_linear_ptr = llvmpipe_get_texture_image_address(dst_tex, dstz, dst_level, LP_TEX_LAYOUT_LINEAR); if (dst_linear_ptr && src_linear_ptr) { util_copy_rect(dst_linear_ptr, format, llvmpipe_resource_stride(&dst_tex->base, dst_level), dstx, dsty, width, height, src_linear_ptr, llvmpipe_resource_stride(&src_tex->base, src_level), src_box->x, src_box->y); } } }
void util_format_translate(enum pipe_format dst_format, void *dst, unsigned dst_stride, unsigned dst_x, unsigned dst_y, enum pipe_format src_format, const void *src, unsigned src_stride, unsigned src_x, unsigned src_y, unsigned width, unsigned height) { const struct util_format_description *dst_format_desc; const struct util_format_description *src_format_desc; uint8_t *dst_row; const uint8_t *src_row; unsigned x_step, y_step; unsigned dst_step; unsigned src_step; dst_format_desc = util_format_description(dst_format); src_format_desc = util_format_description(src_format); if (util_is_format_compatible(src_format_desc, dst_format_desc)) { /* * Trivial case. */ util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y, width, height, src, (int)src_stride, src_x, src_y); return; } assert(dst_x % dst_format_desc->block.width == 0); assert(dst_y % dst_format_desc->block.height == 0); assert(src_x % src_format_desc->block.width == 0); assert(src_y % src_format_desc->block.height == 0); dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8); src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8); /* * This works because all pixel formats have pixel blocks with power of two * sizes. */ y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height); x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width); assert(y_step % dst_format_desc->block.height == 0); assert(y_step % src_format_desc->block.height == 0); dst_step = y_step / dst_format_desc->block.height * dst_stride; src_step = y_step / src_format_desc->block.height * src_stride; /* * TODO: double formats will loose precision * TODO: Add a special case for formats that are mere swizzles of each other */ if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS || dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { float *tmp_z = NULL; uint8_t *tmp_s = NULL; assert(x_step == 1); assert(y_step == 1); if (src_format_desc->unpack_z_float && dst_format_desc->pack_z_float) { tmp_z = MALLOC(width * sizeof *tmp_z); } if (src_format_desc->unpack_s_8uint && dst_format_desc->pack_s_8uint) { tmp_s = MALLOC(width * sizeof *tmp_s); } while (height--) { if (tmp_z) { src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1); dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1); } if (tmp_s) { src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1); dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1); } dst_row += dst_step; src_row += src_step; } FREE(tmp_s); FREE(tmp_z); return; } if (util_format_fits_8unorm(src_format_desc) || util_format_fits_8unorm(dst_format_desc)) { unsigned tmp_stride; uint8_t *tmp_row; tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; tmp_row = MALLOC(y_step * tmp_stride); if (!tmp_row) return; while (height >= y_step) { src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step); dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); dst_row += dst_step; src_row += src_step; height -= y_step; } if (height) { src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height); dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height); } FREE(tmp_row); } else { unsigned tmp_stride; float *tmp_row; tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; tmp_row = MALLOC(y_step * tmp_stride); if (!tmp_row) return; while (height >= y_step) { src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step); dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); dst_row += dst_step; src_row += src_step; height -= y_step; } if (height) { src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height); dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height); } FREE(tmp_row); } }
VAStatus vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, unsigned int width, unsigned int height, VAImageID image) { vlVaDriver *drv; vlVaSurface *surf; vlVaBuffer *img_buf; VAImage *vaimage; struct pipe_sampler_view **views; enum pipe_format format; bool convert = false; void *data[3]; unsigned pitches[3], i, j; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; drv = VL_VA_DRIVER(ctx); pipe_mutex_lock(drv->mutex); surf = handle_table_get(drv->htab, surface); if (!surf || !surf->buffer) { pipe_mutex_unlock(drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; } vaimage = handle_table_get(drv->htab, image); if (!vaimage) { pipe_mutex_unlock(drv->mutex); return VA_STATUS_ERROR_INVALID_IMAGE; } img_buf = handle_table_get(drv->htab, vaimage->buf); if (!img_buf) { pipe_mutex_unlock(drv->mutex); return VA_STATUS_ERROR_INVALID_BUFFER; } format = VaFourccToPipeFormat(vaimage->format.fourcc); if (format == PIPE_FORMAT_NONE) { pipe_mutex_unlock(drv->mutex); return VA_STATUS_ERROR_OPERATION_FAILED; } if (format != surf->buffer->buffer_format) { /* support NV12 to YV12 and IYUV conversion now only */ if ((format == PIPE_FORMAT_YV12 && surf->buffer->buffer_format == PIPE_FORMAT_NV12) || (format == PIPE_FORMAT_IYUV && surf->buffer->buffer_format == PIPE_FORMAT_NV12)) convert = true; else { pipe_mutex_unlock(drv->mutex); return VA_STATUS_ERROR_OPERATION_FAILED; } } views = surf->buffer->get_sampler_view_planes(surf->buffer); if (!views) { pipe_mutex_unlock(drv->mutex); return VA_STATUS_ERROR_OPERATION_FAILED; } for (i = 0; i < vaimage->num_planes; i++) { data[i] = img_buf->data + vaimage->offsets[i]; pitches[i] = vaimage->pitches[i]; } if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) { void *tmp_d; unsigned tmp_p; tmp_d = data[1]; data[1] = data[2]; data[2] = tmp_d; tmp_p = pitches[1]; pitches[1] = pitches[2]; pitches[2] = tmp_p; } for (i = 0; i < vaimage->num_planes; i++) { unsigned width, height; if (!views[i]) continue; vlVaVideoSurfaceSize(surf, i, &width, &height); for (j = 0; j < views[i]->texture->array_size; ++j) { struct pipe_box box = {0, 0, j, width, height, 1}; struct pipe_transfer *transfer; uint8_t *map; map = drv->pipe->transfer_map(drv->pipe, views[i]->texture, 0, PIPE_TRANSFER_READ, &box, &transfer); if (!map) { pipe_mutex_unlock(drv->mutex); return VA_STATUS_ERROR_OPERATION_FAILED; } if (i == 1 && convert) { u_copy_nv12_to_yv12(data, pitches, i, j, transfer->stride, views[i]->texture->array_size, map, box.width, box.height); } else { util_copy_rect(data[i] + pitches[i] * j, views[i]->texture->format, pitches[i] * views[i]->texture->array_size, 0, 0, box.width, box.height, map, transfer->stride, 0, 0); } pipe_transfer_unmap(drv->pipe, transfer); } } pipe_mutex_unlock(drv->mutex); return VA_STATUS_SUCCESS; }
static void lp_resource_copy(struct pipe_context *pipe, struct pipe_resource *dst, struct pipe_subresource subdst, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, struct pipe_subresource subsrc, unsigned srcx, unsigned srcy, unsigned srcz, unsigned width, unsigned height) { /* XXX what about the dstz/srcz parameters - zslice wasn't used... */ struct llvmpipe_resource *src_tex = llvmpipe_resource(src); struct llvmpipe_resource *dst_tex = llvmpipe_resource(dst); const enum pipe_format format = src_tex->base.format; llvmpipe_flush_resource(pipe, dst, subdst.face, subdst.level, 0, /* flush_flags */ FALSE, /* read_only */ TRUE, /* cpu_access */ FALSE, /* do_not_block */ "blit dest"); llvmpipe_flush_resource(pipe, src, subsrc.face, subsrc.level, 0, /* flush_flags */ TRUE, /* read_only */ TRUE, /* cpu_access */ FALSE, /* do_not_block */ "blit src"); /* printf("surface copy from %u to %u: %u,%u to %u,%u %u x %u\n", src_tex->id, dst_tex->id, srcx, srcy, dstx, dsty, width, height); */ /* set src tiles to linear layout */ { unsigned tx, ty, tw, th; unsigned x, y; adjust_to_tile_bounds(srcx, srcy, width, height, &tx, &ty, &tw, &th); for (y = 0; y < th; y += TILE_SIZE) { for (x = 0; x < tw; x += TILE_SIZE) { (void) llvmpipe_get_texture_tile_linear(src_tex, subsrc.face, subsrc.level, LP_TEX_USAGE_READ, tx + x, ty + y); } } } /* set dst tiles to linear layout */ { unsigned tx, ty, tw, th; unsigned x, y; enum lp_texture_usage usage; adjust_to_tile_bounds(dstx, dsty, width, height, &tx, &ty, &tw, &th); for (y = 0; y < th; y += TILE_SIZE) { boolean contained_y = ty + y >= dsty && ty + y + TILE_SIZE <= dsty + height ? TRUE : FALSE; for (x = 0; x < tw; x += TILE_SIZE) { boolean contained_x = tx + x >= dstx && tx + x + TILE_SIZE <= dstx + width ? TRUE : FALSE; /* * Set the usage mode to WRITE_ALL for the tiles which are * completely contained by the dest rectangle. */ if (contained_y && contained_x) usage = LP_TEX_USAGE_WRITE_ALL; else usage = LP_TEX_USAGE_READ_WRITE; (void) llvmpipe_get_texture_tile_linear(dst_tex, subdst.face, subdst.level, usage, tx + x, ty + y); } } } /* copy */ { const ubyte *src_linear_ptr = llvmpipe_get_texture_image_address(src_tex, subsrc.face, subsrc.level, LP_TEX_LAYOUT_LINEAR); ubyte *dst_linear_ptr = llvmpipe_get_texture_image_address(dst_tex, subdst.face, subdst.level, LP_TEX_LAYOUT_LINEAR); if (dst_linear_ptr && src_linear_ptr) { util_copy_rect(dst_linear_ptr, format, llvmpipe_resource_stride(&dst_tex->base, subdst.level), dstx, dsty, width, height, src_linear_ptr, llvmpipe_resource_stride(&src_tex->base, subsrc.level), srcx, srcy); } } }
/** * Fallback function for pipe->resource_copy_region(). * Note: (X,Y)=(0,0) is always the upper-left corner. */ void util_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, unsigned dst_level, unsigned dst_x, unsigned dst_y, unsigned dst_z, struct pipe_resource *src, unsigned src_level, const struct pipe_box *src_box) { struct pipe_transfer *src_trans, *dst_trans; uint8_t *dst_map; const uint8_t *src_map; enum pipe_format src_format, dst_format; struct pipe_box dst_box; int z; assert(src && dst); if (!src || !dst) return; assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); src_format = src->format; dst_format = dst->format; assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); src_map = pipe->transfer_map(pipe, src, src_level, PIPE_TRANSFER_READ, src_box, &src_trans); assert(src_map); if (!src_map) { goto no_src_map; } dst_box.x = dst_x; dst_box.y = dst_y; dst_box.z = dst_z; dst_box.width = src_box->width; dst_box.height = src_box->height; dst_box.depth = src_box->depth; dst_map = pipe->transfer_map(pipe, dst, dst_level, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, &dst_box, &dst_trans); assert(dst_map); if (!dst_map) { goto no_dst_map; } if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { assert(src_box->height == 1); assert(src_box->depth == 1); memcpy(dst_map, src_map, src_box->width); } else { for (z = 0; z < src_box->depth; ++z) { util_copy_rect(dst_map, dst_format, dst_trans->stride, 0, 0, src_box->width, src_box->height, src_map, src_trans->stride, 0, 0); dst_map += dst_trans->layer_stride; src_map += src_trans->layer_stride; } } pipe->transfer_unmap(pipe, dst_trans); no_dst_map: pipe->transfer_unmap(pipe, src_trans); no_src_map: ; }
/** * Fallback function for pipe->resource_copy_region(). * Note: (X,Y)=(0,0) is always the upper-left corner. */ void util_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, unsigned dst_level, unsigned dst_x, unsigned dst_y, unsigned dst_z, struct pipe_resource *src, unsigned src_level, const struct pipe_box *src_box) { struct pipe_transfer *src_trans, *dst_trans; void *dst_map; const void *src_map; enum pipe_format src_format, dst_format; unsigned w = src_box->width; unsigned h = src_box->height; assert(src && dst); assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); if (!src || !dst) return; src_format = src->format; dst_format = dst->format; src_trans = pipe_get_transfer(pipe, src, src_level, src_box->z, PIPE_TRANSFER_READ, src_box->x, src_box->y, w, h); dst_trans = pipe_get_transfer(pipe, dst, dst_level, dst_z, PIPE_TRANSFER_WRITE, dst_x, dst_y, w, h); assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); src_map = pipe->transfer_map(pipe, src_trans); dst_map = pipe->transfer_map(pipe, dst_trans); assert(src_map); assert(dst_map); if (src_map && dst_map) { if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { memcpy(dst_map, src_map, w); } else { util_copy_rect(dst_map, dst_format, dst_trans->stride, 0, 0, w, h, src_map, src_trans->stride, 0, 0); } } pipe->transfer_unmap(pipe, src_trans); pipe->transfer_unmap(pipe, dst_trans); pipe->transfer_destroy(pipe, src_trans); pipe->transfer_destroy(pipe, dst_trans); }