1
0
Fork 0

Add CoglOutput and track for the GLX backend

The CoglOutput object represents one output such as a monitor or
laptop panel, with information about attributes of the output such as
the position of the output within the global coordinate space, and
the refresh rate.

We don't yet publically export the ability to get output information but
we track it for the GLX backend, where we'll use it to track the refresh
rate.

Reviewed-by: Robert Bragg <robert@linux.intel.com>

(cherry picked from commit d7ef9d8d71488d0e6874f1ffc6e48700d5c82a31)
This commit is contained in:
Owen W. Taylor 2012-11-12 11:31:16 -05:00 committed by Robert Bragg
parent 23eca5c793
commit 88d8bd84f2
10 changed files with 859 additions and 10 deletions

View file

@ -114,6 +114,7 @@ cogl_experimental_h = \
$(srcdir)/cogl-onscreen.h \
$(srcdir)/cogl-vector.h \
$(srcdir)/cogl-euler.h \
$(srcdir)/cogl-output.h \
$(srcdir)/cogl-quaternion.h \
$(srcdir)/cogl-matrix-stack.h \
$(srcdir)/cogl-poll.h \
@ -387,6 +388,8 @@ cogl_sources_c = \
$(srcdir)/cogl-framebuffer.c \
$(srcdir)/cogl-onscreen-private.h \
$(srcdir)/cogl-onscreen.c \
$(srcdir)/cogl-output-private.h \
$(srcdir)/cogl-output.c \
$(srcdir)/cogl-profile.h \
$(srcdir)/cogl-profile.c \
$(srcdir)/cogl-flags.h \

View file

@ -0,0 +1,50 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_OUTPUT_PRIVATE_H
#define __COGL_OUTPUT_PRIVATE_H
#include "cogl-output.h"
#include "cogl-object-private.h"
struct _CoglOutput
{
CoglObject _parent;
char *name;
int x; /* Must be first field for _cogl_output_values_equal() */
int y;
int width;
int height;
int mm_width;
int mm_height;
float refresh_rate;
CoglSubpixelOrder subpixel_order;
};
CoglOutput *_cogl_output_new (const char *name);
CoglBool _cogl_output_values_equal (CoglOutput *output,
CoglOutput *other);
#endif /* __COGL_OUTPUT_PRIVATE_H */

110
cogl/cogl-output.c Normal file
View file

@ -0,0 +1,110 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cogl-output-private.h"
#include <string.h>
static void _cogl_output_free (CoglOutput *output);
COGL_OBJECT_DEFINE (Output, output);
CoglOutput *
_cogl_output_new (const char *name)
{
CoglOutput *output;
output = g_slice_new0 (CoglOutput);
output->name = g_strdup (name);
return _cogl_output_object_new (output);
}
static void
_cogl_output_free (CoglOutput *output)
{
g_free (output->name);
g_slice_free (CoglOutput, output);
}
gboolean
_cogl_output_values_equal (CoglOutput *output,
CoglOutput *other)
{
return memcmp ((const char *)output + G_STRUCT_OFFSET (CoglOutput, x),
(const char *)other + G_STRUCT_OFFSET (CoglOutput, x),
sizeof (CoglOutput) - G_STRUCT_OFFSET (CoglOutput, x)) == 0;
}
int
cogl_output_get_x (CoglOutput *output)
{
return output->x;
}
int
cogl_output_get_y (CoglOutput *output)
{
return output->y;
}
int
cogl_output_get_width (CoglOutput *output)
{
return output->width;
}
int
cogl_output_get_height (CoglOutput *output)
{
return output->height;
}
int
cogl_output_get_mm_width (CoglOutput *output)
{
return output->mm_width;
}
int
cogl_output_get_mm_height (CoglOutput *output)
{
return output->mm_height;
}
CoglSubpixelOrder
cogl_output_get_subpixel_order (CoglOutput *output)
{
return output->subpixel_order;
}
float
cogl_output_get_refresh_rate (CoglOutput *output)
{
return output->refresh_rate;
}

