bool EGLInteropResource::map(IDirect3DSurface9* surface, GLuint tex, int w, int h, int) { D3DSURFACE_DESC dxvaDesc; surface->GetDesc(&dxvaDesc); if (!ensureSurface(w, h)) { releaseEGL(); releaseDX(); return false; } DYGL(glBindTexture(GL_TEXTURE_2D, tex)); const RECT src = { 0, 0, w, h}; if (SUCCEEDED(d3ddev->StretchRect(surface, &src, dx_surface, NULL, D3DTEXF_NONE))) { if (dx_query) { // Flush the draw command now. Ideally, this should be done immediately before the draw call that uses the texture. Flush it once here though. dx_query->Issue(D3DISSUE_END); // ensure data is copied to egl surface. Solution and comment is from chromium // The DXVA decoder has its own device which it uses for decoding. ANGLE has its own device which we don't have access to. // The above code attempts to copy the decoded picture into a surface which is owned by ANGLE. // As there are multiple devices involved in this, the StretchRect call above is not synchronous. // We attempt to flush the batched operations to ensure that the picture is copied to the surface owned by ANGLE. // We need to do this in a loop and call flush multiple times. // We have seen the GetData call for flushing the command buffer fail to return success occassionally on multi core machines, leading to an infinite loop. // Workaround is to have an upper limit of 10 on the number of iterations to wait for the Flush to finish. int k = 0; while ((dx_query->GetData(NULL, 0, D3DGETDATA_FLUSH) == FALSE) && ++k < 10) { Sleep(1); } } eglBindTexImage(egl->dpy, egl->surface, EGL_BACK_BUFFER); } DYGL(glBindTexture(GL_TEXTURE_2D, 0)); return true; }
void QWaylandCursor::setupPixmapCursor(QCursor *cursor) { if (!cursor) { delete mBuffer; mBuffer = 0; return; } ensureSurface(cursor->pixmap().size()); QImage src = cursor->pixmap().toImage().convertToFormat(QImage::Format_ARGB32); for (int y = 0; y < src.height(); ++y) memcpy(mBuffer->image()->scanLine(y), src.scanLine(y), src.bytesPerLine()); mDisplay->setCursor(mSurface, cursor->hotSpot().x(), cursor->hotSpot().y()); }
void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window) { const struct pointer_image *p; if (window == NULL) return; p = NULL; bool isBitmap = false; switch (cursor->shape()) { case Qt::ArrowCursor: p = &pointer_images[cursor->shape()]; break; case Qt::UpArrowCursor: case Qt::CrossCursor: case Qt::WaitCursor: break; case Qt::IBeamCursor: p = &pointer_images[cursor->shape()]; break; case Qt::SizeVerCursor: /* 5 */ case Qt::SizeHorCursor: case Qt::SizeBDiagCursor: case Qt::SizeFDiagCursor: case Qt::SizeAllCursor: case Qt::BlankCursor: /* 10 */ break; case Qt::SplitVCursor: case Qt::SplitHCursor: case Qt::PointingHandCursor: p = &pointer_images[cursor->shape()]; break; case Qt::ForbiddenCursor: case Qt::WhatsThisCursor: /* 15 */ case Qt::BusyCursor: break; case Qt::OpenHandCursor: case Qt::ClosedHandCursor: case Qt::DragCopyCursor: case Qt::DragMoveCursor: /* 20 */ case Qt::DragLinkCursor: p = &pointer_images[cursor->shape()]; break; case Qt::BitmapCursor: isBitmap = true; break; default: break; } if (!p && !isBitmap) { p = &pointer_images[0]; qWarning("unhandled cursor %d", cursor->shape()); } if (isBitmap && !cursor->pixmap().isNull()) { setupPixmapCursor(cursor); } else if (isBitmap && cursor->bitmap()) { qWarning("unsupported QBitmap cursor"); } else { QImageReader reader(p->filename); if (!reader.canRead()) return; ensureSurface(reader.size()); reader.read(mBuffer->image()); mDisplay->setCursor(mSurface, p->hotspot_x, p->hotspot_y); } }