/** * Destroy Buffer */ static void MSMDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer) { MSMDRI2BufferPtr buf = MSMBUF(buffer); ScreenPtr pScreen = buf->pPixmap->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); if (--buf->refcnt) return; DEBUG_MSG("pDraw=%p, buffer=%p, attachment=%d", pDraw, buffer, buffer->attachment); /* if drawable has already gone away, 3rd buf is cleaned * up in MSMDRI2DrawableGone() */ if ((buffer->attachment == DRI2BufferBackLeft) && pDraw) { MSMDRI2DrawablePtr pPriv = MSMDRI2GetDrawable(pDraw); if (pPriv->pThirdBuffer) { MSMDRI2DestroyBuffer(pDraw, pPriv->pThirdBuffer); pPriv->pThirdBuffer = NULL; } } pScreen->DestroyPixmap(buf->pPixmap); free(buf); }
static DRI2Buffer2Ptr vivante_dri2_CreateBuffer(DrawablePtr drawable, unsigned int attachment, unsigned int format) { struct vivante_dri2_buffer *buf; struct vivante_pixmap *vpix; ScreenPtr pScreen = drawable->pScreen; PixmapPtr pixmap = NULL; uint32_t name; fprintf(stderr, "%s: %p %u %u\n", __func__, drawable, attachment, format); if (attachment == DRI2BufferFrontLeft) { pixmap = vivante_dri2_get_front_pixmap(drawable); if (!pixmap) { drawable = &pixmap->drawable; pixmap = NULL; } } if (pixmap == NULL) { int width = drawable->width; int height = drawable->height; int depth = format ? format : drawable->depth; pixmap = pScreen->CreatePixmap(pScreen, width, height, depth, 0); if (!pixmap) goto err; } vpix = vivante_get_pixmap_priv(pixmap); if (!vpix) goto err; buf = calloc(1, sizeof *buf); if (!buf) goto err; if (!vpix->bo || drm_armada_bo_flink(vpix->bo, &name)) { free(buf); goto err; } buf->dri2.attachment = attachment; buf->dri2.name = name; buf->dri2.pitch = pixmap->devKind; buf->dri2.cpp = pixmap->drawable.bitsPerPixel / 8; buf->dri2.flags = 0; buf->dri2.format = format; buf->dri2.driverPrivate = buf; buf->pixmap = pixmap; buf->ref = 1; return &buf->dri2; err: if (pixmap) pScreen->DestroyPixmap(pixmap); return NULL; }
Bool exaDestroyPixmap_classic(PixmapPtr pPixmap) { ScreenPtr pScreen = pPixmap->drawable.pScreen; ExaScreenPriv(pScreen); Bool ret; if (pPixmap->refcnt == 1) { ExaPixmapPriv(pPixmap); exaDestroyPixmap(pPixmap); if (pExaPixmap->area) { DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", (void *) pPixmap->drawable.id, ExaGetPixmapPriv(pPixmap)->area->offset, pPixmap->drawable.width, pPixmap->drawable.height)); /* Free the offscreen area */ exaOffscreenFree(pPixmap->drawable.pScreen, pExaPixmap->area); pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; pPixmap->devKind = pExaPixmap->sys_pitch; } RegionUninit(&pExaPixmap->validSys); RegionUninit(&pExaPixmap->validFB); } swap(pExaScr, pScreen, DestroyPixmap); ret = pScreen->DestroyPixmap(pPixmap); swap(pExaScr, pScreen, DestroyPixmap); return ret; }
Bool rdpDestroyPixmap(PixmapPtr pPixmap) { Bool rv; ScreenPtr pScreen; rdpPixmapRec *priv; LLOGLN(10, ("rdpDestroyPixmap:")); priv = GETPIXPRIV(pPixmap); LLOGLN(10, ("status %d refcnt %d", priv->status, pPixmap->refcnt)); if (pPixmap->refcnt < 2) { if (XRDP_IS_OS(priv)) { rdpup_remove_os_bitmap(priv->rdpindex); rdpup_delete_os_surface(priv->rdpindex); draw_item_remove_all(priv); } } pScreen = pPixmap->drawable.pScreen; pScreen->DestroyPixmap = g_rdpScreen.DestroyPixmap; rv = pScreen->DestroyPixmap(pPixmap); pScreen->DestroyPixmap = rdpDestroyPixmap; return rv; }
static void crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) { ScreenPtr pScreen = rotate_pixmap->drawable.pScreen; pScreen->DestroyPixmap(rotate_pixmap); }
void nouveau_dri2_destroy_buffer2(ScreenPtr pScreen, DrawablePtr pDraw, DRI2BufferPtr buf) { struct nouveau_dri2_buffer *nvbuf; nvbuf = nouveau_dri2_buffer(buf); if (!nvbuf) return; if (nvbuf->ppix) pScreen->DestroyPixmap(nvbuf->ppix); free(nvbuf); }
Bool rdpDestroyPixmap(PixmapPtr pPixmap) { Bool rv; ScreenPtr pScreen; rdpPtr dev; LLOGLN(10, ("rdpDestroyPixmap: refcnt %d", pPixmap->refcnt)); pScreen = pPixmap->drawable.pScreen; dev = rdpGetDevFromScreen(pScreen); pScreen->DestroyPixmap = dev->DestroyPixmap; rv = pScreen->DestroyPixmap(pPixmap); pScreen->DestroyPixmap = rdpDestroyPixmap; return rv; }
static Bool shadowCloseScreen(int i, ScreenPtr pScreen) { shadowBuf(pScreen); unwrap(pBuf, pScreen, GetImage); unwrap(pBuf, pScreen, CloseScreen); shadowRemove(pScreen, pBuf->pPixmap); DamageDestroy(pBuf->pDamage); #ifdef BACKWARDS_COMPATIBILITY REGION_UNINIT(pScreen, &pBuf->damage); /* bc */ #endif if (pBuf->pPixmap) pScreen->DestroyPixmap(pBuf->pPixmap); xfree(pBuf); return pScreen->CloseScreen(i, pScreen); }
static Bool shadowCloseScreen(ScreenPtr pScreen) { shadowBuf(pScreen); unwrap(pBuf, pScreen, GetImage); unwrap(pBuf, pScreen, CloseScreen); shadowRemove(pScreen, pBuf->pPixmap); DamageDestroy(pBuf->pDamage); #ifdef BACKWARDS_COMPATIBILITY RegionUninit(&pBuf->damage); /* bc */ #endif if (pBuf->pPixmap) pScreen->DestroyPixmap(pBuf->pPixmap); free(pBuf); return pScreen->CloseScreen(pScreen); }
Bool shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window) { PixmapPtr pPixmap; pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height, pScreen->rootDepth); if (!pPixmap) return FALSE; if (!shadowSetup(pScreen)) { pScreen->DestroyPixmap(pPixmap); return FALSE; } shadowAdd(pScreen, pPixmap, update, window, NULL, SHADOW_ROTATE_0, 0); return TRUE; }
static void vivante_dri2_DestroyBuffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer) { if (buffer) { struct vivante_dri2_buffer *buf = buffer->driverPrivate; ScreenPtr screen; /* This should never happen... due to how we allocate the private */ assert(buf != NULL); if (--buf->ref != 0) return; screen = buf->pixmap->drawable.pScreen; screen->DestroyPixmap(buf->pixmap); free(buf); } }
static Bool destroy_buffer(DrawablePtr pDraw, struct ARMSOCDRI2BufferRec *buf) { ScreenPtr pScreen = buf->pPixmaps[0]->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); DRI2BufferPtr buffer = DRIBUF(buf); int numBuffers, i; if (--buf->refcnt > 0) return FALSE; if (buffer->attachment == DRI2BufferBackLeft) { assert(pARMSOC->driNumBufs > 1); numBuffers = pARMSOC->driNumBufs-1; } else numBuffers = 1; for (i = 0; i < numBuffers && buf->pPixmaps[i] != NULL; i++) { ARMSOCDeregisterExternalAccess(buf->pPixmaps[i]); pScreen->DestroyPixmap(buf->pPixmaps[i]); } return TRUE; }
/** * exaCreatePixmap() creates a new pixmap. * * If width and height are 0, this won't be a full-fledged pixmap and it will * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because * ModifyPixmapHeader() would break migration. These types of pixmaps are used * for scratch pixmaps, or to represent the visible screen. */ PixmapPtr exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint) { PixmapPtr pPixmap; ExaPixmapPrivPtr pExaPixmap; BoxRec box; int bpp; ExaScreenPriv(pScreen); if (w > 32767 || h > 32767) return NullPixmap; swap(pExaScr, pScreen, CreatePixmap); pPixmap = pScreen->CreatePixmap(pScreen, w, h, depth, usage_hint); swap(pExaScr, pScreen, CreatePixmap); if (!pPixmap) return NULL; pExaPixmap = ExaGetPixmapPriv(pPixmap); pExaPixmap->driverPriv = NULL; bpp = pPixmap->drawable.bitsPerPixel; pExaPixmap->driverPriv = NULL; /* Scratch pixmaps may have w/h equal to zero, and may not be * migrated. */ if (!w || !h) pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; else pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; pExaPixmap->sys_pitch = pPixmap->devKind; pPixmap->devPrivate.ptr = NULL; pExaPixmap->use_gpu_copy = FALSE; pExaPixmap->fb_ptr = NULL; exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; if (pExaPixmap->fb_pitch > 131071) { swap(pExaScr, pScreen, DestroyPixmap); pScreen->DestroyPixmap(pPixmap); swap(pExaScr, pScreen, DestroyPixmap); return NULL; } /* Set up damage tracking */ pExaPixmap->pDamage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, pScreen, pPixmap); if (pExaPixmap->pDamage == NULL) { swap(pExaScr, pScreen, DestroyPixmap); pScreen->DestroyPixmap(pPixmap); swap(pExaScr, pScreen, DestroyPixmap); return NULL; } DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage); /* This ensures that pending damage reflects the current operation. */ /* This is used by exa to optimize migration. */ DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE); pExaPixmap->area = NULL; /* We set the initial pixmap as completely valid for a simple reason. * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which * could form single pixel rects as part of a region. Setting the complete region * as valid is a natural defragmentation of the region. */ box.x1 = 0; box.y1 = 0; box.x2 = w; box.y2 = h; RegionInit(&pExaPixmap->validSys, &box, 0); RegionInit(&pExaPixmap->validFB, &box, 0); exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); /* During a fallback we must prepare access. */ if (pExaScr->fallback_counter) exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); return pPixmap; }
PixmapPtr glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen, int fd, CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp) { #ifdef GLAMOR_HAS_GBM ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; struct gbm_bo *bo; EGLImageKHR image; PixmapPtr pixmap; Bool ret = FALSE; EGLint attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, EGL_DMA_BUF_PLANE0_FD_EXT, 0, EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, 0, EGL_NONE }; glamor_egl = glamor_egl_get_screen_private(scrn); if (!glamor_egl->dri3_capable) return NULL; if (bpp != 32 || !(depth == 24 || depth == 32) || width == 0 || height == 0) return NULL; attribs[1] = width; attribs[3] = height; attribs[7] = fd; attribs[11] = stride; image = eglCreateImageKHR(glamor_egl->display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); if (image == EGL_NO_IMAGE_KHR) return NULL; /* EGL_EXT_image_dma_buf_import can impose restrictions on the * usage of the image. Use gbm_bo to bypass the limitations. */ bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); eglDestroyImageKHR(glamor_egl->display, image); if (!bo) return NULL; pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL); ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); gbm_bo_destroy(bo); if (ret) return pixmap; else { screen->DestroyPixmap(pixmap); return NULL; } #else return NULL; #endif }
void I915DisplayVideoTextured(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, int id, RegionPtr dstRegion, short width, short height, int video_pitch, int video_pitch2, short src_w, short src_h, short drw_w, short drw_h, PixmapPtr pixmap) { intel_screen_private *intel = intel_get_screen_private(scrn); uint32_t format, ms3, s5, tiling; BoxPtr pbox = REGION_RECTS(dstRegion); int nbox_total = REGION_NUM_RECTS(dstRegion); int nbox_this_time; int dxo, dyo, pix_xoff, pix_yoff; PixmapPtr target; #if 0 ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height, video_pitch); #endif dxo = dstRegion->extents.x1; dyo = dstRegion->extents.y1; if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048 || !intel_uxa_check_pitch_3d(pixmap)) { ScreenPtr screen = pixmap->drawable.pScreen; target = screen->CreatePixmap(screen, dstRegion->extents.x2 - dxo, dstRegion->extents.y2 - dyo, pixmap->drawable.depth, CREATE_PIXMAP_USAGE_SCRATCH); if (target == NULL) return; if (intel_uxa_get_pixmap_bo(target) == NULL) { screen->DestroyPixmap(target); return; } pix_xoff = -dxo; pix_yoff = -dyo; } else { target = pixmap; /* Set up the offset for translating from the given region * (in screen coordinates) to the backing pixmap. */ #ifdef COMPOSITE pix_xoff = -target->screen_x + target->drawable.x; pix_yoff = -target->screen_y + target->drawable.y; #else pix_xoff = 0; pix_yoff = 0; #endif } #define BYTES_FOR_BOXES(n) ((200 + (n) * 20) * 4) #define BOXES_IN_BYTES(s) ((((s)/4) - 200) / 20) #define BATCH_BYTES(p) ((p)->batch_bo->size - 16) while (nbox_total) { nbox_this_time = nbox_total; if (BYTES_FOR_BOXES(nbox_this_time) > BATCH_BYTES(intel)) nbox_this_time = BOXES_IN_BYTES(BATCH_BYTES(intel)); nbox_total -= nbox_this_time; intel_batch_start_atomic(scrn, 200 + 20 * nbox_this_time); IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_VIDEO; /* draw rect -- just clipping */ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); OUT_BATCH(DRAW_DITHER_OFS_X(pixmap->drawable.x & 3) | DRAW_DITHER_OFS_Y(pixmap->drawable.y & 3)); OUT_BATCH(0x00000000); /* ymin, xmin */ /* ymax, xmax */ OUT_BATCH((target->drawable.width - 1) | (target->drawable.height - 1) << 16); OUT_BATCH(0x00000000); /* yorigin, xorigin */ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(5) | I1_LOAD_S(6) | 2); OUT_BATCH(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) | S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT)); s5 = 0x0; if (intel->cpp == 2) s5 |= S5_COLOR_DITHER_ENABLE; OUT_BATCH(s5); /* S5 - enable bits */ OUT_BATCH((2 << S6_DEPTH_TEST_FUNC_SHIFT) | (2 << S6_CBUF_SRC_BLEND_FACT_SHIFT) | (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE | (2 << S6_TRISTRIP_PV_SHIFT)); OUT_BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD); OUT_BATCH(0x00000000); OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); if (intel->cpp == 2) format = COLR_BUF_RGB565; else format = COLR_BUF_ARGB8888 | DEPTH_FRMT_24_FIXED_8_OTHER; OUT_BATCH(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8) | format); /* front buffer, pitch, offset */ if (intel_uxa_pixmap_tiled(target)) { tiling = BUF_3D_TILED_SURFACE; if (intel_uxa_get_pixmap_private(target)->tiling == I915_TILING_Y) tiling |= BUF_3D_TILE_WALK_Y; } else tiling = 0; OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling | BUF_3D_PITCH(intel_pixmap_pitch(target))); OUT_RELOC_PIXMAP(target, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); if (!is_planar_fourcc(id)) { FS_LOCALS(); OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | 4); OUT_BATCH(0x0000001); /* constant 0 */ /* constant 0: brightness/contrast */ OUT_BATCH_F(adaptor_priv->brightness / 128.0); OUT_BATCH_F(adaptor_priv->contrast / 255.0); OUT_BATCH_F(0.0); OUT_BATCH_F(0.0); OUT_BATCH(_3DSTATE_SAMPLER_STATE | 3); OUT_BATCH(0x00000001); OUT_BATCH(SS2_COLORSPACE_CONVERSION | (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) | (0 << SS3_TEXTUREMAP_INDEX_SHIFT) | SS3_NORMALIZED_COORDS); OUT_BATCH(0x00000000); OUT_BATCH(_3DSTATE_MAP_STATE | 3); OUT_BATCH(0x00000001); /* texture map #1 */ if (adaptor_priv->buf) OUT_RELOC(adaptor_priv->buf, I915_GEM_DOMAIN_SAMPLER, 0, adaptor_priv->YBufOffset); else OUT_BATCH(adaptor_priv->YBufOffset); ms3 = MAPSURF_422; switch (id) { case FOURCC_YUY2: ms3 |= MT_422_YCRCB_NORMAL; break; case FOURCC_UYVY: ms3 |= MT_422_YCRCB_SWAPY; break; } ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); FS_BEGIN(); i915_fs_dcl(FS_S0); i915_fs_dcl(FS_T0); i915_fs_texld(FS_OC, FS_S0, FS_T0); if (adaptor_priv->brightness != 0) { i915_fs_add(FS_OC, i915_fs_operand_reg(FS_OC), i915_fs_operand(FS_C0, X, X, X, ZERO)); } FS_END(); } else { FS_LOCALS(); /* For the planar formats, we set up three samplers -- * one for each plane, in a Y8 format. Because I * couldn't get the special PLANAR_TO_PACKED * shader setup to work, I did the manual pixel shader: * * y' = y - .0625 * u' = u - .5 * v' = v - .5; * * r = 1.1643 * y' + 0.0 * u' + 1.5958 * v' * g = 1.1643 * y' - 0.39173 * u' - 0.81290 * v' * b = 1.1643 * y' + 2.017 * u' + 0.0 * v' * * register assignment: * r0 = (y',u',v',0) * r1 = (y,y,y,y) * r2 = (u,u,u,u) * r3 = (v,v,v,v) * OC = (r,g,b,1) */ OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | (22 - 2)); OUT_BATCH(0x000001f); /* constants 0-4 */ /* constant 0: normalization offsets */ OUT_BATCH_F(-0.0625); OUT_BATCH_F(-0.5); OUT_BATCH_F(-0.5); OUT_BATCH_F(0.0); /* constant 1: r coefficients */ OUT_BATCH_F(1.1643); OUT_BATCH_F(0.0); OUT_BATCH_F(1.5958); OUT_BATCH_F(0.0); /* constant 2: g coefficients */ OUT_BATCH_F(1.1643); OUT_BATCH_F(-0.39173); OUT_BATCH_F(-0.81290); OUT_BATCH_F(0.0); /* constant 3: b coefficients */ OUT_BATCH_F(1.1643); OUT_BATCH_F(2.017); OUT_BATCH_F(0.0); OUT_BATCH_F(0.0); /* constant 4: brightness/contrast */ OUT_BATCH_F(adaptor_priv->brightness / 128.0); OUT_BATCH_F(adaptor_priv->contrast / 255.0); OUT_BATCH_F(0.0); OUT_BATCH_F(0.0); OUT_BATCH(_3DSTATE_SAMPLER_STATE | 9); OUT_BATCH(0x00000007); /* sampler 0 */ OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) | (0 << SS3_TEXTUREMAP_INDEX_SHIFT) | SS3_NORMALIZED_COORDS); OUT_BATCH(0x00000000); /* sampler 1 */ OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) | (1 << SS3_TEXTUREMAP_INDEX_SHIFT) | SS3_NORMALIZED_COORDS); OUT_BATCH(0x00000000); /* sampler 2 */ OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) | (2 << SS3_TEXTUREMAP_INDEX_SHIFT) | SS3_NORMALIZED_COORDS); OUT_BATCH(0x00000000); OUT_BATCH(_3DSTATE_MAP_STATE | 9); OUT_BATCH(0x00000007); if (adaptor_priv->buf) OUT_RELOC(adaptor_priv->buf, I915_GEM_DOMAIN_SAMPLER, 0, adaptor_priv->YBufOffset); else OUT_BATCH(adaptor_priv->YBufOffset); ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); /* check to see if Y has special pitch than normal * double u/v pitch, e.g i915 XvMC hw requires at * least 1K alignment, so Y pitch might * be same as U/V's.*/ if (video_pitch2) OUT_BATCH(((video_pitch2 / 4) - 1) << MS4_PITCH_SHIFT); else OUT_BATCH(((video_pitch * 2 / 4) - 1) << MS4_PITCH_SHIFT); if (adaptor_priv->buf) OUT_RELOC(adaptor_priv->buf, I915_GEM_DOMAIN_SAMPLER, 0, adaptor_priv->UBufOffset); else OUT_BATCH(adaptor_priv->UBufOffset); ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); if (adaptor_priv->buf) OUT_RELOC(adaptor_priv->buf, I915_GEM_DOMAIN_SAMPLER, 0, adaptor_priv->VBufOffset); else OUT_BATCH(adaptor_priv->VBufOffset); ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); FS_BEGIN(); /* Declare samplers */ i915_fs_dcl(FS_S0); /* Y */ i915_fs_dcl(FS_S1); /* U */ i915_fs_dcl(FS_S2); /* V */ i915_fs_dcl(FS_T0); /* normalized coords */ /* Load samplers to temporaries. */ i915_fs_texld(FS_R1, FS_S0, FS_T0); i915_fs_texld(FS_R2, FS_S1, FS_T0); i915_fs_texld(FS_R3, FS_S2, FS_T0); /* Move the sampled YUV data in R[123] to the first * 3 channels of R0. */ i915_fs_mov_masked(FS_R0, MASK_X, i915_fs_operand_reg(FS_R1)); i915_fs_mov_masked(FS_R0, MASK_Y, i915_fs_operand_reg(FS_R2)); i915_fs_mov_masked(FS_R0, MASK_Z, i915_fs_operand_reg(FS_R3)); /* Normalize the YUV data */ i915_fs_add(FS_R0, i915_fs_operand_reg(FS_R0), i915_fs_operand_reg(FS_C0)); /* dot-product the YUV data in R0 by the vectors of * coefficients for calculating R, G, and B, storing * the results in the R, G, or B channels of the output * color. The OC results are implicitly clamped * at the end of the program. */ i915_fs_dp3(FS_OC, MASK_X, i915_fs_operand_reg(FS_R0), i915_fs_operand_reg(FS_C1)); i915_fs_dp3(FS_OC, MASK_Y, i915_fs_operand_reg(FS_R0), i915_fs_operand_reg(FS_C2)); i915_fs_dp3(FS_OC, MASK_Z, i915_fs_operand_reg(FS_R0), i915_fs_operand_reg(FS_C3)); /* Set alpha of the output to 1.0, by wiring W to 1 * and not actually using the source. */ i915_fs_mov_masked(FS_OC, MASK_W, i915_fs_operand_one()); if (adaptor_priv->brightness != 0) { i915_fs_add(FS_OC, i915_fs_operand_reg(FS_OC), i915_fs_operand(FS_C4, X, X, X, ZERO)); } FS_END(); } OUT_BATCH(PRIM3D_RECTLIST | (12 * nbox_this_time - 1)); while (nbox_this_time--) { int box_x1 = pbox->x1; int box_y1 = pbox->y1; int box_x2 = pbox->x2; int box_y2 = pbox->y2; float src_scale_x, src_scale_y; pbox++; src_scale_x = ((float)src_w / width) / drw_w; src_scale_y = ((float)src_h / height) / drw_h; /* vertex data - rect list consists of bottom right, * bottom left, and top left vertices. */ /* bottom right */ OUT_BATCH_F(box_x2 + pix_xoff); OUT_BATCH_F(box_y2 + pix_yoff); OUT_BATCH_F((box_x2 - dxo) * src_scale_x); OUT_BATCH_F((box_y2 - dyo) * src_scale_y); /* bottom left */ OUT_BATCH_F(box_x1 + pix_xoff); OUT_BATCH_F(box_y2 + pix_yoff); OUT_BATCH_F((box_x1 - dxo) * src_scale_x); OUT_BATCH_F((box_y2 - dyo) * src_scale_y); /* top left */ OUT_BATCH_F(box_x1 + pix_xoff); OUT_BATCH_F(box_y1 + pix_yoff); OUT_BATCH_F((box_x1 - dxo) * src_scale_x); OUT_BATCH_F((box_y1 - dyo) * src_scale_y); } intel_batch_end_atomic(scrn); } if (target != pixmap) { GCPtr gc; gc = GetScratchGC(pixmap->drawable.depth, pixmap->drawable.pScreen); if (gc) { gc->subWindowMode = ClipByChildren; if (REGION_NUM_RECTS(dstRegion) > 1) { RegionPtr tmp; tmp = REGION_CREATE(pixmap->drawable.pScreen, NULL, 0); if (tmp) { REGION_COPY(pixmap->drawable.pScreen, tmp, dstRegion); gc->funcs->ChangeClip(gc, CT_REGION, tmp, 0); } } ValidateGC(&pixmap->drawable, gc); gc->ops->CopyArea(&target->drawable, &pixmap->drawable, gc, 0, 0, target->drawable.width, target->drawable.height, -pix_xoff, -pix_yoff); FreeScratchGC(gc); } target->drawable.pScreen->DestroyPixmap(target); } intel_uxa_debug_flush(scrn); }
static Bool create_buffer(DrawablePtr pDraw, struct ARMSOCDRI2BufferRec *buf) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); DRI2BufferPtr buffer = DRIBUF(buf); PixmapPtr pPixmap = NULL; struct armsoc_bo *bo; int ret; if (buffer->attachment == DRI2BufferFrontLeft) { pPixmap = draw2pix(pDraw); pPixmap->refcnt++; } else { pPixmap = createpix(pDraw); } if (!pPixmap) { assert(buffer->attachment != DRI2BufferFrontLeft); ERROR_MSG("Failed to create back buffer for window"); goto fail; } if (buffer->attachment == DRI2BufferBackLeft && pARMSOC->driNumBufs > 2) { buf->pPixmaps = calloc(pARMSOC->driNumBufs-1, sizeof(PixmapPtr)); buf->numPixmaps = pARMSOC->driNumBufs-1; } else { buf->pPixmaps = malloc(sizeof(PixmapPtr)); buf->numPixmaps = 1; } if (!buf->pPixmaps) { ERROR_MSG("Failed to allocate PixmapPtr array for DRI2Buffer"); goto fail; } buf->pPixmaps[0] = pPixmap; assert(buf->currentPixmap == 0); bo = ARMSOCPixmapBo(pPixmap); if (!bo) { ERROR_MSG( "Attempting to DRI2 wrap a pixmap with no DRM buffer object backing"); goto fail; } DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap); DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8; DRIBUF(buf)->flags = 0; buf->refcnt = 1; buf->previous_canflip = canflip(pDraw); ret = armsoc_bo_get_name(bo, &DRIBUF(buf)->name); if (ret) { ERROR_MSG("could not get buffer name: %d", ret); goto fail; } if (canflip(pDraw) && buffer->attachment != DRI2BufferFrontLeft) { /* Create an fb around this buffer. This will fail and we will * fall back to blitting if the display controller hardware * cannot scan out this buffer (for example, if it doesn't * support the format or there was insufficient scanout memory * at buffer creation time). */ int ret = armsoc_bo_add_fb(bo); if (ret) { WARNING_MSG( "Falling back to blitting a flippable window"); } #if DRI2INFOREC_VERSION >= 6 else if (FALSE == DRI2SwapLimit(pDraw, pARMSOC->swap_chain_size)) { WARNING_MSG( "Failed to set DRI2SwapLimit(%x,%d)", (unsigned int)pDraw, pARMSOC->swap_chain_size); } #endif /* DRI2INFOREC_VERSION >= 6 */ } DRI2_BUFFER_SET_FB(DRIBUF(buf)->flags, armsoc_bo_get_fb(bo) > 0 ? 1 : 0); DRI2_BUFFER_SET_REUSED(DRIBUF(buf)->flags, 0); /* Register Pixmap as having a buffer that can be accessed externally, * so needs synchronised access */ ARMSOCRegisterExternalAccess(pPixmap); return TRUE; fail: if (pPixmap != NULL) { if (buffer->attachment != DRI2BufferFrontLeft) pScreen->DestroyPixmap(pPixmap); else pPixmap->refcnt--; } return FALSE; }
DRI2BufferPtr nouveau_dri2_create_buffer2(ScreenPtr pScreen, DrawablePtr pDraw, unsigned int attachment, unsigned int format) { NVPtr pNv = NVPTR(xf86ScreenToScrn(pScreen)); struct nouveau_dri2_buffer *nvbuf; struct nouveau_pixmap *nvpix; PixmapPtr ppix = NULL; nvbuf = calloc(1, sizeof(*nvbuf)); if (!nvbuf) return NULL; if (attachment == DRI2BufferFrontLeft) { ppix = get_drawable_pixmap(pDraw); if (pScreen != ppix->drawable.pScreen) ppix = NULL; if (pDraw->type == DRAWABLE_WINDOW) { #if DRI2INFOREC_VERSION >= 6 /* Set initial swap limit on drawable. */ DRI2SwapLimit(pDraw, pNv->swap_limit); #endif } if (ppix) ppix->refcnt++; } else { int bpp; unsigned int usage_hint = NOUVEAU_CREATE_PIXMAP_TILED; /* 'format' is just depth (or 0, or maybe it depends on the caller) */ bpp = round_up_pow2(format ? format : pDraw->depth); if (attachment == DRI2BufferDepth || attachment == DRI2BufferDepthStencil) usage_hint |= NOUVEAU_CREATE_PIXMAP_ZETA; else usage_hint |= NOUVEAU_CREATE_PIXMAP_SCANOUT; ppix = pScreen->CreatePixmap(pScreen, pDraw->width, pDraw->height, bpp, usage_hint); } if (ppix) { pNv->exa_force_cp = TRUE; exaMoveInPixmap(ppix); pNv->exa_force_cp = FALSE; nvbuf->base.pitch = ppix->devKind; nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8; } nvbuf->base.attachment = attachment; nvbuf->base.driverPrivate = nvbuf; nvbuf->base.format = format; nvbuf->base.flags = 0; nvbuf->ppix = ppix; if (ppix) { nvpix = nouveau_pixmap(ppix); if (!nvpix || !nvpix->bo || nouveau_bo_name_get(nvpix->bo, &nvbuf->base.name)) { pScreen->DestroyPixmap(nvbuf->ppix); free(nvbuf); return NULL; } } return &nvbuf->base; }
/* All caches for a single format share a single pixmap for glyph storage, * allowing mixing glyphs of different sizes without paying a penalty * for switching between source pixmaps. (Note that for a size of font * right at the border between two sizes, we might be switching for almost * every glyph.) * * This function allocates the storage pixmap, and then fills in the * rest of the allocated structures for all caches with the given format. */ static Bool uxa_realize_glyph_caches(ScreenPtr pScreen) { uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); unsigned int formats[] = { PIXMAN_a8, PIXMAN_a8r8g8b8, }; int i; if (uxa_screen->glyph_cache_initialized) return TRUE; uxa_screen->glyph_cache_initialized = TRUE; memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches)); for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i]; PixmapPtr pixmap; PicturePtr picture; CARD32 component_alpha; int depth = PIXMAN_FORMAT_DEPTH(formats[i]); int error; PictFormatPtr pPictFormat = PictureMatchFormat(pScreen, depth, formats[i]); if (!pPictFormat) goto bail; /* Now allocate the pixmap and picture */ pixmap = pScreen->CreatePixmap(pScreen, CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, depth, INTEL_CREATE_PIXMAP_TILING_X); if (!pixmap) goto bail; if (!uxa_pixmap_is_offscreen(pixmap)) { /* Presume shadow is in-effect */ pScreen->DestroyPixmap(pixmap); uxa_unrealize_glyph_caches(pScreen); return TRUE; } component_alpha = NeedsComponent(pPictFormat->format); picture = CreatePicture(0, &pixmap->drawable, pPictFormat, CPComponentAlpha, &component_alpha, serverClient, &error); pScreen->DestroyPixmap(pixmap); if (!picture) goto bail; ValidatePicture(picture); cache->picture = picture; cache->glyphs = calloc(sizeof(GlyphPtr), GLYPH_CACHE_SIZE); if (!cache->glyphs) goto bail; cache->evict = rand() % GLYPH_CACHE_SIZE; } assert(i == UXA_NUM_GLYPH_CACHE_FORMATS); return TRUE; bail: uxa_unrealize_glyph_caches(pScreen); return FALSE; }
static int uxa_glyphs_via_mask(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { ScreenPtr screen = pDst->pDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); CARD32 component_alpha; PixmapPtr pixmap, white_pixmap; PicturePtr glyph_atlas, mask, white; int xDst = list->xOff, yDst = list->yOff; int x, y, width, height; int dst_off_x, dst_off_y; int n, error; BoxRec box; uxa_glyph_extents(nlist, list, glyphs, &box); if (box.x2 <= box.x1 || box.y2 <= box.y1) return 0; dst_off_x = box.x1; dst_off_y = box.y1; width = box.x2 - box.x1; height = box.y2 - box.y1; x = -box.x1; y = -box.y1; if (maskFormat->depth == 1) { PictFormatPtr a8Format = PictureMatchFormat(screen, 8, PICT_a8); if (!a8Format) return -1; maskFormat = a8Format; } pixmap = screen->CreatePixmap(screen, width, height, maskFormat->depth, CREATE_PIXMAP_USAGE_SCRATCH); if (!pixmap) return 1; if (!uxa_pixmap_is_offscreen(pixmap)) { screen->DestroyPixmap(pixmap); return -1; } white_pixmap = NULL; white = create_white_solid(screen); if (white) white_pixmap = uxa_get_drawable_pixmap(white->pDrawable); if (!white_pixmap) { if (white) FreePicture(white, 0); screen->DestroyPixmap(pixmap); return -1; } uxa_clear_pixmap(screen, uxa_screen, pixmap); component_alpha = NeedsComponent(maskFormat->format); mask = CreatePicture(0, &pixmap->drawable, maskFormat, CPComponentAlpha, &component_alpha, serverClient, &error); screen->DestroyPixmap(pixmap); if (!mask) { FreePicture(white, 0); return 1; } ValidatePicture(mask); glyph_atlas = NULL; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; while (n--) { GlyphPtr glyph = *glyphs++; PicturePtr this_atlas; int glyph_x, glyph_y; struct uxa_glyph *priv; if (glyph->info.width == 0 || glyph->info.height == 0) goto next_glyph; priv = uxa_glyph_get_private(glyph); if (priv != NULL) { glyph_x = priv->x; glyph_y = priv->y; this_atlas = priv->cache->picture; } else { if (glyph_atlas) { uxa_screen->info->done_composite(pixmap); glyph_atlas = NULL; } this_atlas = uxa_glyph_cache(screen, glyph, &glyph_x, &glyph_y); if (this_atlas == NULL) { /* no cache for this glyph */ this_atlas = GetGlyphPicture(glyph, screen); glyph_x = glyph_y = 0; } } if (this_atlas != glyph_atlas) { PixmapPtr glyph_pixmap; if (glyph_atlas) uxa_screen->info->done_composite(pixmap); glyph_pixmap = uxa_get_drawable_pixmap(this_atlas->pDrawable); if (!uxa_pixmap_is_offscreen(glyph_pixmap) || !uxa_screen->info->prepare_composite(PictOpAdd, white, this_atlas, mask, white_pixmap, glyph_pixmap, pixmap)) { FreePicture(white, 0); FreePicture(mask, 0); return -1; } glyph_atlas = this_atlas; } uxa_screen->info->composite(pixmap, 0, 0, glyph_x, glyph_y, x - glyph->info.x, y - glyph->info.y, glyph->info.width, glyph->info.height); next_glyph: x += glyph->info.xOff; y += glyph->info.yOff; } list++; } if (glyph_atlas) uxa_screen->info->done_composite(pixmap); uxa_composite(op, pSrc, mask, pDst, dst_off_x + xSrc - xDst, dst_off_y + ySrc - yDst, 0, 0, dst_off_x, dst_off_y, width, height); FreePicture(white, 0); FreePicture(mask, 0); return 0; }
/* The most efficient thing to way to upload the glyph to the screen * is to use CopyArea; uxa pixmaps are always offscreen. */ static void uxa_glyph_cache_upload_glyph(ScreenPtr screen, uxa_glyph_cache_t * cache, GlyphPtr glyph, int x, int y) { PicturePtr pGlyphPicture = GetGlyphPicture(glyph, screen); PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; PixmapPtr scratch; GCPtr gc; gc = GetScratchGC(pCachePixmap->drawable.depth, screen); if (!gc) return; ValidateGC(&pCachePixmap->drawable, gc); scratch = pGlyphPixmap; /* Create a temporary bo to stream the updates to the cache */ if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth || !uxa_pixmap_is_offscreen(scratch)) { scratch = screen->CreatePixmap(screen, glyph->info.width, glyph->info.height, pCachePixmap->drawable.depth, UXA_CREATE_PIXMAP_FOR_MAP); if (scratch) { if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) { PicturePtr picture; int error; picture = CreatePicture(0, &scratch->drawable, PictureMatchFormat(screen, pCachePixmap->drawable.depth, cache->picture->format), 0, NULL, serverClient, &error); if (picture) { ValidatePicture(picture); uxa_composite(PictOpSrc, pGlyphPicture, NULL, picture, 0, 0, 0, 0, 0, 0, glyph->info.width, glyph->info.height); FreePicture(picture, 0); } } else { uxa_copy_area(&pGlyphPixmap->drawable, &scratch->drawable, gc, 0, 0, glyph->info.width, glyph->info.height, 0, 0); } } else { scratch = pGlyphPixmap; } } uxa_copy_area(&scratch->drawable, &pCachePixmap->drawable, gc, 0, 0, glyph->info.width, glyph->info.height, x, y); if (scratch != pGlyphPixmap) screen->DestroyPixmap(scratch); FreeScratchGC(gc); }