242
cogl/cogl-output.h Normal file
View file

@ -0,0 +1,242 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*
*
* Authors:
* Owen Taylor <otaylor@redhat.com>
*/
#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION)
#error "Only <cogl/cogl.h> can be included directly."
#endif
#ifndef __COGL_OUTPUT_H
#define __COGL_OUTPUT_H
#include <cogl/cogl-types.h>
COGL_BEGIN_DECLS
/**
* SECTION:cogl-output
* @short_description: information about an output device
*
* The #CoglOutput object holds information about an output device
* such as a monitor or laptop display. It can be queried to find
* out the position of the output with respect to the screen
* coordinate system and other information such as the resolution
* and refresh rate of the device.
*
* There can be any number of outputs which may overlap: the
* same area of the screen may be displayed by multiple output
* devices.
*
* XXX: though it's possible to query the position of the output
* with respect to screen coordinates, there is currently no way
* of finding out the position of a #CoglOnscreen in screen
* coordinates, at least without using windowing-system specific
* API's, so it's not easy to get the output positions relative
* to the #CoglOnscreen.
*/
typedef struct _CoglOutput CoglOutput;
#define COGL_OUTPUT(X) ((CoglOutput *)(X))
/**
* CoglSubpixelOrder
* @COGL_SUBPIXEL_ORDER_UNKNOWN: the layout of subpixel
* components for the device is unknown.
* @COGL_SUBPIXEL_ORDER_NONE: the device displays colors
* without geometrically-separated subpixel components,
* or the positioning or colors of the components do not
* match any of the values in the enumeration.
* @COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB: the device has
* horizontally arranged components in the order
* red-green-blue from left to right.
* @COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR: the device has
* horizontally arranged components in the order
* blue-green-red from left to right.
* @COGL_SUBPIXEL_ORDER_VERTICAL_RGB: the device has
* vertically arranged components in the order
* red-green-blue from top to bottom.
* @COGL_SUBPIXEL_ORDER_VERTICAL_BGR: the device has
* vertically arranged components in the order
* blue-green-red from top to bottom.
*
* Some output devices (such as LCD panels) display colors
* by making each pixel consist of smaller "subpixels"
* that each have a particular color. By using knowledge
* of the layout of this subpixel components, it is possible
* to create image content with higher resolution than the
* pixel grid.
*
* Since: 1.14
* Stability: unstable
*/
typedef enum {
COGL_SUBPIXEL_ORDER_UNKNOWN,
COGL_SUBPIXEL_ORDER_NONE,
COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB,
COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR,
COGL_SUBPIXEL_ORDER_VERTICAL_RGB,
COGL_SUBPIXEL_ORDER_VERTICAL_BGR
} CoglSubpixelOrder;
/**
* cogl_is_output:
* @object: A #CoglObject pointer
*
* Gets whether the given object references a #CoglOutput.
*
* Return value: %TRUE if the object references a #CoglOutput
* and %FALSE otherwise.
* Since: 1.14
* Stability: unstable
*/
CoglBool
cogl_is_output (void *object);
/**
* cogl_output_get_x:
* @output: a #CoglOutput
*
* Gets the X position of the output with respect to the coordinate
* system of the screen.
*
* Return value: the X position of the output as a pixel offset
* from the left side of the screen coordinate space
* Since: 1.14
* Stability: unstable
*/
int
cogl_output_get_x (CoglOutput *output);
/**
* cogl_output_get_y:
* @output: a #CoglOutput
*
* Gets the Y position of the output with respect to the coordinate
* system of the screen.
*
* Return value: the Y position of the output as a pixel offset
* from the top side of the screen coordinate space
* Since: 1.14
* Stability: unstable
*/
int
cogl_output_get_y (CoglOutput *output);
/**
* cogl_output_get_width:
* @output: a #CoglOutput
*
* Gets the width of the output in pixels.
*
* Return value: the width of the output in pixels
* Since: 1.14
* Stability: unstable
*/
int
cogl_output_get_width (CoglOutput *output);
/**
* cogl_output_get_height:
* @output: a #CoglOutput
*
* Gets the height of the output in pixels.
*
* Return value: the height of the output in pixels
* Since: 1.14
* Stability: unstable
*/
int
cogl_output_get_height (CoglOutput *output);
/**
* cogl_output_get_mm_width:
* @output: a #CoglOutput
*
* Gets the physical width of the output. In some cases (such as
* as a projector), the value returned here might correspond to
* nominal resolution rather than the actual physical size of the
* output device.
*
* Return value: the height of the output in millimeters. A value
* of 0 indicates the width is unknown
* Since: 1.14
* Stability: unstable
*/
int
cogl_output_get_mm_width (CoglOutput *output);
/**
* cogl_output_get_mm_height:
* @output: a #CoglOutput
*
* Gets the physical height of the output. In some cases (such as
* as a projector), the value returned here might correspond to
* nominal resolution rather than the actual physical size of the
* output device.
*
* Return value: the height of the output in millimeters. A value
* of 0 indicates that the height is unknown
* Since: 1.14
* Stability: unstable
*/
int
cogl_output_get_mm_height (CoglOutput *output);
/**
* cogl_output_get_subpixel_order:
* @output: a #CoglOutput
*
* For an output device where each pixel is made up of smaller components
* with different colors, returns the layout of the subpixel
* components.
*
* Return value: the order of subpixel components for the output device
* Since: 1.14
* Stability: unstable
*/
CoglSubpixelOrder
cogl_output_get_subpixel_order (CoglOutput *output);
/**
* cogl_output_get_refresh_rate:
* @output: a #CoglOutput
*
* Gets the number of times per second that the output device refreshes
* the display contents.
*
* Return value: the refresh rate of the output device. A value of zero
* indicates that the refresh rate is unknown.
* Since: 1.14
* Stability: unstable
*/
float
cogl_output_get_refresh_rate (CoglOutput *output);
COGL_END_DECLS
#endif /* __COGL_OUTPUT_H */

