Example #1
0
void
S9xXVDisplayDriver::create_window (int width, int height)
{
    GdkWindowAttr window_attr;
    memset (&window_attr, 0, sizeof (GdkWindowAttr));
    window_attr.event_mask = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
    window_attr.width = width;
    window_attr.height = height;
    window_attr.x = 0;
    window_attr.y = 0;
    window_attr.wclass = GDK_INPUT_OUTPUT;
    window_attr.window_type = GDK_WINDOW_CHILD;
    window_attr.visual = gdk_x11_screen_lookup_visual (gtk_widget_get_screen (drawing_area), vi->visualid);

    gdk_window = gdk_window_new (gtk_widget_get_window (drawing_area),
                                 &window_attr,
                                 GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
    gdk_window_set_user_data (gdk_window, (gpointer) drawing_area);

    gdk_window_show (gdk_window);
    xwindow = GDK_COMPAT_WINDOW_XID (gdk_window);

    output_window_width = width;
    output_window_height = height;
}
int
S9xOpenGLDisplayDriver::init_glx (void)
{
    int glx_attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };

    display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());

    vi = glXChooseVisual (display, DefaultScreen (display), glx_attribs);

    if (!vi)
    {
        fprintf (stderr, _("Couldn't find an adequate OpenGL visual.\n"));
        return 0;
    }

    xcolormap = XCreateColormap (display,
                                GDK_COMPAT_WINDOW_XID (gtk_widget_get_window (drawing_area)),
                                vi->visual,
                                AllocNone);

    create_window (1, 1);
    gdk_window_hide (gdk_window);

    glx_context = glXCreateContext (display, vi, 0, 1);

    if (!glx_context)
    {
        XFreeColormap (display, xcolormap);
        g_object_unref (gdk_window);
        XDestroyWindow (display, xwindow);

        fprintf (stderr, _("Couldn't create an OpenGL context.\n"));
        return 0;
    }

    if (!glXMakeCurrent (display, xwindow, glx_context))
    {
        XFreeColormap (display, xcolormap);
        g_object_unref (gdk_window);
        XDestroyWindow (display, xwindow);
        glXDestroyContext (display, glx_context);

        fprintf (stderr, "glXMakeCurrent failed.\n");
        return 0;
    }

    return 1;
}
void
S9xOpenGLDisplayDriver::create_window (int width, int height)
{
    XSetWindowAttributes window_attr;

    window_attr.colormap = xcolormap;
    window_attr.border_pixel = 0;
    window_attr.event_mask = StructureNotifyMask | ExposureMask;
    window_attr.background_pixmap = None;

    xwindow = XCreateWindow (display,
                             GDK_COMPAT_WINDOW_XID (gtk_widget_get_window (drawing_area)),
                             0,
                             0,
                             width,
                             height,
                             0,
                             vi->depth,
                             InputOutput,
                             vi->visual,
                             CWColormap | CWBorderPixel | CWBackPixmap | CWEventMask,
                             &window_attr);
    XSync (display, False);

    output_window_width = width;
    output_window_height = height;

    XMapWindow (display, xwindow);
    XSync (display, False);

#if USE_GTK3
    gdk_window = gdk_x11_window_foreign_new_for_display (gtk_widget_get_display (drawing_area), xwindow);
#else
    gdk_window = gdk_window_foreign_new (xwindow);
#endif
    XSync (display, False);

    gdk_window_set_user_data (gdk_window, drawing_area);
}
int
S9xXVDisplayDriver::init (void)
{
    int                 padding;
    int                 depth = 0, num_formats, num_attrs, highest_formats = 0;
    XvImageFormatValues *formats = NULL;
    XvAdaptorInfo       *adaptors;
    XvAttribute         *port_attr;
    VisualID            visualid = None;
    unsigned int        num_adaptors;
    GdkScreen           *screen;
    GdkWindow           *root;

    buffer[0] = malloc (image_padded_size);
    buffer[1] = malloc (scaled_padded_size);

    padding = (image_padded_size - image_size) / 2;
    padded_buffer[0] = (void *) (((uint8 *) buffer[0]) + padding);

    padding = (scaled_padded_size - scaled_size) / 2;
    padded_buffer[1] = (void *) (((uint8 *) buffer[1]) + padding);

    memset (buffer[0], 0, image_padded_size);
    memset (buffer[1], 0, scaled_padded_size);

    /* Setup XV */
    gtk_widget_realize (drawing_area);

    display = gdk_x11_display_get_xdisplay (gtk_widget_get_display (drawing_area));
    screen = gtk_widget_get_screen (drawing_area);
    root = gdk_screen_get_root_window (screen);

    xv_portid = -1;
    XvQueryAdaptors (display,
                     GDK_COMPAT_WINDOW_XID (root),
                     &num_adaptors,
                     &adaptors);


    for (int i = 0; i < (int) num_adaptors; i++)
    {
        if (adaptors[i].type & XvInputMask &&
            adaptors[i].type & XvImageMask)
        {
            formats = XvListImageFormats (display,
                                          adaptors[i].base_id,
                                          &num_formats);

            if (num_formats > highest_formats)
            {
                xv_portid = adaptors[i].base_id;
                highest_formats = num_formats;
                visualid = adaptors[i].formats->visual_id;
            }

            free (formats);
        }
    }

    XvFreeAdaptorInfo (adaptors);

    if (xv_portid < 0)
    {
        fprintf (stderr, "Could not open Xv output port.\n");
        return -1;
    }

    /* Set XV_AUTOPAINT_COLORKEY _only_ if available */
    port_attr = XvQueryPortAttributes (display, xv_portid, &num_attrs);

    for (int i = 0; i < num_attrs; i++)
    {
        if (!strcmp (port_attr[i].name, "XV_AUTOPAINT_COLORKEY"))
        {
            Atom colorkey = None;

            colorkey = XInternAtom (display, "XV_AUTOPAINT_COLORKEY", True);
            if (colorkey != None)
                XvSetPortAttribute (display, xv_portid, colorkey, 1);
        }
    }

    /* Try to find an RGB format */
    format = FOURCC_YUY2;
    bpp = 100;

    formats = XvListImageFormats (display,
                                  xv_portid,
                                  &num_formats);

    for (int i = 0; i < num_formats; i++)
    {
        if (formats[i].id == 0x3 || formats[i].type == XvRGB)
        {
            if (formats[i].bits_per_pixel < bpp)
            {
                format = formats[i].id;
                bpp = formats[i].bits_per_pixel;
                bytes_per_pixel = (bpp == 15) ? 2 : bpp >> 3;
                depth = formats[i].depth;

                this->rshift = get_inv_shift (formats[i].red_mask, bpp);
                this->gshift = get_inv_shift (formats[i].green_mask, bpp);
                this->bshift = get_inv_shift (formats[i].blue_mask, bpp);

                /* Check for red-blue inversion on SiliconMotion drivers */
                if (formats[i].red_mask  == 0x001f &&
                    formats[i].blue_mask == 0x7c00)
                {
                    int copy = this->rshift;
                    this->rshift = this->bshift;
                    this->bshift = copy;
                }

                /* on big-endian Xv still seems to like LSB order */
                if (config->force_inverted_byte_order)
                    S9xSetEndianess (ENDIAN_MSB);
                else
                    S9xSetEndianess (ENDIAN_LSB);
            }
        }
    }