void MoonEGLContext::Paint (Color *color) { Target *target = Top ()->GetTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); Rect clip; // avoid GL rendering to target without previously // allocated hardware drawable if (!HasDrawable ()) { Context::Paint (color); ms->unref (); return; } Top ()->GetClip (&clip); if (!target->GetInit () && r == clip) { // mark target as initialized target->SetInit (ms); } ForceCurrent (); GLContext::Paint (color); ms->unref (); }
void MoonEGLContext::SetupVertexData (const double *matrix, double x, double y, double width, double height) { Target *target = Top ()->GetTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); MoonEGLSurface *dst = (MoonEGLSurface *) ms; double m[16]; if (matrix) Matrix3D::Init (m, matrix); else Matrix3D::Identity (m); GLContext::SetupVertexData (m, x, y, width, height); if (dst->GetEGLDisplay ()) { int i; for (i = 0; i < 4; i++) { GLfloat v = vertices[i][1] + vertices[i][3]; vertices[i][1] = vertices[i][3] - v; } } ms->unref (); }
void MoonEGLContext::SetScissor () { Target *target = Top ()->GetTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); MoonEGLSurface *dst = (MoonEGLSurface *) ms; Rect clip; Top ()->GetClip (&clip); clip.x -= r.x; clip.y -= r.y; if (dst->GetEGLDisplay ()) { glScissor (clip.x, dst->Height () - (clip.y + clip.height), clip.width, clip.height); } else { GLContext::SetScissor (); } ms->unref (); }
Rect MoonEGLContext::Pop (MoonSurface **ref) { Context::Node *prev = (Context::Node *) Top ()->prev; g_assert (prev); if (Top ()->GetTarget () != prev->GetTarget ()) { Target *target = Top ()->GetTarget (); MoonSurface *init = target->GetInit (); MoonSurface *ms; Rect r = target->GetData (&ms); MoonSurface *data = init != ms ? init : NULL; ms->unref (); ForceCurrent (); // return reference to initial state surface instead // of the target surface itself if (data) { Node *node = (Node *) Stack::Pop (); *ref = data->ref (); delete node; return r; } else { SyncDrawable (); } } return GLContext::Pop (ref); }
void CGLContext::BlitVUY2 (unsigned char *data) { Target *target = Top ()->GetTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); OpengGLSurface *dst = (OpenGLSurface *) ms; int size[] = { dst->Width (), dst->Height () }; GLuint texture = dst->Texture (); // no support for clipping g_assert (GetClip () == r); // no support for blit to drawable at the moment g_assert (!dst->HasDrawable ()); // mark target as initialized target->SetInit (ms); glBindTexture (GL_TEXTURE_2D, texture); glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, size [0], size [1], 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, data); glBindTexture (GL_TEXTURE_2D, 0); ms->unref (); }
void MoonEGLContext::Blit (unsigned char *data, int stride) { Target *target = Top ()->GetTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); MoonEGLSurface *dst = (MoonEGLSurface *) ms; unsigned char *buffer = data; int buffer_stride = stride; ForceCurrent (); // no support for clipping g_assert (GetClip () == r); // no support for blit to drawable at the moment g_assert (!dst->GetEGLDisplay ()); // mark target as initialized target->SetInit (ms); if (PixelRowLength (stride, dst->Width (), 4) != dst->Width ()) { buffer_stride = dst->Width () * 4; buffer = (unsigned char *) g_malloc (buffer_stride * dst->Height ()); for (int y = 0; y < dst->Height (); y++) memcpy (buffer + (y * buffer_stride), data + (y * stride), buffer_stride); } glPixelStorei (GL_UNPACK_ALIGNMENT, PixelAlignment (buffer_stride)); glBindTexture (GL_TEXTURE_2D, dst->Texture ()); glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, dst->Width (), dst->Height (), GL_RGBA, GL_UNSIGNED_BYTE, buffer); glBindTexture (GL_TEXTURE_2D, 0); glPixelStorei (GL_UNPACK_ALIGNMENT, 4); if (buffer != data) g_free (buffer); ms->unref (); }
cairo_t * MoonEGLContext::Push (Cairo extents) { Target *target = Top ()->GetTarget (); Target *cairo = target->GetCairoTarget (); Rect box; Top ()->GetClip (&box); box = box.Intersection (extents.r); if (box.IsEmpty ()) return Context::Push (extents); if (cairo) { Rect r = cairo->GetData (NULL); Region *region = new Region (r); if (region->RectIn (box) != CAIRO_REGION_OVERLAP_IN) { ForceCurrent (); SyncDrawable (); } delete region; } if (!target->GetCairoTarget ()) { MoonSurface *ms; Rect r = target->GetData (&ms); if (HasDrawable ()) { MoonEGLSurface *surface = new MoonEGLSurface (box.width, box.height); Target *cairo = new Target (surface, box); target->SetCairoTarget (cairo); cairo->unref (); surface->unref (); } else { // mark target contents as initialized target->SetInit (ms); } ms->unref (); } return Context::Push (extents); }
void MoonEGLContext::SetFramebuffer () { Target *target = Top ()->GetTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); MoonEGLSurface *dst = (MoonEGLSurface *) ms; SyncDrawable (); if (!dst->GetEGLDisplay ()) GLContext::SetFramebuffer (); ms->unref (); }
gboolean MoonEGLContext::HasDrawable () { Target *target = Top ()->GetTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); MoonEGLSurface *dst = (MoonEGLSurface *) ms; gboolean status = FALSE; if (dst->GetEGLDisplay () || dst->HasTexture ()) status = TRUE; ms->unref (); return status; }
void MoonEGLContext::BlitYV12 (unsigned char *data[], int stride[]) { Target *target = Top ()->GetTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); MoonEGLSurface *dst = (MoonEGLSurface *) ms; int size[] = { dst->Width (), dst->Height () }; int width[] = { size[0], size[0] / 2, size[0] / 2 }; int height[] = { size[1], size[1] / 2, size[1] / 2 }; unsigned char *buffer[] = { data[0], data[1], data[2] }; int buffer_stride[] = { stride[0], stride[1], stride[2] }; ForceCurrent (); // no support for blit to drawable at the moment g_assert (!dst->GetEGLDisplay ()); // mark target as initialized target->SetInit (ms); for (int i = 0; i < 3; i++) { if (PixelRowLength (stride[i], width[i], 1) != width[i]) { buffer_stride[i] = width[i]; buffer[i] = (unsigned char *) g_malloc (buffer_stride[i] * height[i]); for (int y = 0; y < height[i]; y++) memcpy (buffer[i] + y * buffer_stride[i], data[i] + y * stride[i], buffer_stride[i]); } } GLContext::BlitYV12 (buffer, buffer_stride); for (int i = 0; i < 3; i++) if (buffer[i] != data[i]) g_free (buffer[i]); ms->unref (); }
void CairoContext::Push (Group extents) { cairo_surface_t *parent = Top ()->GetTarget ()->Cairo (); Rect r = extents.r.RoundOut (); cairo_surface_t *data = cairo_surface_create_similar (parent, CAIRO_CONTENT_COLOR_ALPHA, r.width, r.height); MoonSurface *surface = new CairoSurface (data, r.width, r.height); Target *target = new Target (surface, extents.r); cairo_matrix_t matrix; Top ()->GetMatrix (&matrix); Stack::Push (new Context::Node (target, &matrix, &extents.r)); target->unref (); surface->unref (); cairo_surface_destroy (data); }
void WriteableBitmap::Render (UIElement *element, Transform *transform) { MoonSurface *src; Context *ctx; if (!element) return; cairo_surface_t *surface = GetImageSurface (); if (!surface) return; Rect bounds (0, 0, GetPixelWidth (), GetPixelHeight ()); #ifdef USE_GALLIUM struct pipe_resource pt, *texture; GalliumSurface *target; struct pipe_screen *screen = swrast_screen_create (null_sw_create ()); memset (&pt, 0, sizeof (pt)); pt.target = PIPE_TEXTURE_2D; pt.format = PIPE_FORMAT_B8G8R8A8_UNORM; pt.width0 = 1; pt.height0 = 1; pt.depth0 = 1; pt.last_level = 0; pt.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_TRANSFER_READ; texture = (*screen->resource_create) (screen, &pt); target = new GalliumSurface (texture); pipe_resource_reference (&texture, NULL); ctx = new GalliumContext (target); target->unref (); #else CairoSurface *target; target = new CairoSurface (1, 1); ctx = new CairoContext (target); target->unref (); #endif ctx->Push (Context::Group (bounds)); cairo_matrix_t xform; cairo_matrix_init_identity (&xform); if (transform) transform->GetTransform (&xform); FrameworkElement *fe = (FrameworkElement *)element; if (fe->GetFlowDirection () == FlowDirectionRightToLeft) { cairo_matrix_translate (&xform, fe->GetActualWidth (), 0.0); cairo_matrix_scale (&xform, -1, 1); } element->Paint (ctx, bounds, &xform); bounds = ctx->Pop (&src); if (!bounds.IsEmpty ()) { cairo_surface_t *image = src->Cairo (); cairo_t *cr = cairo_create (surface); cairo_set_source_surface (cr, image, 0, 0); cairo_paint (cr); cairo_destroy (cr); cairo_surface_destroy (image); src->unref (); } delete ctx; #ifdef USE_GALLIUM screen->destroy (screen); #endif }
void MoonEGLContext::SyncDrawable () { Target *target = Top ()->GetTarget (); Target *cairo = target->GetCairoTarget (); MoonSurface *ms; Rect r = target->GetData (&ms); MoonEGLSurface *dst = (MoonEGLSurface *) ms; // clear target contents if (!target->GetInit ()) { if (!dst->GetEGLDisplay ()) GLContext::SetFramebuffer (); glClearColor (0.0, 0.0, 0.0, 0.0); glClear (GL_COLOR_BUFFER_BIT); // mark target contents as initialized target->SetInit (ms); } // initialize target contents with surface if (target->GetInit () != ms) { MoonEGLSurface *src = (MoonEGLSurface *) target->GetInit (); GLuint texture0 = src->Texture (); GLuint program = GetProjectProgram (1.0, 0); GLsizei width0 = src->Width (); GLsizei height0 = src->Height (); if (!dst->GetEGLDisplay ()) GLContext::SetFramebuffer (); SetViewport (); glUseProgram (program); SetupVertexData (NULL, 0, 0, width0, height0); SetupTexCoordData (); glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, vertices); glVertexAttribPointer (1, 4, GL_FLOAT, GL_FALSE, 0, texcoords); glBindTexture (GL_TEXTURE_2D, texture0); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glUniform1i (glGetUniformLocation (program, "sampler0"), 0); glEnableVertexAttribArray (0); glEnableVertexAttribArray (1); glDrawArrays (GL_TRIANGLE_FAN, 0, 4); glDisableVertexAttribArray (1); glDisableVertexAttribArray (0); glBindTexture (GL_TEXTURE_2D, 0); glUseProgram (0); glBindFramebuffer (GL_FRAMEBUFFER, 0); // mark target contents as initialized target->SetInit (ms); } // render any cairo contents onto target if (cairo) { MoonSurface *mSrc; Rect rSrc = cairo->GetData (&mSrc); MoonEGLSurface *src = (MoonEGLSurface *) mSrc; GLuint texture0 = src->Texture (); GLuint program = GetProjectProgram (1.0, 0); GLsizei width0 = src->Width (); GLsizei height0 = src->Height (); if (!dst->GetEGLDisplay ()) GLContext::SetFramebuffer (); SetViewport (); glUseProgram (program); SetupVertexData (NULL, rSrc.x - r.x, rSrc.y - r.y, width0, height0); SetupTexCoordData (); glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, vertices); glVertexAttribPointer (1, 4, GL_FLOAT, GL_FALSE, 0, texcoords); glBindTexture (GL_TEXTURE_2D, texture0); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glUniform1i (glGetUniformLocation (program, "sampler0"), 0); glEnableVertexAttribArray (0); glEnableVertexAttribArray (1); glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glDrawArrays (GL_TRIANGLE_FAN, 0, 4); glDisable (GL_BLEND); glDisableVertexAttribArray (1); glDisableVertexAttribArray (0); glBindTexture (GL_TEXTURE_2D, 0); glUseProgram (0); glBindFramebuffer (GL_FRAMEBUFFER, 0); mSrc->unref (); target->SetCairoTarget (NULL); } ms->unref (); }
int main (int argc, char **argv) { Context *ctx; CairoSurface *target; MoonSurface *surface; cairo_surface_t *dst, *src; TransformEffect *effect; Matrix3D *matrix; DoubleCollection *values; int stride = width * 4; Rect bounds = Rect (0, 0, width, height); gpointer data; bool status = true; int count = 1; if (argc < 2) { printf ("usage: %s MATRIX [COUNT]\n", argv[0]); return 1; } gtk_init (&argc, &argv); runtime_init_desktop (); values = DoubleCollection::FromStr (argv[1]); if (!values) { printf ("usage: %s MATRIX [COUNT]\n", argv[0]); return 1; } if (values->GetCount () != 16) { printf ("usage: %s MATRIX [COUNT]\n", argv[0]); values->unref (); return 1; } data = g_malloc0 (height * stride); dst = cairo_image_surface_create_for_data ((unsigned char *) data, CAIRO_FORMAT_ARGB32, width, height, stride); target = new CairoSurface (dst); cairo_surface_destroy (dst); ctx = new CairoContext (target); target->unref (); src = cairo_surface_create_similar (dst, CAIRO_CONTENT_COLOR_ALPHA, width, height); surface = new CairoSurface (src); cairo_surface_destroy (src); effect = new TransformEffect (); matrix = new Matrix3D (); matrix->SetM11 (values->GetValueAt (0)->AsDouble ()); matrix->SetM12 (values->GetValueAt (1)->AsDouble ()); matrix->SetM13 (values->GetValueAt (2)->AsDouble ()); matrix->SetM14 (values->GetValueAt (3)->AsDouble ()); matrix->SetM21 (values->GetValueAt (4)->AsDouble ()); matrix->SetM22 (values->GetValueAt (5)->AsDouble ()); matrix->SetM23 (values->GetValueAt (6)->AsDouble ()); matrix->SetM24 (values->GetValueAt (7)->AsDouble ()); matrix->SetM31 (values->GetValueAt (8)->AsDouble ()); matrix->SetM32 (values->GetValueAt (9)->AsDouble ()); matrix->SetM33 (values->GetValueAt (10)->AsDouble ()); matrix->SetM34 (values->GetValueAt (11)->AsDouble ()); matrix->SetOffsetX (values->GetValueAt (12)->AsDouble ()); matrix->SetOffsetY (values->GetValueAt (13)->AsDouble ()); matrix->SetOffsetZ (values->GetValueAt (14)->AsDouble ()); matrix->SetM44 (values->GetValueAt (15)->AsDouble ()); values->unref (); if (argc > 2) { count = atoi (argv[2]); if (count > 1) { signal (SIGALRM, projection_alarm_handler); alarm (5); } } while (status && count-- > 0) { status = effect->Render (ctx, surface, (double *) matrix->GetMatrixValues (), 0, 0, width, height); frames++; } matrix->unref (); surface->unref (); delete ctx; g_free (data); runtime_shutdown (); return status != true; }
void MoonWindowGtk::PaintToDrawable (GdkDrawable *drawable, GdkVisual *visual, GdkEventExpose *event, int off_x, int off_y, bool transparent, bool clear_transparent) { // LOG_UI ("Surface::PaintToDrawable (%p, %p, (%d,%d %d,%d), %d, %d, %d, %d)\n", // drawable, visual, event->area.x, event->area.y, event->area.width, event->area.height, // off_x, off_y, transparent, clear_transparent); SetCurrentDeployment (); #if 0 #if TIME_REDRAW STARTTIMER (expose, "redraw"); #endif if (cache_size_multiplier == -1) cache_size_multiplier = gdk_drawable_get_depth (drawable) / 8 + 1; #endif int width, height; gdk_drawable_get_size (drawable, &width, &height); Context *ctx; GdkRectangle area = event->area; MoonSurface *src; Rect r = Rect (area.x, area.y, area.width, area.height); if (!native) native = CreateCairoSurface (drawable, visual, true, width, height); cairo_xlib_surface_set_drawable (native, gdk_x11_drawable_get_xid (drawable), width, height); cairo_surface_set_device_offset (native, off_x, off_y); Region *region = new Region (); int count = 0; GdkRectangle *rects; gdk_region_get_rectangles (event->region, &rects, &count); while (count--) { GdkRectangle c = rects[count]; region->Union (Rect (c.x, c.y, c.width, c.height)); } #ifdef USE_GALLIUM if (gctx) { ctx = gctx; } else { struct pipe_resource pt, *texture; GalliumSurface *target; memset (&pt, 0, sizeof (pt)); pt.target = PIPE_TEXTURE_2D; pt.format = PIPE_FORMAT_B8G8R8A8_UNORM; pt.width0 = width; pt.height0 = height; pt.depth0 = 1; pt.last_level = 0; pt.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_TRANSFER_READ; g_assert (screen); texture = (*screen->resource_create) (screen, &pt); target = new GalliumSurface (texture); pipe_resource_reference (&texture, NULL); ctx = new GalliumContext (target); target->unref (); if (gctxn < CONTEXT_CACHE_SIZE) { gctxn++; gctx = ctx; } } #else CairoSurface *target = new CairoSurface (1, 1); ctx = new CairoContext (target); target->unref (); #endif ctx->Push (Context::Group (r)); /* if we are redirecting to an image surface clear that first */ surface->Paint (ctx, region, transparent, true); r = ctx->Pop (&src); if (!r.IsEmpty ()) { cairo_surface_t *image = src->Cairo (); cairo_t *cr = cairo_create (native); cairo_surface_flush (image); cairo_set_source_surface (cr, image, r.x, r.y); cairo_set_operator (cr, clear_transparent ? CAIRO_OPERATOR_SOURCE : CAIRO_OPERATOR_OVER); region->Draw (cr); cairo_fill (cr); cairo_destroy (cr); cairo_surface_destroy (image); src->unref (); } #ifdef USE_GALLIUM if (ctx != gctx) #endif delete ctx; delete region; #if TIME_REDRAW ENDTIMER (expose, "redraw"); #endif }
/** * @fn void PaintToDrawable (GdkVisual *visual, cairo_t *cr_t, GtkAllocation &allocation, bool transparent, bool clear_transparent); * @brief Paints to moonlight window drawable and sets transparency to display the video * and sends the video-rect event to uniplayer * @param visual GdkVisual * @param cr_t cairo_t * @param allocation GtkAllocation * @param transparent bool * @param clear_transparent bool * @return void */ void MoonWindowGtk::PaintToDrawable (GdkVisual *visual, cairo_t *cr_t, GtkAllocation &allocation, bool transparent, bool clear_transparent) { SetCurrentDeployment (); #if 0 #if TIME_REDRAW STARTTIMER (expose, "redraw"); #endif if (cache_size_multiplier == -1) { cache_size_multiplier = gdk_drawable_get_depth (drawable) / 8 + 1; } #endif Context *ctx; cairo_rectangle_int_t area; area.x = allocation.x; area.y = allocation.y; area.width = allocation.width; area.height = allocation.height; MoonSurface *src; Rect r = Rect (area.x, area.y, area.width, area.height); Region *region = new Region (); int count = 0; cairo_region_t *t_region = cairo_region_create_rectangle(&area); count = cairo_region_num_rectangles (t_region); cairo_rectangle_int_t rects[count]; for(int i=0;i<count;i++) { cairo_region_get_rectangle (t_region, i, &rects[i]); } while (count--) { cairo_rectangle_int_t c = rects[count]; region->Union (Rect (c.x, c.y, c.width, c.height)); } #ifdef USE_GALLIUM if (gctx) { ctx = gctx; } else { struct pipe_resource pt, *texture; GalliumSurface *target; memset (&pt, 0, sizeof (pt)); pt.target = PIPE_TEXTURE_2D; pt.format = PIPE_FORMAT_B8G8R8A8_UNORM; pt.width0 = width; pt.height0 = height; pt.depth0 = 1; pt.last_level = 0; pt.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_TRANSFER_READ; g_assert (screen); texture = (*screen->resource_create) (screen, &pt); target = new GalliumSurface (texture); pipe_resource_reference (&texture, NULL); ctx = new GalliumContext (target); target->unref (); if (gctxn < CONTEXT_CACHE_SIZE) { gctxn++; gctx = ctx; } } #else CairoSurface *target = new CairoSurface (1, 1); ctx = new CairoContext (target); target->unref (); #endif ctx->Push (Context::Group (r)); surface->Paint (ctx, region, transparent, true); r = ctx->Pop (&src); if (!r.IsEmpty ()) { cairo_surface_t *image = (cairo_surface_t*) src->Cairo (); cairo_surface_flush (image); cairo_set_source_surface (cr_t, image, r.x, r.y); cairo_set_operator (cr_t, clear_transparent ? CAIRO_OPERATOR_SOURCE : CAIRO_OPERATOR_OVER); region->Draw (cr_t); cairo_fill (cr_t); cairo_surface_destroy (image); src->unref (); } #ifdef USE_GALLIUM if (ctx != gctx) #endif delete ctx; delete region; #if TIME_REDRAW ENDTIMER (expose, "redraw"); #endif }