View file

@ -50,6 +50,8 @@ struct _CoglRenderer
CoglWinsysID winsys_id_override;
GList *constraints;
GList *outputs;
#ifdef COGL_HAS_XLIB_SUPPORT
Display *foreign_xdpy;
CoglBool xlib_enable_event_retrieval;

View file

@ -28,6 +28,7 @@
#include "cogl-xlib-private.h"
#include "cogl-x11-renderer-private.h"
#include "cogl-context.h"
#include "cogl-output.h"
typedef struct _CoglXlibRenderer
{
@ -41,6 +42,8 @@ typedef struct _CoglXlibRenderer
/* A poll FD for handling event retrieval within Cogl */
CoglPollFD poll_fd;
unsigned long outputs_update_serial;
} CoglXlibRenderer;
CoglBool
@ -92,4 +95,11 @@ _cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds,
int n_poll_fds);
CoglOutput *
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
int x,
int y,
int width,
int height);
#endif /* __COGL_RENDERER_XLIB_PRIVATE_H */

View file

@ -32,6 +32,7 @@
#include "cogl-util.h"
#include "cogl-object.h"
#include "cogl-output-private.h"
#include "cogl-renderer-private.h"
#include "cogl-xlib-renderer-private.h"
#include "cogl-x11-renderer-private.h"
@ -40,8 +41,10 @@
#include <X11/Xlib.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrandr.h>
#include <stdlib.h>
#include <string.h>
static char *_cogl_x11_display_name = NULL;
static GList *_cogl_xlib_renderers = NULL;
@ -190,6 +193,280 @@ assert_xlib_display (CoglRenderer *renderer, CoglError **error)
return xdpy;
}
static int
compare_outputs (CoglOutput *a,
CoglOutput *b)
{
return strcmp (a->name, b->name);
}
#define CSO(X) COGL_SUBPIXEL_ORDER_ ## X
static CoglSubpixelOrder subpixel_map[6][6] = {
{ CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR),
CSO(VERTICAL_RGB), CSO(VERTICAL_BGR) }, /* 0 */
{ CSO(UNKNOWN), CSO(NONE), CSO(VERTICAL_RGB), CSO(VERTICAL_BGR),
CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB) }, /* 90 */
{ CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB),
CSO(VERTICAL_BGR), CSO(VERTICAL_RGB) }, /* 180 */
{ CSO(UNKNOWN), CSO(NONE), CSO(VERTICAL_BGR), CSO(VERTICAL_RGB),
CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR) }, /* 270 */
{ CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB),
CSO(VERTICAL_RGB), CSO(VERTICAL_BGR) }, /* Reflect_X */
{ CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR),
CSO(VERTICAL_BGR), CSO(VERTICAL_RGB) }, /* Reflect_Y */
};
#undef CSO
static void
update_outputs (CoglRenderer *renderer,
CoglBool notify)
{
CoglXlibRenderer *xlib_renderer =
_cogl_xlib_renderer_get_data (renderer);
XRRScreenResources *resources;
CoglXlibTrapState state;
CoglBool error = FALSE;
GList *new_outputs = NULL;
GList *l, *m;
CoglBool changed = FALSE;
int i;
xlib_renderer->outputs_update_serial = XNextRequest (xlib_renderer->xdpy);
resources = XRRGetScreenResources (xlib_renderer->xdpy,
DefaultRootWindow (xlib_renderer->xdpy));
_cogl_xlib_renderer_trap_errors (renderer, &state);
for (i = 0; i < resources->ncrtc && !error; i++)
{
XRRCrtcInfo *crtc_info = NULL;
XRROutputInfo *output_info = NULL;
CoglOutput *output;
float refresh_rate = 0;
int j;
crtc_info = XRRGetCrtcInfo (xlib_renderer->xdpy,
resources, resources->crtcs[i]);
if (crtc_info == NULL)
{
error = TRUE;
goto next;
}
if (crtc_info->mode == None)
goto next;
for (j = 0; j < resources->nmode; j++)
{
if (resources->modes[j].id == crtc_info->mode)
refresh_rate = (resources->modes[j].dotClock /
((float)resources->modes[j].hTotal *
resources->modes[j].vTotal));
}
output_info = XRRGetOutputInfo (xlib_renderer->xdpy,
resources,
crtc_info->outputs[0]);
if (output_info == NULL)
{
error = TRUE;
goto next;
}
output = _cogl_output_new (output_info->name);
output->x = crtc_info->x;
output->y = crtc_info->y;
output->width = crtc_info->width;
output->height = crtc_info->height;
if ((crtc_info->rotation & (RR_Rotate_90 | RR_Rotate_270)) != 0)
{
output->mm_width = output_info->mm_height;
output->mm_height = output_info->mm_width;
}
else
{
output->mm_width = output_info->mm_width;
output->mm_height = output_info->mm_height;
}
output->refresh_rate = refresh_rate;
switch (output_info->subpixel_order)
{
case SubPixelUnknown:
default:
output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
break;
case SubPixelNone:
output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
break;
case SubPixelHorizontalRGB:
output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
break;
case SubPixelHorizontalBGR:
output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR;
break;
case SubPixelVerticalRGB:
output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB;
break;
case SubPixelVerticalBGR:
output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR;
break;
}
output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
/* Handle the effect of rotation and reflection on subpixel order (ugh) */
for (j = 0; j < 6; j++)
{
if ((crtc_info->rotation & (1 << j)) != 0)
output->subpixel_order = subpixel_map[j][output->subpixel_order];
}
new_outputs = g_list_prepend (new_outputs, output);
next:
if (crtc_info != NULL)
XFree (crtc_info);
if (output_info != NULL)
XFree (output_info);
}
XFree (resources);
if (!error)
{
new_outputs = g_list_sort (new_outputs, (GCompareFunc)compare_outputs);
l = new_outputs;
m = renderer->outputs;
while (l || m)
{
int cmp;
CoglOutput *output_l = l ? (CoglOutput *)l->data : NULL;
CoglOutput *output_m = m ? (CoglOutput *)m->data : NULL;
if (l && m)
cmp = compare_outputs (output_l, output_m);
else if (l)
cmp = -1;
else
cmp = 1;
if (cmp == 0)
{
GList *m_next = m->next;
if (!_cogl_output_values_equal (output_l, output_m))
{
renderer->outputs = g_list_remove_link (renderer->outputs, m);
renderer->outputs = g_list_insert_before (renderer->outputs,
m_next, output_l);
cogl_object_ref (output_l);
changed = TRUE;
}
l = l->next;
m = m_next;
}
else if (cmp < 0)
{
renderer->outputs =
g_list_insert_before (renderer->outputs, m, output_l);
cogl_object_ref (output_l);
changed = TRUE;
l = l->next;
}
else
{
GList *m_next = m->next;
renderer->outputs = g_list_remove_link (renderer->outputs, m);
changed = TRUE;
m = m_next;
}
}
}
g_list_free_full (new_outputs, (GDestroyNotify)cogl_object_unref);
_cogl_xlib_renderer_untrap_errors (renderer, &state);
if (changed)
{
const CoglWinsysVtable *winsys = renderer->winsys_vtable;
if (notify)
COGL_NOTE (WINSYS, "Outputs changed:");
else
COGL_NOTE (WINSYS, "Outputs:");
for (l = renderer->outputs; l; l = l->next)
{
CoglOutput *output = l->data;
const char *subpixel_string;
switch (output->subpixel_order)
{
case COGL_SUBPIXEL_ORDER_UNKNOWN:
default:
subpixel_string = "unknown";
break;
case COGL_SUBPIXEL_ORDER_NONE:
subpixel_string = "none";
break;
case COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB:
subpixel_string = "horizontal_rgb";
break;
case COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR:
subpixel_string = "horizontal_bgr";
break;
case COGL_SUBPIXEL_ORDER_VERTICAL_RGB:
subpixel_string = "vertical_rgb";
break;
case COGL_SUBPIXEL_ORDER_VERTICAL_BGR:
subpixel_string = "vertical_bgr";
break;
}
COGL_NOTE (WINSYS,
" %10s: +%d+%dx%dx%d mm=%dx%d dpi=%.1fx%.1f "
"subpixel_order=%s refresh_rate=%.3f",
output->name,
output->x, output->y, output->width, output->height,
output->mm_width, output->mm_height,
output->width / (output->mm_width / 25.4),
output->height / (output->mm_height / 25.4),
subpixel_string,
output->refresh_rate);
}
if (notify && winsys->renderer_outputs_changed != NULL)
winsys->renderer_outputs_changed (renderer);
}
}
static CoglFilterReturn
randr_filter (XEvent *event,
void *data)
{
CoglRenderer *renderer = data;
CoglXlibRenderer *xlib_renderer =
_cogl_xlib_renderer_get_data (renderer);
CoglX11Renderer *x11_renderer =
(CoglX11Renderer *) xlib_renderer;
if (x11_renderer->randr_base != -1 &&
(event->xany.type == x11_renderer->randr_base + RRScreenChangeNotify ||
event->xany.type == x11_renderer->randr_base + RRNotify) &&
event->xany.serial >= xlib_renderer->outputs_update_serial)
update_outputs (renderer, TRUE);
return COGL_FILTER_CONTINUE;
}
CoglBool
_cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error)
{
@ -198,6 +475,7 @@ _cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error)
CoglX11Renderer *x11_renderer =
(CoglX11Renderer *) xlib_renderer;
int damage_error;
int randr_error;
if (!assert_xlib_display (renderer, error))
return FALSE;
@ -211,13 +489,30 @@ _cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error)
&damage_error))
x11_renderer->damage_base = -1;
/* Check whether randr is supported on this display */
if (!XRRQueryExtension (xlib_renderer->xdpy,
&x11_renderer->randr_base,
&randr_error))
x11_renderer->randr_base = -1;
xlib_renderer->trap_state = NULL;
xlib_renderer->poll_fd.fd = ConnectionNumber (xlib_renderer->xdpy);
xlib_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN;
XRRSelectInput(xlib_renderer->xdpy,
DefaultRootWindow (xlib_renderer->xdpy),
RRScreenChangeNotifyMask
| RRCrtcChangeNotifyMask
| RROutputPropertyNotifyMask);
update_outputs (renderer, FALSE);
register_xlib_renderer (renderer);
cogl_xlib_renderer_add_filter (renderer,
randr_filter,
renderer);
return TRUE;
}
@ -227,6 +522,9 @@ _cogl_xlib_renderer_disconnect (CoglRenderer *renderer)
CoglXlibRenderer *xlib_renderer =
_cogl_xlib_renderer_get_data (renderer);
g_list_free_full (renderer->outputs, (GDestroyNotify)cogl_object_unref);
renderer->outputs = NULL;
if (!renderer->foreign_xdpy && xlib_renderer->xdpy)
XCloseDisplay (xlib_renderer->xdpy);
@ -312,3 +610,39 @@ _cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer,
cogl_xlib_renderer_handle_event (renderer, &xevent);
}
}
CoglOutput *
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
int x,
int y,
int width,
int height)
{
int max_overlap = 0;
CoglOutput *max_overlapped = NULL;
GList *l;
int xa1 = x, xa2 = x + width;
int ya1 = y, ya2 = y + height;
for (l = renderer->outputs; l; l = l->next)
{
CoglOutput *output = l->data;
int xb1 = output->x, xb2 = output->x + output->width;
int yb1 = output->y, yb2 = output->y + output->height;
int overlap_x = MIN(xa2, xb2) - MAX(xa1, xb1);
int overlap_y = MIN(ya2, yb2) - MAX(ya1, yb1);
if (overlap_x > 0 && overlap_y > 0)
{
int overlap = overlap_x * overlap_y;
if (overlap > max_overlap)
{
max_overlap = overlap;
max_overlapped = output;
}
}
}
return max_overlapped;
}

