static Bool videoInitWindow(CompPlugin *p, CompWindow *w) { VideoWindow *vw; VIDEO_SCREEN(w->screen); vw = malloc(sizeof (VideoWindow)); if (!vw) return FALSE; vw->source = NULL; vw->context = NULL; w->base.privates[vs->windowPrivateIndex].ptr = vw; if (w->shaded || w->attrib.map_state == IsViewable) videoWindowUpdate(w); return TRUE; }
static void videoSetSupportedHint (CompScreen *s) { Atom data[16]; int i, n = 0; VIDEO_DISPLAY (s->display); VIDEO_SCREEN (s); for (i = 0; i < IMAGE_FORMAT_NUM; i++) { if (!vs->imageFormat[i]) continue; if (i == 0 || vd->opt[i - 1].value.b) data[n++] = vd->videoImageFormatAtom[i]; } XChangeProperty (s->display->display, s->root, vd->videoSupportedAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) data, n); }
static void videoWindowMoveNotify(CompWindow *w, int dx, int dy, Bool immediate) { VIDEO_SCREEN(w->screen); VIDEO_WINDOW(w); if (vw->context) { vw->context->box.extents.x1 += dx; vw->context->box.extents.y1 += dy; vw->context->box.extents.x2 += dx; vw->context->box.extents.y2 += dy; updateWindowVideoMatrix(w); } UNWRAP(vs, w->screen, windowMoveNotify); (*w->screen->windowMoveNotify)(w, dx, dy, immediate); WRAP(vs, w->screen, windowMoveNotify, videoWindowMoveNotify); }
static void videoWindowUpdate(CompWindow *w) { Atom actual; int result, format, i; unsigned long n, left; unsigned char *propData; VideoTexture *texture = NULL; Pixmap pixmap = None; Atom imageFormat = 0; decor_point_t p[2]; int aspectX = 0; int aspectY = 0; int panScan = 0; int width = 0; int height = 0; VIDEO_DISPLAY(w->screen->display); VIDEO_SCREEN(w->screen); VIDEO_WINDOW(w); memset(p, 0, sizeof (p)); result = XGetWindowProperty(w->screen->display->display, w->id, vd->videoAtom, 0L, 13L, FALSE, XA_INTEGER, &actual, &format, &n, &left, &propData); if (result == Success && propData) { if (n == 13) { long *data = (long *)propData; pixmap = *data++; imageFormat = *data++; width = *data++; height = *data++; aspectX = *data++; aspectY = *data++; panScan = *data++; p[0].gravity = *data++; p[0].x = *data++; p[0].y = *data++; p[1].gravity = *data++; p[1].x = *data++; p[1].y = *data++; } XFree(propData); } for (i = 0; i < IMAGE_FORMAT_NUM; i++) if (vd->videoImageFormatAtom[i] == imageFormat) break; if (i < IMAGE_FORMAT_NUM) { if (!vs->imageFormat[i]) { compLogMessage("video", CompLogLevelWarn, "Image format not supported"); i = IMAGE_FORMAT_NUM; } } if (i < IMAGE_FORMAT_NUM) { texture = videoGetTexture(w->screen, pixmap); if (!texture) { compLogMessage("video", CompLogLevelWarn, "Bad pixmap 0x%x", (int)pixmap); } } if (vw->source) { videoReleaseTexture(w->screen, vw->source->texture); } else { vw->source = malloc(sizeof (VideoSource)); } if (texture && vw->source) { vw->source->texture = texture; vw->source->format = i; vw->source->p1 = p[0]; vw->source->p2 = p[1]; vw->source->width = width; vw->source->height = height; vw->source->aspect = aspectX && aspectY; vw->source->panScan = panScan / 65536.0f; if (vw->source->aspect) vw->source->aspectRatio = (float)aspectX / aspectY; updateWindowVideoContext(w, vw->source); } else { if (texture) videoReleaseTexture(w->screen, texture); if (vw->source) { free(vw->source); vw->source = NULL; } if (vw->context) { free(vw->context); vw->context = NULL; } } }
static void videoDrawWindowTexture(CompWindow *w, CompTexture *texture, const FragmentAttrib *attrib, unsigned int mask) { CompScreen *s = w->screen; VIDEO_SCREEN(s); VIDEO_WINDOW(w); if (vw->context) { VideoSource *src = vw->context->source; if (src->format == IMAGE_FORMAT_YV12 && &src->texture->texture == texture) { FragmentAttrib fa = *attrib; int param, function; param = allocFragmentParameters(&fa, 2); function = getYV12FragmentFunction(s, texture, param); if (function) { float minX, minY, maxX, maxY, y1, y2; addFragmentFunction(&fa, function); minX = COMP_TEX_COORD_X(&texture->matrix, 1.0f); maxX = COMP_TEX_COORD_X(&texture->matrix, src->width - 1.0f); y1 = COMP_TEX_COORD_Y(&texture->matrix, 1.0f); y2 = COMP_TEX_COORD_Y(&texture->matrix, src->height - 1.0f); minY = MIN(y1, y2); maxY = MAX(y1, y2); (*s->programEnvParameter4f)(GL_FRAGMENT_PROGRAM_ARB, param, minX, minY, maxX, maxY); /* need to provide plane offsets when texture coordinates are not normalized */ if (texture->target != GL_TEXTURE_2D) { float offsetX, offsetY; offsetX = COMP_TEX_COORD_X(&texture->matrix, src->width / 2); if (s->glxPixmapFBConfigs[8].yInverted) offsetY = COMP_TEX_COORD_Y(&texture->matrix, src->height); else offsetY = COMP_TEX_COORD_Y(&texture->matrix, -src->height / 2); (*s->programEnvParameter4f)(GL_FRAGMENT_PROGRAM_ARB, param + 1, 0.0f, offsetY, offsetX, 0.0f); } } UNWRAP(vs, s, drawWindowTexture); (*s->drawWindowTexture)(w, texture, &fa, mask); WRAP(vs, s, drawWindowTexture, videoDrawWindowTexture); } else { if (!(mask & PAINT_WINDOW_BLEND_MASK)) { /* we don't have to draw client window texture when video cover the full window and blending isn't used */ if (vw->context->full && texture == w->texture) return; } UNWRAP(vs, s, drawWindowTexture); (*s->drawWindowTexture)(w, texture, attrib, mask); WRAP(vs, s, drawWindowTexture, videoDrawWindowTexture); } } else { UNWRAP(vs, s, drawWindowTexture); (*s->drawWindowTexture)(w, texture, attrib, mask); WRAP(vs, s, drawWindowTexture, videoDrawWindowTexture); } }
static int getYV12FragmentFunction(CompScreen *s, CompTexture *texture, int param) { VideoFunction *function; CompFunctionData *data; int target; VIDEO_SCREEN(s); if (texture->target == GL_TEXTURE_2D) target = COMP_FETCH_TARGET_2D; else target = COMP_FETCH_TARGET_RECT; for (function = vs->yv12Functions; function; function = function->next) if (function->param == param && function->target == target) return function->handle; data = createFunctionData(); if (data) { static char *temp[] = { "uv", "tmp", "position" }; int i, handle = 0; char str[1024]; Bool ok = TRUE; for (i = 0; i < sizeof (temp) / sizeof (temp[0]); i++) ok &= addTempHeaderOpToFunctionData(data, temp[i]); snprintf(str, 1024, "MOV position, fragment.texcoord[0];" "MAX position, position, program.env[%d];" "MIN position, position, program.env[%d].zwww;", param, param); ok &= addDataOpToFunctionData(data, str); if (target == COMP_FETCH_TARGET_RECT) { snprintf(str, 1024, "TEX output, position, texture[0], RECT;" "MOV output, output.a;"); ok &= addDataOpToFunctionData(data, str); if (s->glxPixmapFBConfigs[8].yInverted) { snprintf(str, 1024, "MAD position, position, 0.5, program.env[%d].xy;", param + 1); } else { snprintf(str, 1024, "ADD position, position, program.env[%d].xy;" "MUL position, position, 0.5;", param + 1); } ok &= addDataOpToFunctionData(data, str); snprintf(str, 1024, "TEX tmp, position, texture[0], RECT;" "MOV uv, tmp.a;" "MAD output, output, 1.164, -0.073;" "ADD position.x, position.x, program.env[%d].z;" "TEX tmp, position, texture[0], RECT;" "MOV uv.y, tmp.a;", param + 1); } else { snprintf(str, 1024, "TEX output, position, texture[0], 2D;" "MOV output, output.a;"); ok &= addDataOpToFunctionData(data, str); if (s->glxPixmapFBConfigs[8].yInverted) { snprintf(str, 1024, "MAD position, position, 0.5, { 0.0, %f };", 2.0f / 3.0f); } else { snprintf(str, 1024, "SUB position, position, { 0.0, %f };" "MUL position, position, 0.5;", 1.0f / 3.0f); } ok &= addDataOpToFunctionData(data, str); snprintf(str, 1024, "TEX tmp, position, texture[0], 2D;" "MOV uv, tmp.a;" "MAD output, output, 1.164, -0.073;" "ADD position.x, position.x, 0.5;" "TEX tmp, position, texture[0], 2D;" "MOV uv.y, tmp.a;"); } ok &= addDataOpToFunctionData(data, str); snprintf(str, 1024, "SUB uv, uv, { 0.5, 0.5 };" "MAD output.xyz, { 1.596, -0.813, 0.0 }, uv.xxxw, output;" "MAD output.xyz, { 0.0, -0.391, 2.018 }, uv.yyyw, output;" "MOV output.a, 1.0;"); ok &= addDataOpToFunctionData(data, str); if (!ok) { destroyFunctionData(data); return 0; } function = malloc(sizeof (VideoFunction)); if (function) { handle = createFragmentFunction(s, "video", data); function->handle = handle; function->target = target; function->param = param; function->next = vs->yv12Functions; vs->yv12Functions = function; } destroyFunctionData(data); return handle; } return 0; }