View file

@ -71,7 +71,9 @@ typedef struct _CoglContextGLX
typedef struct _CoglOnscreenXlib
{
Window xwin;
int x, y;
CoglBool is_foreign_xwin;
CoglOutput *output;
} CoglOnscreenXlib;
typedef struct _CoglOnscreenGLX
@ -189,29 +191,84 @@ notify_swap_buffers (CoglContext *context, GLXDrawable drawable)
}
static void
notify_resize (CoglContext *context,
GLXDrawable drawable,
int width,
int height)
update_output (CoglOnscreen *onscreen)
{
CoglOnscreen *onscreen = find_onscreen_for_xid (context, drawable);
CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *context = framebuffer->context;
CoglDisplay *display = context->display;
CoglOutput *output;
int width, height;
width = cogl_framebuffer_get_width (framebuffer);
height = cogl_framebuffer_get_height (framebuffer);
output = _cogl_xlib_renderer_output_for_rectangle (display->renderer,
xlib_onscreen->x,
xlib_onscreen->y,
width, height);
if (xlib_onscreen->output != output)
{
if (xlib_onscreen->output)
cogl_object_unref (xlib_onscreen->output);
xlib_onscreen->output = output;
if (output)
cogl_object_ref (xlib_onscreen->output);
}
}
static void
notify_resize (CoglContext *context,
XConfigureEvent *configure_event)
{
CoglOnscreen *onscreen = find_onscreen_for_xid (context,
configure_event->window);
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglDisplay *display = context->display;
CoglGLXDisplay *glx_display = display->winsys;
CoglOnscreenGLX *glx_onscreen;
CoglOnscreenXlib *xlib_onscreen;
if (!onscreen)
return;
glx_onscreen = onscreen->winsys;
xlib_onscreen = onscreen->winsys;
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
_cogl_framebuffer_winsys_update_size (framebuffer,
configure_event->width,
configure_event->height);
/* We only want to notify that a resize happened when the
application calls cogl_context_dispatch so instead of immediately
notifying we'll set a flag to remember to notify later */
glx_display->pending_resize_notify = TRUE;
glx_onscreen->pending_resize_notify = TRUE;
if (!xlib_onscreen->is_foreign_xwin)
{
int x, y;
if (configure_event->send_event)
{
x = configure_event->x;
y = configure_event->y;
}
else
{
Window child;
XTranslateCoordinates (configure_event->display,
configure_event->window,
DefaultRootWindow (configure_event->display),
0, 0, &x, &y, &child);
}
xlib_onscreen->x = x;
xlib_onscreen->y = y;
update_output (onscreen);
}
}
static CoglFilterReturn
@ -225,9 +282,7 @@ glx_event_filter_cb (XEvent *xevent, void *data)
if (xevent->type == ConfigureNotify)
{
notify_resize (context,
xevent->xconfigure.window,
xevent->xconfigure.width,
xevent->xconfigure.height);
&xevent->xconfigure);
/* we let ConfigureNotify pass through */
return COGL_FILTER_CONTINUE;
@ -263,6 +318,38 @@ _cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
g_slice_free (CoglGLXRenderer, renderer->winsys);
}
static CoglBool
update_all_outputs (CoglRenderer *renderer)
{
GList *l;
_COGL_GET_CONTEXT (context, FALSE);
if (context->display == NULL) /* during connection */
return FALSE;
if (context->display->renderer != renderer)
return FALSE;
for (l = context->framebuffers; l; l = l->next)
{
CoglFramebuffer *framebuffer = l->data;
if (framebuffer->type != COGL_FRAMEBUFFER_TYPE_ONSCREEN)
continue;
update_output (COGL_ONSCREEN (framebuffer));
}
return TRUE;
}
static void
_cogl_winsys_renderer_outputs_changed (CoglRenderer *renderer)
{
update_all_outputs (renderer);
}
static CoglBool
resolve_core_glx_functions (CoglRenderer *renderer,
CoglError **error)
@ -1060,6 +1147,12 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
if (glx_onscreen == NULL)
return;
if (xlib_onscreen->output != NULL)
{
cogl_object_unref (xlib_onscreen->output);
xlib_onscreen->output = NULL;
}
_cogl_xlib_renderer_trap_errors (context->display->renderer, &old_state);
drawable =
@ -2206,6 +2299,7 @@ static CoglWinsysVtable _cogl_winsys_vtable =
.renderer_get_proc_address = _cogl_winsys_renderer_get_proc_address,
.renderer_connect = _cogl_winsys_renderer_connect,
.renderer_disconnect = _cogl_winsys_renderer_disconnect,
.renderer_outputs_changed = _cogl_winsys_renderer_outputs_changed,
.display_setup = _cogl_winsys_display_setup,
.display_destroy = _cogl_winsys_display_destroy,
.context_init = _cogl_winsys_context_init,

View file

@ -83,6 +83,9 @@ typedef struct _CoglWinsysVtable
void
(*renderer_disconnect) (CoglRenderer *renderer);
void
(*renderer_outputs_changed) (CoglRenderer *renderer);
CoglBool
(*display_setup) (CoglDisplay *display, CoglError **error);

View file

@ -90,6 +90,7 @@ m4_define([uprof_req_version], [0.3])
m4_define([gtk_doc_req_version], [1.13])
m4_define([xfixes_req_version], [3])
m4_define([xcomposite_req_version], [0.4])
m4_define([xrandr_req_version], [1.2])
m4_define([cairo_req_version], [1.10])
dnl These variables get copied into the generated README
@ -1073,7 +1074,7 @@ dnl Check X11 dependencies if required
dnl ========================================================
AS_IF([test "x$NEED_XLIB" = "xyes"],
[
X11_MODULES="x11 xext xfixes >= xfixes_req_version xdamage xcomposite >= xcomposite_req_version"
X11_MODULES="x11 xext xfixes >= xfixes_req_version xdamage xcomposite >= xcomposite_req_version xrandr >= xrandr_req_version"
PKG_CHECK_MODULES(DUMMY, [$X11_MODULES],
[COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES $X11_MODULES"])
SUPPORT_X11=yes