Merge remote-tracking branch 'anholt/glamor-next'

This commit is contained in:
Keith Packard 2014-07-17 20:06:21 -07:00
commit 5c2e9fa3d6
55 changed files with 3054 additions and 3243 deletions

View File

@ -7,20 +7,21 @@ AM_CFLAGS = $(CWARNFLAGS) $(DIX_CFLAGS) $(GLAMOR_CFLAGS)
libglamor_la_SOURCES = \
glamor.c \
glamor_context.h \
glamor_copyarea.c \
glamor_copywindow.c \
glamor_copy.c \
glamor_core.c \
glamor_dash.c \
glamor_debug.h \
glamor_fill.c \
glamor_font.c \
glamor_font.h \
glamor_glx.c \
glamor_glyphs.c \
glamor_polylines.c \
glamor_segment.c \
glamor_image.c \
glamor_lines.c \
glamor_segs.c \
glamor_render.c \
glamor_gradient.c \
glamor_prepare.c \
glamor_prepare.h \
glamor_program.c \
glamor_program.h \
glamor_rects.c \
@ -31,10 +32,8 @@ libglamor_la_SOURCES = \
glamor_transform.c \
glamor_transform.h \
glamor_trapezoid.c \
glamor_tile.c \
glamor_triangles.c\
glamor_addtraps.c\
glamor_copyplane.c\
glamor_glyphblt.c\
glamor_points.c\
glamor_priv.h\
@ -45,7 +44,9 @@ libglamor_la_SOURCES = \
glamor_window.c\
glamor_fbo.c\
glamor_compositerects.c\
glamor_utils.c\
glamor_utils.h\
glamor_xv.c \
glamor.h
libglamor_egl_stubs_la_SOURCES = glamor_egl_stubs.c

View File

@ -35,10 +35,9 @@
#include "glamor_priv.h"
static DevPrivateKeyRec glamor_screen_private_key_index;
DevPrivateKey glamor_screen_private_key = &glamor_screen_private_key_index;
static DevPrivateKeyRec glamor_pixmap_private_key_index;
DevPrivateKey glamor_pixmap_private_key = &glamor_pixmap_private_key_index;
DevPrivateKeyRec glamor_screen_private_key;
DevPrivateKeyRec glamor_pixmap_private_key;
DevPrivateKeyRec glamor_gc_private_key;
/**
* glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable.
@ -68,7 +67,7 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type)
glamor_get_screen_private(pixmap->drawable.pScreen);
pixmap_priv = dixLookupPrivate(&pixmap->devPrivates,
glamor_pixmap_private_key);
&glamor_pixmap_private_key);
if (pixmap_priv == NULL) {
pixmap_priv = calloc(sizeof(*pixmap_priv), 1);
glamor_set_pixmap_private(pixmap, pixmap_priv);
@ -251,11 +250,6 @@ glamor_block_handler(ScreenPtr screen)
glamor_priv->tick++;
glFlush();
glamor_fbo_expire(glamor_priv);
if (glamor_priv->state == RENDER_STATE
&& glamor_priv->render_idle_cnt++ > RENDER_IDEL_MAX) {
glamor_priv->state = IDLE_STATE;
glamor_priv->render_idle_cnt = 0;
}
}
static void
@ -330,13 +324,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
return FALSE;
glamor_priv->flags = flags;
if (flags & GLAMOR_INVERTED_Y_AXIS) {
glamor_priv->yInverted = TRUE;
}
else
glamor_priv->yInverted = FALSE;
if (!dixRegisterPrivateKey(glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
LogMessage(X_WARNING,
"glamor%d: Failed to allocate screen private\n",
screen->myNum);
@ -345,11 +334,19 @@ glamor_init(ScreenPtr screen, unsigned int flags)
glamor_set_screen_private(screen, glamor_priv);
if (!dixRegisterPrivateKey(glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) {
if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) {
LogMessage(X_WARNING,
"glamor%d: Failed to allocate pixmap private\n",
screen->myNum);
goto fail;;
goto fail;
}
if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC,
sizeof (glamor_gc_private))) {
LogMessage(X_WARNING,
"glamor%d: Failed to allocate gc private\n",
screen->myNum);
goto fail;
}
if (epoxy_is_desktop_gl())
@ -398,6 +395,10 @@ glamor_init(ScreenPtr screen, unsigned int flags)
}
}
glamor_priv->has_rw_pbo = FALSE;
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
glamor_priv->has_rw_pbo = TRUE;
glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug");
glamor_priv->has_pack_invert =
epoxy_has_gl_extension("GL_MESA_pack_invert");
@ -407,6 +408,10 @@ glamor_init(ScreenPtr screen, unsigned int flags)
epoxy_has_gl_extension("GL_ARB_map_buffer_range");
glamor_priv->has_buffer_storage =
epoxy_has_gl_extension("GL_ARB_buffer_storage");
glamor_priv->has_nv_texture_barrier =
epoxy_has_gl_extension("GL_NV_texture_barrier");
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]);
@ -505,8 +510,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
glamor_init_vbo(screen);
glamor_init_pixmap_fbo(screen);
glamor_init_solid_shader(screen);
glamor_init_tile_shader(screen);
#ifdef GLAMOR_TRAPEZOID_SHADER
glamor_init_trapezoid_shader(screen);
#endif
@ -538,8 +541,6 @@ glamor_release_screen_priv(ScreenPtr screen)
#endif
glamor_fini_vbo(screen);
glamor_fini_pixmap_fbo(screen);
glamor_fini_solid_shader(screen);
glamor_fini_tile_shader(screen);
#ifdef GLAMOR_TRAPEZOID_SHADER
glamor_fini_trapezoid_shader(screen);
#endif
@ -559,7 +560,7 @@ glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv)
glamor_pixmap_private *old_priv;
glamor_pixmap_fbo *fbo;
old_priv = dixGetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key);
old_priv = dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key);
if (priv) {
assert(old_priv == NULL);
@ -572,7 +573,7 @@ glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv)
free(old_priv);
}
dixSetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key, priv);
dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key, priv);
}
Bool

View File

@ -63,7 +63,7 @@ typedef enum glamor_pixmap_type {
} glamor_pixmap_type_t;
#define GLAMOR_EGL_EXTERNAL_BUFFER 3
#define GLAMOR_INVERTED_Y_AXIS 1
#define GLAMOR_INVERTED_Y_AXIS 1 /* compat stub */
#define GLAMOR_USE_SCREEN (1 << 1)
#define GLAMOR_USE_PICTURE_SCREEN (1 << 2)
#define GLAMOR_USE_EGL_SCREEN (1 << 3)
@ -79,12 +79,6 @@ typedef enum glamor_pixmap_type {
* @screen: Current screen pointer.
* @flags: Please refer the flags description above.
*
* @GLAMOR_INVERTED_Y_AXIS:
* set 1 means the GL env's origin (0,0) is at top-left.
* EGL/DRM platform is an example need to set this bit.
* glx platform's origin is at bottom-left thus need to
* clear this bit.
*
* @GLAMOR_USE_SCREEN:
* If running in an pre-existing X environment, and the
* gl context is GLX, then you should set this bit and
@ -321,6 +315,10 @@ extern _X_EXPORT int glamor_create_gc(GCPtr gc);
extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes,
DrawablePtr drawable);
extern _X_EXPORT void glamor_destroy_gc(GCPtr gc);
#define HAS_GLAMOR_DESTROY_GC 1
extern Bool _X_EXPORT glamor_change_window_attributes(WindowPtr pWin, unsigned long mask);
extern void _X_EXPORT glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_region);
@ -354,6 +352,17 @@ extern _X_EXPORT Bool glamor_copy_n_to_n_nf(DrawablePtr src,
Bool upsidedown, Pixel bitplane,
void *closure);
extern _X_EXPORT Bool glamor_copy_nf(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown, Pixel bitplane,
void *closure);
extern _X_EXPORT Bool glamor_composite_nf(CARD8 op,
PicturePtr source,
PicturePtr mask,

693
glamor/glamor_copy.c Normal file
View File

@ -0,0 +1,693 @@
/*
* Copyright © 2014 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
#include "glamor_transfer.h"
#include "glamor_prepare.h"
#include "glamor_transform.h"
struct copy_args {
PixmapPtr src_pixmap;
glamor_pixmap_fbo *src;
uint32_t bitplane;
int dx, dy;
};
static Bool
use_copyarea(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg)
{
struct copy_args *args = arg;
glamor_pixmap_fbo *src = args->src;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, src->tex);
glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
glUniform2f(prog->fill_size_uniform, src->width, src->height);
return TRUE;
}
static const glamor_facet glamor_facet_copyarea = {
"copy_area",
.vs_vars = "attribute vec2 primitive;\n",
.vs_exec = (GLAMOR_POS(gl_Position, primitive.xy)
" fill_pos = (fill_offset + primitive.xy) / fill_size;\n"),
.fs_exec = " gl_FragColor = texture2D(sampler, fill_pos);\n",
.locations = glamor_program_location_fill,
.use = use_copyarea,
};
/*
* Configure the copy plane program for the current operation
*/
static Bool
use_copyplane(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg)
{
struct copy_args *args = arg;
glamor_pixmap_fbo *src = args->src;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, src->tex);
glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
glUniform2f(prog->fill_size_uniform, src->width, src->height);
glamor_set_color(dst, gc->fgPixel, prog->fg_uniform);
glamor_set_color(dst, gc->bgPixel, prog->bg_uniform);
/* XXX handle 2 10 10 10 and 1555 formats; presumably the pixmap private knows this? */
switch (args->src_pixmap->drawable.depth) {
case 24:
glUniform4ui(prog->bitplane_uniform,
(args->bitplane >> 16) & 0xff,
(args->bitplane >> 8) & 0xff,
(args->bitplane ) & 0xff,
0);
glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0);
break;
case 32:
glUniform4ui(prog->bitplane_uniform,
(args->bitplane >> 16) & 0xff,
(args->bitplane >> 8) & 0xff,
(args->bitplane ) & 0xff,
(args->bitplane >> 24) & 0xff);
glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0xff);
break;
case 16:
glUniform4ui(prog->bitplane_uniform,
(args->bitplane >> 11) & 0x1f,
(args->bitplane >> 5) & 0x3f,
(args->bitplane ) & 0x1f,
0);
glUniform4f(prog->bitmul_uniform, 0x1f, 0x3f, 0x1f, 0);
break;
case 15:
glUniform4ui(prog->bitplane_uniform,
(args->bitplane >> 10) & 0x1f,
(args->bitplane >> 5) & 0x1f,
(args->bitplane ) & 0x1f,
0);
glUniform4f(prog->bitmul_uniform, 0x1f, 0x1f, 0x1f, 0);
break;
case 8:
glUniform4ui(prog->bitplane_uniform,
0, 0, 0, args->bitplane);
glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff);
break;
case 1:
glUniform4ui(prog->bitplane_uniform,
0, 0, 0, args->bitplane);
glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff);
break;
}
return TRUE;
}
static const glamor_facet glamor_facet_copyplane = {
"copy_plane",
.version = 130,
.vs_vars = "attribute vec2 primitive;\n",
.vs_exec = (GLAMOR_POS(gl_Position, (primitive.xy))
" fill_pos = (fill_offset + primitive.xy) / fill_size;\n"),
.fs_exec = (" uvec4 bits = uvec4(round(texture2D(sampler, fill_pos) * bitmul));\n"
" if ((bits & bitplane) != uvec4(0,0,0,0))\n"
" gl_FragColor = fg;\n"
" else\n"
" gl_FragColor = bg;\n"),
.locations = glamor_program_location_fill|glamor_program_location_fg|glamor_program_location_bg|glamor_program_location_bitplane,
.use = use_copyplane,
};
/*
* When all else fails, pull the bits out of the GPU and do the
* operation with fb
*/
static void
glamor_copy_bail(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
if (bitplane) {
if (src->bitsPerPixel > 1)
fbCopyNto1(src, dst, gc, box, nbox, dx, dy,
reverse, upsidedown, bitplane, closure);
else
fbCopy1toN(src, dst, gc, box, nbox, dx, dy,
reverse, upsidedown, bitplane, closure);
} else {
fbCopyNtoN(src, dst, gc, box, nbox, dx, dy,
reverse, upsidedown, bitplane, closure);
}
}
glamor_finish_access(dst);
glamor_finish_access(src);
}
/**
* Implements CopyPlane and CopyArea from the GPU to the GPU by using
* the source as a texture and painting that into the destination.
*
* This requires that source and dest are different textures, or that
* (if the copy area doesn't overlap), GL_NV_texture_barrier is used
* to ensure that the caches are flushed at the right times.
*/
static Bool
glamor_copy_cpu_fbo(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
ScreenPtr screen = dst->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
FbBits *src_bits;
FbStride src_stride;
int src_bpp;
int src_xoff, src_yoff;
int dst_xoff, dst_yoff;
if (gc && gc->alu != GXcopy)
goto bail;
if (gc && !glamor_pm_is_solid(dst, gc->planemask))
goto bail;
glamor_make_current(glamor_priv);
glamor_prepare_access(src, GLAMOR_ACCESS_RO);
glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff);
fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, src_yoff);
glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff + dx, src_yoff + dy,
dst_xoff, dst_yoff,
(uint8_t *) src_bits, src_stride * sizeof (FbBits));
glamor_finish_access(src);
return TRUE;
bail:
return FALSE;
}
/*
* Copy from GPU to GPU by using the source
* as a texture and painting that into the destination
*/
static Bool
glamor_copy_fbo_fbo_draw(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
ScreenPtr screen = dst->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
int src_box_x, src_box_y, dst_box_x, dst_box_y;
int dst_off_x, dst_off_y;
int src_off_x, src_off_y;
GLshort *v;
char *vbo_offset;
struct copy_args args;
glamor_program *prog;
const glamor_facet *copy_facet;
Bool set_scissor;
int n;
glamor_make_current(glamor_priv);
if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask))
goto bail_ctx;
if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
goto bail_ctx;
if (bitplane) {
prog = &glamor_priv->copy_plane_prog;
copy_facet = &glamor_facet_copyplane;
} else {
prog = &glamor_priv->copy_area_prog;
copy_facet = &glamor_facet_copyarea;
}
if (prog->failed)
goto bail_ctx;
if (!prog->prog) {
if (!glamor_build_program(screen, prog,
copy_facet, NULL))
goto bail_ctx;
}
args.src_pixmap = src_pixmap;
args.bitplane = bitplane;
/* Set up the vertex buffers for the points */
v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
2 * sizeof (GLshort), vbo_offset);
for (n = 0; n < nbox; n++) {
v[0] = box->x1; v[1] = box->y1;
v[2] = box->x1; v[3] = box->y2;
v[4] = box->x2; v[5] = box->y2;
v[6] = box->x2; v[7] = box->y1;
v += 8;
box++;
}
glamor_put_vbo_space(screen);
glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
set_scissor = src_priv->type == GLAMOR_TEXTURE_LARGE;
if (set_scissor)
glEnable(GL_SCISSOR_TEST);
glamor_pixmap_loop(src_priv, src_box_x, src_box_y) {
BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_x, src_box_y);
args.dx = dx + src_off_x - src_box->x1;
args.dy = dy + src_off_y - src_box->y1;
args.src = glamor_pixmap_fbo_at(src_priv, src_box_x, src_box_y);
if (!glamor_use_program(dst_pixmap, gc, prog, &args))
goto bail_ctx;
glamor_pixmap_loop(dst_priv, dst_box_x, dst_box_y) {
glamor_set_destination_drawable(dst, dst_box_x, dst_box_y, FALSE, FALSE,
prog->matrix_uniform, &dst_off_x, &dst_off_y);
if (set_scissor)
glScissor(dst_off_x - args.dx,
dst_off_y - args.dy,
src_box->x2 - src_box->x1,
src_box->y2 - src_box->y1);
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
glDrawArrays(GL_QUADS, 0, nbox * 4);
else {
int i;
for (i = 0; i < nbox; i++)
glDrawArrays(GL_TRIANGLE_FAN, i*4, 4);
}
}
}
if (set_scissor)
glDisable(GL_SCISSOR_TEST);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
glDisable(GL_COLOR_LOGIC_OP);
return TRUE;
bail_ctx:
glDisable(GL_COLOR_LOGIC_OP);
return FALSE;
}
/**
* Copies from the GPU to the GPU using a temporary pixmap in between,
* to correctly handle overlapping copies.
*/
static Bool
glamor_copy_fbo_fbo_temp(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
ScreenPtr screen = dst->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
PixmapPtr tmp_pixmap;
BoxRec bounds;
int n;
BoxPtr tmp_box;
if (nbox == 0)
return TRUE;
/* Sanity check state to avoid getting halfway through and bailing
* at the last second. Might be nice to have checks that didn't
* involve setting state.
*/
glamor_make_current(glamor_priv);
if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask))
goto bail_ctx;
if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
goto bail_ctx;
glDisable(GL_COLOR_LOGIC_OP);
/* Find the size of the area to copy
*/
bounds = box[0];
for (n = 1; n < nbox; n++) {
bounds.x1 = min(bounds.x1, box[n].x1);
bounds.x2 = max(bounds.x2, box[n].x2);
bounds.y1 = min(bounds.y1, box[n].y1);
bounds.y2 = max(bounds.y2, box[n].y2);
}
/* Allocate a suitable temporary pixmap
*/
tmp_pixmap = glamor_create_pixmap(screen,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1,
src->depth, 0);
if (!tmp_pixmap)
goto bail;
tmp_box = calloc(nbox, sizeof (BoxRec));
if (!tmp_box)
goto bail_pixmap;
/* Convert destination boxes into tmp pixmap boxes
*/
for (n = 0; n < nbox; n++) {
tmp_box[n].x1 = box[n].x1 - bounds.x1;
tmp_box[n].x2 = box[n].x2 - bounds.x1;
tmp_box[n].y1 = box[n].y1 - bounds.y1;
tmp_box[n].y2 = box[n].y2 - bounds.y1;
}
if (!glamor_copy_fbo_fbo_draw(src,
&tmp_pixmap->drawable,
NULL,
tmp_box,
nbox,
dx + bounds.x1,
dy + bounds.y1,
FALSE, FALSE,
0, NULL))
goto bail_box;
if (!glamor_copy_fbo_fbo_draw(&tmp_pixmap->drawable,
dst,
gc,
box,
nbox,
-bounds.x1,
-bounds.y1,
FALSE, FALSE,
bitplane, closure))
goto bail_box;
free(tmp_box);
glamor_destroy_pixmap(tmp_pixmap);
return TRUE;
bail_box:
free(tmp_box);
bail_pixmap:
glamor_destroy_pixmap(tmp_pixmap);
bail:
return FALSE;
bail_ctx:
glDisable(GL_COLOR_LOGIC_OP);
return FALSE;
}
/**
* Returns TRUE if the copy has to be implemented with
* glamor_copy_fbo_fbo_temp() instead of glamor_copy_fbo_fbo().
*
* If the src and dst are in the same pixmap, then glamor_copy_fbo_fbo()'s
* sampling would give undefined results (since the same texture would be
* bound as an FBO destination and as a texture source). However, if we
* have GL_NV_texture_barrier, we can take advantage of the exception it
* added:
*
* "- If a texel has been written, then in order to safely read the result
* a texel fetch must be in a subsequent Draw separated by the command
*
* void TextureBarrierNV(void);
*
* TextureBarrierNV() will guarantee that writes have completed and caches
* have been invalidated before subsequent Draws are executed."
*/
static Bool
glamor_copy_needs_temp(DrawablePtr src,
DrawablePtr dst,
BoxPtr box,
int nbox,
int dx,
int dy)
{
PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
ScreenPtr screen = dst->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
int n;
int dst_off_x, dst_off_y;
int src_off_x, src_off_y;
BoxRec bounds;
if (src_pixmap != dst_pixmap)
return FALSE;
if (nbox == 0)
return FALSE;
if (!glamor_priv->has_nv_texture_barrier)
return TRUE;
glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y);
bounds = box[0];
for (n = 1; n < nbox; n++) {
bounds.x1 = min(bounds.x1, box[n].x1);
bounds.y1 = min(bounds.y1, box[n].y1);
bounds.x2 = max(bounds.x2, box[n].x2);
bounds.y2 = max(bounds.y2, box[n].y2);
}
/* Check to see if the pixmap-relative boxes overlap in both X and Y,
* in which case we can't rely on NV_texture_barrier and must
* make a temporary copy
*
* dst.x1 < src.x2 &&
* src.x1 < dst.x2 &&
*
* dst.y1 < src.y2 &&
* src.y1 < dst.y2
*/
if (bounds.x1 + dst_off_x < bounds.x2 + dx + src_off_x &&
bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x &&
bounds.y1 + dst_off_y < bounds.y2 + dy + src_off_y &&
bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) {
return TRUE;
}
glTextureBarrierNV();
return FALSE;
}
static Bool
glamor_copy_gl(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_priv)) {
if (GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv)) {
if (glamor_copy_needs_temp(src, dst, box, nbox, dx, dy))
return glamor_copy_fbo_fbo_temp(src, dst, gc, box, nbox, dx, dy,
reverse, upsidedown, bitplane, closure);
else
return glamor_copy_fbo_fbo_draw(src, dst, gc, box, nbox, dx, dy,
reverse, upsidedown, bitplane, closure);
}
if (bitplane == 0)
return glamor_copy_cpu_fbo(src, dst, gc, box, nbox, dx, dy,
reverse, upsidedown, bitplane, closure);
}
return FALSE;
}
void
glamor_copy(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure))
return;
glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
}
RegionPtr
glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int width, int height, int dstx, int dsty)
{
return miDoCopy(src, dst, gc,
srcx, srcy, width, height,
dstx, dsty, glamor_copy, 0, NULL);
}
RegionPtr
glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int width, int height, int dstx, int dsty,
unsigned long bitplane)
{
if ((bitplane & FbFullMask(src->depth)) == 0)
return miHandleExposures(src, dst, gc,
srcx, srcy, width, height, dstx, dsty,
bitplane);
return miDoCopy(src, dst, gc,
srcx, srcy, width, height,
dstx, dsty, glamor_copy, bitplane, NULL);
}
void
glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_region)
{
PixmapPtr pixmap = glamor_get_drawable_pixmap(&window->drawable);
DrawablePtr drawable = &pixmap->drawable;
RegionRec dst_region;
int dx, dy;
dx = old_origin.x - window->drawable.x;
dy = old_origin.y - window->drawable.y;
RegionTranslate(src_region, -dx, -dy);
RegionNull(&dst_region);
RegionIntersect(&dst_region, &window->borderClip, src_region);
#ifdef COMPOSITE
if (pixmap->screen_x || pixmap->screen_y)
RegionTranslate(&dst_region, -pixmap->screen_x, -pixmap->screen_y);
#endif
miCopyRegion(drawable, drawable,
0, &dst_region, dx, dy, glamor_copy, 0, 0);
RegionUninit(&dst_region);
}
Bool
glamor_copy_n_to_n_nf(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown, Pixel bitplane,
void *closure)
{
if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure))
return TRUE;
if (glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(dst))
return FALSE;
glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
return TRUE;
}
Bool
glamor_copy_plane_nf(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int w, int h, int dstx, int dsty,
unsigned long bitplane, RegionPtr *region)
{
if (glamor_ddx_fallback_check_pixmap(src) &&
glamor_ddx_fallback_check_pixmap(dst) &&
glamor_ddx_fallback_check_gc(gc))
return FALSE;
*region = glamor_copy_plane(src, dst, gc,
srcx, srcy, w, h, dstx, dsty,
bitplane);
return TRUE;
}

View File

@ -1,626 +0,0 @@
/*
* Copyright © 2008 Intel Corporation
* Copyright © 1998 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
* Zhigang Gong <zhigang.gong@linux.intel.com>
*/
#include "glamor_priv.h"
/** @file glamor_copyarea.c
*
* GC CopyArea implementation
*/
static Bool
glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
DrawablePtr dst,
GCPtr gc, BoxPtr box, int nbox, int dx, int dy)
{
ScreenPtr screen = dst->pScreen;
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
int dst_x_off, dst_y_off, src_x_off, src_y_off, i;
int fbo_x_off, fbo_y_off;
int src_fbo_x_off, src_fbo_y_off;
if (!glamor_priv->has_fbo_blit) {
glamor_delayed_fallback(screen, "no EXT_framebuffer_blit\n");
return FALSE;
}
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (gc) {
if (gc->alu != GXcopy) {
glamor_delayed_fallback(screen, "non-copy ALU\n");
return FALSE;
}
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
glamor_delayed_fallback(screen, "no src fbo\n");
return FALSE;
}
if (glamor_set_destination_pixmap(dst_pixmap))
return FALSE;
pixmap_priv_get_fbo_off(dst_pixmap_priv, &fbo_x_off, &fbo_y_off);
pixmap_priv_get_fbo_off(src_pixmap_priv, &src_fbo_x_off, &src_fbo_y_off);
glamor_make_current(glamor_priv);
glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->base.fbo->fb);
glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
dst_x_off += fbo_x_off;
dst_y_off += fbo_y_off;
src_y_off += dy + src_fbo_y_off;
src_x_off += src_fbo_x_off;
for (i = 0; i < nbox; i++) {
if (glamor_priv->yInverted) {
glBlitFramebuffer(box[i].x1 + dx + src_x_off,
box[i].y1 + src_y_off,
box[i].x2 + dx + src_x_off,
box[i].y2 + src_y_off,
box[i].x1 + dst_x_off,
box[i].y1 + dst_y_off,
box[i].x2 + dst_x_off,
box[i].y2 + dst_y_off,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
else {
int flip_dst_y1 =
dst_pixmap->drawable.height - (box[i].y2 + dst_y_off);
int flip_dst_y2 =
dst_pixmap->drawable.height - (box[i].y1 + dst_y_off);
int flip_src_y1 =
src_pixmap->drawable.height - (box[i].y2 + src_y_off);
int flip_src_y2 =
src_pixmap->drawable.height - (box[i].y1 + src_y_off);
glBlitFramebuffer(box[i].x1 + dx + src_x_off,
flip_src_y1,
box[i].x2 + dx + src_x_off,
flip_src_y2,
box[i].x1 + dst_x_off,
flip_dst_y1,
box[i].x2 + dst_x_off,
flip_dst_y2,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
}
glamor_priv->state = BLIT_STATE;
return TRUE;
}
static Bool
glamor_copy_n_to_n_textured(DrawablePtr src,
DrawablePtr dst,
GCPtr gc, BoxPtr box, int nbox, int dx, int dy)
{
glamor_screen_private *glamor_priv =
glamor_get_screen_private(dst->pScreen);
PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
int i;
float vertices[8], texcoords[8];
glamor_pixmap_private *src_pixmap_priv;
glamor_pixmap_private *dst_pixmap_priv;
int src_x_off, src_y_off, dst_x_off, dst_y_off;
enum glamor_pixmap_status src_status = GLAMOR_NONE;
GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale;
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (src_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) {
#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
return FALSE;
#else
src_status = glamor_upload_pixmap_to_texture(src_pixmap);
if (src_status != GLAMOR_UPLOAD_DONE)
return FALSE;
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
#endif
}
pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale);
glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
glamor_make_current(glamor_priv);
glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
GL_FALSE, 2 * sizeof(float), vertices);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
dx += src_x_off;
dy += src_y_off;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
2 * sizeof(float), texcoords);
glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
glUseProgram(glamor_priv->finish_access_prog[0]);
glUniform1i(glamor_priv->finish_access_revert[0], REVERT_NONE);
glUniform1i(glamor_priv->finish_access_swap_rb[0], SWAP_NONE_UPLOADING);
for (i = 0; i < nbox; i++) {
glamor_set_normalize_vcoords(dst_pixmap_priv,
dst_xscale, dst_yscale,
box[i].x1 + dst_x_off,
box[i].y1 + dst_y_off,
box[i].x2 + dst_x_off,
box[i].y2 + dst_y_off,
glamor_priv->yInverted, vertices);
glamor_set_normalize_tcoords(src_pixmap_priv,
src_xscale,
src_yscale,
box[i].x1 + dx,
box[i].y1 + dy,
box[i].x2 + dx,
box[i].y2 + dy,
glamor_priv->yInverted, texcoords);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
/* The source texture is bound to a fbo, we have to flush it here. */
glamor_priv->state = RENDER_STATE;
glamor_priv->render_idle_cnt = 0;
return TRUE;
}
static Bool
__glamor_copy_n_to_n(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown, Pixel bitplane, void *closure)
{
PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL;
DrawablePtr temp_src = src;
glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
glamor_screen_private *glamor_priv;
BoxRec bound;
ScreenPtr screen;
int temp_dx = dx;
int temp_dy = dy;
int src_x_off, src_y_off, dst_x_off, dst_y_off;
int i;
int overlaped = 0;
Bool ret = FALSE;
dst_pixmap = glamor_get_drawable_pixmap(dst);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
src_pixmap = glamor_get_drawable_pixmap(src);
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
screen = dst_pixmap->drawable.pScreen;
glamor_priv = glamor_get_screen_private(dst->pScreen);
glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
if (src_pixmap_priv->base.fbo
&& src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) {
int x_shift = abs(src_x_off - dx - dst_x_off);
int y_shift = abs(src_y_off - dy - dst_y_off);
for (i = 0; i < nbox; i++) {
if (x_shift < abs(box[i].x2 - box[i].x1)
&& y_shift < abs(box[i].y2 - box[i].y1)) {
overlaped = 1;
break;
}
}
}
DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n",
box[0].x1, box[0].y1,
box[0].x2 - box[0].x1, box[0].y2 - box[0].y1,
dx, dy, src_pixmap, dst_pixmap);
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
!overlaped &&
(glamor_priv->state != RENDER_STATE
|| !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex)
&& glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) {
ret = TRUE;
goto done;
}
glamor_calculate_boxes_bound(&bound, box, nbox);
/* Overlaped indicate the src and dst are the same pixmap. */
if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)
&& (((bound.x2 - bound.x1) * (bound.y2 - bound.y1)
* 4 >
src_pixmap->drawable.width *
src_pixmap->drawable.height)
|| !(glamor_check_fbo_size(glamor_priv,
src_pixmap->drawable.width,
src_pixmap->drawable.
height))))) {
temp_pixmap = glamor_create_pixmap(screen,
bound.x2 - bound.x1,
bound.y2 - bound.y1,
src_pixmap->drawable.depth,
overlaped ? 0 :
GLAMOR_CREATE_PIXMAP_CPU);
assert(bound.x2 - bound.x1 <= glamor_priv->max_fbo_size);
assert(bound.y2 - bound.y1 <= glamor_priv->max_fbo_size);
if (!temp_pixmap)
goto done;
glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1);
temp_src = &temp_pixmap->drawable;
if (overlaped)
glamor_copy_n_to_n_textured(src, temp_src, gc, box,
nbox,
temp_dx + bound.x1, temp_dy + bound.y1);
else
fbCopyNtoN(src, temp_src, gc, box, nbox,
temp_dx + bound.x1, temp_dy + bound.y1,
reverse, upsidedown, bitplane, closure);
glamor_translate_boxes(box, nbox, bound.x1, bound.y1);
temp_dx = -bound.x1;
temp_dy = -bound.y1;
}
else {
temp_dx = dx;
temp_dy = dy;
temp_src = src;
}
if (glamor_copy_n_to_n_textured
(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) {
ret = TRUE;
}
done:
if (temp_src != src)
glamor_destroy_pixmap(temp_pixmap);
return ret;
}
static Bool
_glamor_copy_n_to_n(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown, Pixel bitplane,
void *closure, Bool fallback)
{
ScreenPtr screen = dst->pScreen;
PixmapPtr dst_pixmap, src_pixmap;
glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
glamor_screen_private *glamor_priv;
BoxPtr extent;
RegionRec region;
int src_x_off, src_y_off, dst_x_off, dst_y_off;
Bool ok = FALSE;
int force_clip = 0;
if (nbox == 0)
return TRUE;
dst_pixmap = glamor_get_drawable_pixmap(dst);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
src_pixmap = glamor_get_drawable_pixmap(src);
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
glamor_priv = glamor_get_screen_private(screen);
DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n",
box[0].x1, box[0].y1,
box[0].x2 - box[0].x1, box[0].y2 - box[0].y1,
dx, dy, src_pixmap, dst_pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv))
goto fall_back;
if (gc) {
if (!glamor_set_planemask(dst_pixmap, gc->planemask))
goto fall_back;
glamor_make_current(glamor_priv);
if (!glamor_set_alu(screen, gc->alu)) {
goto fail_noregion;
}
}
if (!src_pixmap_priv) {
glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY);
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
}
glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
RegionInitBoxes(&region, box, nbox);
extent = RegionExtents(&region);
if (!glamor_check_fbo_size(glamor_priv,
extent->x2 - extent->x1, extent->y2 - extent->y1)
&& (src_pixmap_priv->type == GLAMOR_MEMORY
|| (src_pixmap_priv == dst_pixmap_priv))) {
force_clip = 1;
}
if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
|| src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
glamor_pixmap_clipped_regions *clipped_dst_regions;
int n_dst_region, i, j;
PixmapPtr temp_source_pixmap;
glamor_pixmap_private *temp_source_priv = NULL;
RegionTranslate(&region, dst_x_off, dst_y_off);
if (!force_clip)
clipped_dst_regions =
glamor_compute_clipped_regions(dst_pixmap_priv, &region,
&n_dst_region, 0, reverse,
upsidedown);
else
clipped_dst_regions =
glamor_compute_clipped_regions_ext(dst_pixmap_priv, &region,
&n_dst_region,
glamor_priv->max_fbo_size,
glamor_priv->max_fbo_size,
reverse, upsidedown);
for (i = 0; i < n_dst_region; i++) {
int n_src_region;
glamor_pixmap_clipped_regions *clipped_src_regions;
BoxPtr current_boxes;
int n_current_boxes;
SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv,
clipped_dst_regions[i].block_idx);
temp_source_pixmap = NULL;
if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
RegionTranslate(clipped_dst_regions[i].region,
-dst_x_off + src_x_off + dx,
-dst_y_off + src_y_off + dy);
clipped_src_regions =
glamor_compute_clipped_regions(src_pixmap_priv,
clipped_dst_regions[i].
region, &n_src_region, 0,
reverse, upsidedown);
DEBUGF("Source is large pixmap.\n");
for (j = 0; j < n_src_region; j++) {
if (src_pixmap_priv != dst_pixmap_priv)
SET_PIXMAP_FBO_CURRENT(src_pixmap_priv,
clipped_src_regions[j].
block_idx);
else if (src_pixmap_priv == dst_pixmap_priv &&
clipped_src_regions[j].block_idx !=
clipped_dst_regions[i].block_idx) {
/* source and the dest are the same, but need different block_idx.
* we create a empty pixmap and fill the required source fbo and box to
* it. It's a little hacky, but avoid extra copy. */
temp_source_pixmap =
glamor_create_pixmap(src->pScreen, 0, 0, src->depth,
0);
if (!temp_source_pixmap) {
ok = FALSE;
goto fail;
}
src->pScreen->ModifyPixmapHeader(temp_source_pixmap,
src_pixmap->drawable.
width,
src_pixmap->drawable.
height, 0, 0,
src_pixmap->devKind,
NULL);
temp_source_priv =
glamor_get_pixmap_private(temp_source_pixmap);
*temp_source_priv = *src_pixmap_priv;
temp_source_priv->large.box =
src_pixmap_priv->large.
box_array[clipped_src_regions[j].block_idx];
temp_source_priv->base.fbo =
src_pixmap_priv->large.
fbo_array[clipped_src_regions[j].block_idx];
temp_source_priv->base.pixmap = temp_source_pixmap;
}
assert(temp_source_pixmap ||
!(src_pixmap_priv == dst_pixmap_priv &&
(clipped_src_regions[j].block_idx !=
clipped_dst_regions[i].block_idx)));
RegionTranslate(clipped_src_regions[j].region,
-src_x_off - dx, -src_y_off - dy);
current_boxes = RegionRects(clipped_src_regions[j].region);
n_current_boxes =
RegionNumRects(clipped_src_regions[j].region);
DEBUGF("dst pixmap fbo idx %d src pixmap fbo idx %d \n",
clipped_dst_regions[i].block_idx,
clipped_src_regions[j].block_idx);
DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n",
current_boxes[0].x1, current_boxes[0].y1,
current_boxes[0].x2, current_boxes[0].y2, dx, dy,
src_pixmap, dst_pixmap);
if (!temp_source_pixmap)
ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes,
n_current_boxes, dx, dy,
reverse, upsidedown, bitplane,
closure);
else {
ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable,
dst, gc, current_boxes,
n_current_boxes, dx, dy,
reverse, upsidedown, bitplane,
closure);
temp_source_priv->type = GLAMOR_MEMORY;
temp_source_priv->base.fbo = NULL;
glamor_destroy_pixmap(temp_source_pixmap);
temp_source_pixmap = NULL;
}
RegionDestroy(clipped_src_regions[j].region);
if (!ok) {
assert(0);
goto fail;
}
}
if (n_src_region == 0)
ok = TRUE;
free(clipped_src_regions);
}
else {
RegionTranslate(clipped_dst_regions[i].region,
-dst_x_off, -dst_y_off);
current_boxes = RegionRects(clipped_dst_regions[i].region);
n_current_boxes = RegionNumRects(clipped_dst_regions[i].region);
DEBUGF("dest pixmap fbo idx %d \n",
clipped_dst_regions[i].block_idx);
DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n",
current_boxes[0].x1, current_boxes[0].y1,
current_boxes[0].x2, current_boxes[0].y2,
dx, dy, src_pixmap, dst_pixmap);
ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes,
n_current_boxes, dx, dy, reverse,
upsidedown, bitplane, closure);
}
RegionDestroy(clipped_dst_regions[i].region);
}
if (n_dst_region == 0)
ok = TRUE;
free(clipped_dst_regions);
}
else {
ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy,
reverse, upsidedown, bitplane, closure);
}
fail:
RegionUninit(&region);
fail_noregion:
glamor_make_current(glamor_priv);
glamor_set_alu(screen, GXcopy);
if (ok)
return TRUE;
fall_back:
if (!fallback && glamor_ddx_fallback_check_pixmap(src)
&& glamor_ddx_fallback_check_pixmap(dst))
goto done;
if (src_pixmap_priv->type == GLAMOR_DRM_ONLY
|| dst_pixmap_priv->type == GLAMOR_DRM_ONLY) {
LogMessage(X_WARNING,
"Access a DRM only pixmap is not allowed within glamor.\n");
return TRUE;
}
glamor_report_delayed_fallbacks(src->pScreen);
glamor_report_delayed_fallbacks(dst->pScreen);
glamor_fallback("from %p to %p (%c,%c)\n", src, dst,
glamor_get_drawable_location(src),
glamor_get_drawable_location(dst));
if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) &&
glamor_prepare_access(src, GLAMOR_ACCESS_RO) &&
glamor_prepare_access_gc(gc)) {
fbCopyNtoN(src, dst, gc, box, nbox,
dx, dy, reverse, upsidedown, bitplane, closure);
}
glamor_finish_access_gc(gc);
glamor_finish_access(src);
glamor_finish_access(dst);
ok = TRUE;
done:
glamor_clear_delayed_fallbacks(src->pScreen);
glamor_clear_delayed_fallbacks(dst->pScreen);
return ok;
}
RegionPtr
glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int width, int height, int dstx, int dsty)
{
RegionPtr region;
region = miDoCopy(src, dst, gc,
srcx, srcy, width, height,
dstx, dsty, glamor_copy_n_to_n, 0, NULL);
return region;
}
void
glamor_copy_n_to_n(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse, Bool upsidedown, Pixel bitplane, void *closure)
{
_glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
dy, reverse, upsidedown, bitplane, closure, TRUE);
}
Bool
glamor_copy_n_to_n_nf(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown, Pixel bitplane, void *closure)
{
return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
dy, reverse, upsidedown, bitplane, closure,
FALSE);
}

View File

@ -1,75 +0,0 @@
/*
* Copyright © 2009 Intel Corporation
* Copyright © 1998 Keith Packard
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Zhigang Gong <zhigang.gong@gmail.com>
*
*/
#include "glamor_priv.h"
static Bool
_glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty,
unsigned long bitPlane, RegionPtr *pRegion, Bool fallback)
{
if (!fallback && glamor_ddx_fallback_check_gc(pGC)
&& glamor_ddx_fallback_check_pixmap(pSrc)
&& glamor_ddx_fallback_check_pixmap(pDst))
goto fail;
if (glamor_prepare_access(pDst, GLAMOR_ACCESS_RW) &&
glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO) &&
glamor_prepare_access_gc(pGC)) {
*pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
dstx, dsty, bitPlane);
}
glamor_finish_access_gc(pGC);
glamor_finish_access(pSrc);
glamor_finish_access(pDst);
return TRUE;
fail:
return FALSE;
}
RegionPtr
glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty,
unsigned long bitPlane)
{
RegionPtr ret;
_glamor_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h,
dstx, dsty, bitPlane, &ret, TRUE);
return ret;
}
Bool
glamor_copy_plane_nf(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty,
unsigned long bitPlane, RegionPtr *pRegion)
{
return _glamor_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h,
dstx, dsty, bitPlane, pRegion, FALSE);
}

View File

@ -1,56 +0,0 @@
/*
* Copyright © 2008 Intel Corporation
* Copyright © 1998 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
/** @file glamor_copywindow.c
*
* Screen CopyWindow implementation.
*/
void
glamor_copy_window(WindowPtr win, DDXPointRec old_origin, RegionPtr src_region)
{
RegionRec dst_region;
int dx, dy;
PixmapPtr pixmap = win->drawable.pScreen->GetWindowPixmap(win);
dx = old_origin.x - win->drawable.x;
dy = old_origin.y - win->drawable.y;
REGION_TRANSLATE(win->drawable.pScreen, src_region, -dx, -dy);
REGION_INIT(win->drawable.pScreen, &dst_region, NullBox, 0);
REGION_INTERSECT(win->drawable.pScreen, &dst_region,
&win->borderClip, src_region);
#ifdef COMPOSITE
if (pixmap->screen_x || pixmap->screen_y)
REGION_TRANSLATE(win->drawable.pScreen, &dst_region,
-pixmap->screen_x, -pixmap->screen_y);
#endif
miCopyRegion(&pixmap->drawable, &pixmap->drawable,
NULL, &dst_region, dx, dy, glamor_copy_n_to_n, 0, NULL);
REGION_UNINIT(win->drawable.pScreen, &dst_region);
}

View File

@ -114,27 +114,6 @@ glamor_link_glsl_prog(ScreenPtr screen, GLint prog, const char *format, ...)
}
}
Bool
glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
{
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap->devPrivate.ptr) {
/* Already mapped, nothing needs to be done. Note that we
* aren't allowing promotion from RO to RW, because it would
* require re-mapping the PBO.
*/
assert(!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) ||
access == GLAMOR_ACCESS_RO ||
pixmap_priv->base.map_access == GLAMOR_ACCESS_RW);
return TRUE;
}
pixmap_priv->base.map_access = access;
return glamor_download_pixmap_to_cpu(pixmap, access);
}
/*
* When downloading a unsupported color format to CPU memory,
we need to shuffle the color elements and then use a supported
@ -313,102 +292,6 @@ glamor_fini_finish_access_shaders(ScreenPtr screen)
glDeleteProgram(glamor_priv->finish_access_prog[1]);
}
void
glamor_finish_access(DrawablePtr drawable)
{
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_screen_private *glamor_priv =
glamor_get_screen_private(drawable->pScreen);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv))
return;
/* If we are doing a series of unmaps from a nested map, we're
* done. None of the callers do any rendering to maps after
* starting an unmap sequence, so we don't need to delay until the
* last nested unmap.
*/
if (!pixmap->devPrivate.ptr)
return;
if (pixmap_priv->base.map_access == GLAMOR_ACCESS_RW) {
glamor_restore_pixmap_to_texture(pixmap);
}
if (pixmap_priv->base.fbo->pbo != 0 && pixmap_priv->base.fbo->pbo_valid) {
assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
glamor_make_current(glamor_priv);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo);
pixmap_priv->base.fbo->pbo_valid = FALSE;
pixmap_priv->base.fbo->pbo = 0;
}
else {
free(pixmap->devPrivate.ptr);
}
if (pixmap_priv->type == GLAMOR_TEXTURE_DRM)
pixmap->devKind = pixmap_priv->base.drm_stride;
if (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED)
pixmap_priv->base.gl_fbo = GLAMOR_FBO_NORMAL;
pixmap->devPrivate.ptr = NULL;
}
/**
* Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the
* current fill style.
*
* Solid doesn't use an extra pixmap source, so we don't worry about them.
* Stippled/OpaqueStippled are 1bpp and can be in fb, so we should worry
* about them.
*/
Bool
glamor_prepare_access_gc(GCPtr gc)
{
if (gc->stipple) {
if (!glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO))
return FALSE;
}
if (gc->fillStyle == FillTiled) {
if (!glamor_prepare_access(&gc->tile.pixmap->drawable,
GLAMOR_ACCESS_RO)) {
if (gc->stipple)
glamor_finish_access(&gc->stipple->drawable);
return FALSE;
}
}
return TRUE;
}
/**
* Finishes access to the tile in the GC, if used.
*/
void
glamor_finish_access_gc(GCPtr gc)
{
if (gc->fillStyle == FillTiled)
glamor_finish_access(&gc->tile.pixmap->drawable);
if (gc->stipple)
glamor_finish_access(&gc->stipple->drawable);
}
Bool
glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple,
int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
unsigned long fg_pixel, unsigned long bg_pixel,
int stipple_x, int stipple_y)
{
glamor_fallback("stubbed out stipple depth %d\n", pixmap->drawable.depth);
return FALSE;
}
GCOps glamor_gc_ops = {
.FillSpans = glamor_fill_spans,
.SetSpans = glamor_set_spans,
@ -432,6 +315,58 @@ GCOps glamor_gc_ops = {
.PushPixels = glamor_push_pixels,
};
/*
* When the stipple is changed or drawn to, invalidate any
* cached copy
*/
static void
glamor_invalidate_stipple(GCPtr gc)
{
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
if (gc_priv->stipple) {
if (gc_priv->stipple_damage)
DamageUnregister(gc_priv->stipple_damage);
glamor_destroy_pixmap(gc_priv->stipple);
gc_priv->stipple = NULL;
}
}
static void
glamor_stipple_damage_report(DamagePtr damage, RegionPtr region,
void *closure)
{
GCPtr gc = closure;
glamor_invalidate_stipple(gc);
}
static void
glamor_stipple_damage_destroy(DamagePtr damage, void *closure)
{
GCPtr gc = closure;
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
gc_priv->stipple_damage = NULL;
glamor_invalidate_stipple(gc);
}
void
glamor_track_stipple(GCPtr gc)
{
if (gc->stipple) {
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
if (!gc_priv->stipple_damage)
gc_priv->stipple_damage = DamageCreate(glamor_stipple_damage_report,
glamor_stipple_damage_destroy,
DamageReportNonEmpty,
TRUE, gc->pScreen, gc);
if (gc_priv->stipple_damage)
DamageRegister(&gc->stipple->drawable, gc_priv->stipple_damage);
}
}
/**
* uxa_validate_gc() sets the ops to glamor's implementations, which may be
* accelerated or may sync the card and fall back to fb.
@ -502,6 +437,9 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
changes &= ~GCTile;
}
if (changes & GCStipple)
glamor_invalidate_stipple(gc);
if (changes & GCStipple && gc->stipple) {
/* We can't inline stipple handling like we do for GCTile because
* it sets fbgc privates.
@ -515,14 +453,38 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
fbValidateGC(gc, changes, drawable);
}
if (changes & GCDashList) {
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
if (gc_priv->dash) {
glamor_destroy_pixmap(gc_priv->dash);
gc_priv->dash = NULL;
}
}
gc->ops = &glamor_gc_ops;
}
void
glamor_destroy_gc(GCPtr gc)
{
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
if (gc_priv->dash) {
glamor_destroy_pixmap(gc_priv->dash);
gc_priv->dash = NULL;
}
glamor_invalidate_stipple(gc);
if (gc_priv->stipple_damage)
DamageDestroy(gc_priv->stipple_damage);
miDestroyGC(gc);
}
static GCFuncs glamor_gc_funcs = {
glamor_validate_gc,
miChangeGC,
miCopyGC,
miDestroyGC,
glamor_destroy_gc,
miChangeClip,
miDestroyClip,
miCopyClip
@ -535,6 +497,10 @@ static GCFuncs glamor_gc_funcs = {
int
glamor_create_gc(GCPtr gc)
{
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
gc_priv->dash = NULL;
gc_priv->stipple = NULL;
if (!fbCreateGC(gc))
return FALSE;

370
glamor/glamor_dash.c Normal file
View File

@ -0,0 +1,370 @@
/*
* Copyright © 2014 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
#include "glamor_program.h"
#include "glamor_transform.h"
#include "glamor_transfer.h"
#include "glamor_prepare.h"
static const char dash_vs_vars[] =
"attribute vec3 primitive;\n"
"varying float dash_offset;\n";
static const char dash_vs_exec[] =
" dash_offset = primitive.z / dash_length;\n"
GLAMOR_POS(gl_Position, primitive.xy);
static const char dash_fs_vars[] =
"varying float dash_offset;\n";
static const char on_off_fs_exec[] =
" float pattern = texture2D(dash, vec2(dash_offset, 0.5)).w;\n"
" if (pattern == 0.0)\n"
" discard;\n";
/* XXX deal with stippled double dashed lines once we have stippling support */
static const char double_fs_exec[] =
" float pattern = texture2D(dash, vec2(dash_offset, 0.5)).w;\n"
" if (pattern == 0.0)\n"
" gl_FragColor = bg;\n"
" else\n"
" gl_FragColor = fg;\n";
static const glamor_facet glamor_facet_on_off_dash_lines = {
.version = 130,
.name = "poly_lines_on_off_dash",
.vs_vars = dash_vs_vars,
.vs_exec = dash_vs_exec,
.fs_vars = dash_fs_vars,
.fs_exec = on_off_fs_exec,
.locations = glamor_program_location_dash,
};
static const glamor_facet glamor_facet_double_dash_lines = {
.version = 130,
.name = "poly_lines_double_dash",
.vs_vars = dash_vs_vars,
.vs_exec = dash_vs_exec,
.fs_vars = dash_fs_vars,
.fs_exec = double_fs_exec,
.locations = (glamor_program_location_dash|
glamor_program_location_fg|
glamor_program_location_bg),
};
static PixmapPtr
glamor_get_dash_pixmap(GCPtr gc)
{
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
ScreenPtr screen = gc->pScreen;
PixmapPtr pixmap;
int offset;
int d;
uint32_t pixel;
GCPtr scratch_gc;
if (gc_priv->dash)
return gc_priv->dash;
offset = 0;
for (d = 0; d < gc->numInDashList; d++)
offset += gc->dash[d];
pixmap = glamor_create_pixmap(screen, offset, 1, 8, 0);
if (!pixmap)
goto bail;
scratch_gc = GetScratchGC(8, screen);
if (!scratch_gc)
goto bail_pixmap;
pixel = 0xffffffff;
offset = 0;
for (d = 0; d < gc->numInDashList; d++) {
xRectangle rect;
ChangeGCVal changes;
changes.val = pixel;
(void) ChangeGC(NullClient, scratch_gc,
GCForeground, &changes);
ValidateGC(&pixmap->drawable, scratch_gc);
rect.x = offset;
rect.y = 0;
rect.width = gc->dash[d];
rect.height = 1;
scratch_gc->ops->PolyFillRect (&pixmap->drawable, scratch_gc, 1, &rect);
offset += gc->dash[d];
pixel = ~pixel;
}
FreeScratchGC(scratch_gc);
gc_priv->dash = pixmap;
return pixmap;
bail_pixmap:
glamor_destroy_pixmap(pixmap);
bail:
return NULL;
}
static glamor_program *
glamor_dash_setup(DrawablePtr drawable, GCPtr gc)
{
ScreenPtr screen = drawable->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
PixmapPtr dash_pixmap;
glamor_pixmap_private *dash_priv;
glamor_program *prog;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
goto bail;
if (gc->lineWidth != 0)
goto bail;
dash_pixmap = glamor_get_dash_pixmap(gc);
dash_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dash_priv))
goto bail;
glamor_make_current(glamor_priv);
switch (gc->lineStyle) {
case LineOnOffDash:
prog = glamor_use_program_fill(pixmap, gc,
&glamor_priv->on_off_dash_line_progs,
&glamor_facet_on_off_dash_lines);
if (!prog)
goto bail_ctx;
break;
case LineDoubleDash:
if (gc->fillStyle != FillSolid)
goto bail_ctx;
prog = &glamor_priv->double_dash_line_prog;
if (!prog->prog) {
if (!glamor_build_program(screen, prog,
&glamor_facet_double_dash_lines,
NULL))
goto bail_ctx;
}
if (!glamor_use_program(pixmap, gc, prog, NULL))
goto bail_ctx;
glamor_set_color(pixmap, gc->fgPixel, prog->fg_uniform);
glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
break;
default:
goto bail_ctx;
}
/* Set the dash pattern as texture 1 */
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, dash_priv->base.fbo->tex);
glUniform1i(prog->dash_uniform, 1);
glUniform1f(prog->dash_length_uniform, dash_pixmap->drawable.width);
return prog;
bail_ctx:
glDisable(GL_COLOR_LOGIC_OP);
bail:
return NULL;
}
static void
glamor_dash_loop(DrawablePtr drawable, GCPtr gc, glamor_program *prog,
int n, GLenum mode)
{
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
int box_x, box_y;
int off_x, off_y;
glEnable(GL_SCISSOR_TEST);
glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
int nbox = RegionNumRects(gc->pCompositeClip);
BoxPtr box = RegionRects(gc->pCompositeClip);
glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE,
prog->matrix_uniform, &off_x, &off_y);
while (nbox--) {
glScissor(box->x1 + off_x,
box->y1 + off_y,
box->x2 - box->x1,
box->y2 - box->y1);
box++;
glDrawArrays(mode, 0, n);
}
}
glDisable(GL_SCISSOR_TEST);
glDisable(GL_COLOR_LOGIC_OP);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
}
static int
glamor_line_length(short x1, short y1, short x2, short y2)
{
return max(abs(x2 - x1), abs(y2 - y1));
}
Bool
glamor_poly_lines_dash_gl(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points)
{
ScreenPtr screen = drawable->pScreen;
glamor_program *prog;
short *v;
char *vbo_offset;
int add_last;
int dash_pos;
int prev_x, prev_y;
int i;
if (n < 2)
return TRUE;
if (!(prog = glamor_dash_setup(drawable, gc)))
return FALSE;
add_last = 0;
if (gc->capStyle != CapNotLast)
add_last = 1;
/* Set up the vertex buffers for the points */
v = glamor_get_vbo_space(drawable->pScreen,
(n + add_last) * 3 * sizeof (short),
&vbo_offset);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
3 * sizeof (short), vbo_offset);
dash_pos = gc->dashOffset;
prev_x = prev_y = 0;
for (i = 0; i < n; i++) {
int this_x = points[i].x;
int this_y = points[i].y;
if (i) {
if (mode == CoordModePrevious) {
this_x += prev_x;
this_y += prev_y;
}
dash_pos += glamor_line_length(prev_x, prev_y,
this_x, this_y);
}
v[0] = prev_x = this_x;
v[1] = prev_y = this_y;
v[2] = dash_pos;
v += 3;
}
if (add_last) {
v[0] = prev_x + 1;
v[1] = prev_y;
v[2] = dash_pos + 1;
}
glamor_put_vbo_space(screen);
glamor_dash_loop(drawable, gc, prog, n + add_last, GL_LINE_STRIP);
return TRUE;
}
static short *
glamor_add_segment(short *v, short x1, short y1, short x2, short y2,
int dash_start, int dash_end)
{
v[0] = x1;
v[1] = y1;
v[2] = dash_start;
v[3] = x2;
v[4] = y2;
v[5] = dash_end;
return v + 6;
}
Bool
glamor_poly_segment_dash_gl(DrawablePtr drawable, GCPtr gc,
int nseg, xSegment *segs)
{
ScreenPtr screen = drawable->pScreen;
glamor_program *prog;
short *v;
char *vbo_offset;
int dash_start = gc->dashOffset;
int add_last;
int i;
if (!(prog = glamor_dash_setup(drawable, gc)))
return FALSE;
add_last = 0;
if (gc->capStyle != CapNotLast)
add_last = 1;
/* Set up the vertex buffers for the points */
v = glamor_get_vbo_space(drawable->pScreen,
(nseg<<add_last) * 6 * sizeof (short),
&vbo_offset);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
3 * sizeof (short), vbo_offset);
for (i = 0; i < nseg; i++) {
int dash_end = dash_start + glamor_line_length(segs[i].x1, segs[i].y1,
segs[i].x2, segs[i].y2);
v = glamor_add_segment(v,
segs[i].x1, segs[i].y1,
segs[i].x2, segs[i].y2,
dash_start, dash_end);
if (add_last)
v = glamor_add_segment(v,
segs[i].x2, segs[i].y2,
segs[i].x2 + 1, segs[i].y2,
dash_end, dash_end + 1);
}
glamor_put_vbo_space(screen);
glamor_dash_loop(drawable, gc, prog, nseg << (1 + add_last), GL_LINES);
return TRUE;
}

View File

@ -1,356 +0,0 @@
/*
* Copyright © 2008 Intel Corporation
* Copyright © 1998 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
* Zhigang Gong <zhigang.gong@linux.intel.com>
*/
#include "glamor_priv.h"
/** @file glamor_fill.c
*
* GC fill implementation, based loosely on fb_fill.c
*/
/**
* Fills the given rectangle of a drawable with the GC's fill style.
*/
Bool
glamor_fill(DrawablePtr drawable,
GCPtr gc, int x, int y, int width, int height, Bool fallback)
{
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable);
int off_x, off_y;
PixmapPtr sub_pixmap = NULL;
glamor_access_t sub_pixmap_access;
DrawablePtr saved_drawable = NULL;
int saved_x = x, saved_y = y;
glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y);
switch (gc->fillStyle) {
case FillSolid:
if (!glamor_solid(dst_pixmap,
x + off_x,
y + off_y,
width, height, gc->alu, gc->planemask, gc->fgPixel))
goto fail;
break;
case FillStippled:
case FillOpaqueStippled:
if (!glamor_stipple(dst_pixmap,
gc->stipple,
x + off_x,
y + off_y,
width,
height,
gc->alu,
gc->planemask,
gc->fgPixel,
gc->bgPixel, gc->patOrg.x, gc->patOrg.y))
goto fail;
break;
case FillTiled:
if (!glamor_tile(dst_pixmap,
gc->tile.pixmap,
x + off_x,
y + off_y,
width,
height,
gc->alu,
gc->planemask,
x - drawable->x - gc->patOrg.x,
y - drawable->y - gc->patOrg.y))
goto fail;
break;
}
return TRUE;
fail:
if (!fallback) {
if (glamor_ddx_fallback_check_pixmap(&dst_pixmap->drawable)
&& glamor_ddx_fallback_check_gc(gc))
return FALSE;
}
/* Is it possible to set the access as WO? */
sub_pixmap_access = GLAMOR_ACCESS_RW;
sub_pixmap = glamor_get_sub_pixmap(dst_pixmap, x + off_x,
y + off_y, width, height,
sub_pixmap_access);
if (sub_pixmap != NULL) {
if (gc->fillStyle != FillSolid) {
gc->patOrg.x += (drawable->x - x);
gc->patOrg.y += (drawable->y - y);
}
saved_drawable = drawable;
drawable = &sub_pixmap->drawable;
saved_x = x;
saved_y = y;
x = 0;
y = 0;
}
if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
glamor_prepare_access_gc(gc)) {
fbFill(drawable, gc, x, y, width, height);
}
glamor_finish_access_gc(gc);
glamor_finish_access(drawable);
if (sub_pixmap != NULL) {
if (gc->fillStyle != FillSolid) {
gc->patOrg.x -= (saved_drawable->x - saved_x);
gc->patOrg.y -= (saved_drawable->y - saved_y);
}
x = saved_x;
y = saved_y;
glamor_put_sub_pixmap(sub_pixmap, dst_pixmap,
x + off_x, y + off_y,
width, height, sub_pixmap_access);
}
return TRUE;
}
void
glamor_init_solid_shader(ScreenPtr screen)
{
glamor_screen_private *glamor_priv;
const char *solid_vs =
"attribute vec4 v_position;"
"void main()\n"
"{\n"
" gl_Position = v_position;\n"
"}\n";
const char *solid_fs =
GLAMOR_DEFAULT_PRECISION
"uniform vec4 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = color;\n"
"}\n";
GLint fs_prog, vs_prog;
glamor_priv = glamor_get_screen_private(screen);
glamor_make_current(glamor_priv);
glamor_priv->solid_prog = glCreateProgram();
vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs);
fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs);
glAttachShader(glamor_priv->solid_prog, vs_prog);
glAttachShader(glamor_priv->solid_prog, fs_prog);
glBindAttribLocation(glamor_priv->solid_prog,
GLAMOR_VERTEX_POS, "v_position");
glamor_link_glsl_prog(screen, glamor_priv->solid_prog, "solid");
glamor_priv->solid_color_uniform_location =
glGetUniformLocation(glamor_priv->solid_prog, "color");
}
void
glamor_fini_solid_shader(ScreenPtr screen)
{
glamor_screen_private *glamor_priv;
glamor_priv = glamor_get_screen_private(screen);
glamor_make_current(glamor_priv);
glDeleteProgram(glamor_priv->solid_prog);
}
static void
_glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
GLfloat xscale, yscale;
float stack_vertices[32];
float *vertices = stack_vertices;
int valid_nbox = ARRAY_SIZE(stack_vertices) / (4 * 2);
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
glamor_make_current(glamor_priv);
glUseProgram(glamor_priv->solid_prog);
glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
if (nbox > valid_nbox) {
int allocated_nbox;
float *new_vertices;
if (nbox > GLAMOR_COMPOSITE_VBO_VERT_CNT / 6)
allocated_nbox = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6;
else
allocated_nbox = nbox;
new_vertices = malloc(allocated_nbox * 4 * 2 * sizeof(float));
if (new_vertices) {
vertices = new_vertices;
valid_nbox = allocated_nbox;
}
}
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
GL_FALSE, 2 * sizeof(float), vertices);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
while (nbox) {
int box_cnt, i;
float *next_box;
next_box = vertices;
box_cnt = nbox > valid_nbox ? valid_nbox : nbox;
for (i = 0; i < box_cnt; i++) {
glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale,
box[i].x1, box[i].y1,
box[i].x2, box[i].y2,
glamor_priv->yInverted,
next_box);
next_box += 4 * 2;
}
if (box_cnt == 1)
glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4);
else {
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
glDrawRangeElements(GL_TRIANGLES, 0, box_cnt * 4, box_cnt * 6,
GL_UNSIGNED_SHORT, NULL);
} else {
glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT,
NULL);
}
}
nbox -= box_cnt;
box += box_cnt;
}
if (vertices != stack_vertices)
free(vertices);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
glamor_priv->state = RENDER_STATE;
glamor_priv->render_idle_cnt = 0;
}
/**
* Fills the given rectangles of pixmap with an X pixel value.
*
* This is a helper used by other code after clipping and translation
* of coordinates to a glamor backing pixmap.
*/
Bool
glamor_solid_boxes(PixmapPtr pixmap,
BoxPtr box, int nbox, unsigned long fg_pixel)
{
glamor_pixmap_private *pixmap_priv;
GLfloat color[4];
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return FALSE;
glamor_get_rgba_from_pixel(fg_pixel,
&color[0],
&color[1],
&color[2], &color[3], format_for_pixmap(pixmap));
if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
RegionRec region;
int n_region;
glamor_pixmap_clipped_regions *clipped_regions;
int i;
RegionInitBoxes(&region, box, nbox);
clipped_regions =
glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0,
0, 0);
for (i = 0; i < n_region; i++) {
BoxPtr inner_box;
int inner_nbox;
SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
inner_box = RegionRects(clipped_regions[i].region);
inner_nbox = RegionNumRects(clipped_regions[i].region);
_glamor_solid_boxes(pixmap, inner_box, inner_nbox, color);
RegionDestroy(clipped_regions[i].region);
}
free(clipped_regions);
RegionUninit(&region);
}
else
_glamor_solid_boxes(pixmap, box, nbox, color);
return TRUE;
}
/**
* Fills a rectangle of a pixmap with an X pixel value.
*
* This is a helper used by other glamor code mostly for clearing of
* buffers to 0.
*/
Bool
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask, unsigned long fg_pixel)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
glamor_pixmap_private *pixmap_priv;
BoxRec box;
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return FALSE;
if (!glamor_set_planemask(pixmap, planemask)) {
glamor_fallback("Failedto set planemask in glamor_solid.\n");
return FALSE;
}
glamor_make_current(glamor_priv);
if (!glamor_set_alu(screen, alu)) {
if (alu == GXclear)
fg_pixel = 0;
else {
glamor_fallback("unsupported alu %x\n", alu);
return FALSE;
}
}
box.x1 = x;
box.y1 = y;
box.x2 = x + width;
box.y2 = y + height;
glamor_solid_boxes(pixmap, &box, 1, fg_pixel);
glamor_set_alu(screen, GXcopy);
return TRUE;
}

View File

@ -56,7 +56,8 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
glamor_make_current(glamor_priv);
prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_glyph_blt_progs,
prog = glamor_use_program_fill(pixmap, gc,
&glamor_priv->poly_glyph_blt_progs,
&glamor_facet_poly_glyph_blt);
if (!prog)
goto bail_ctx;
@ -74,7 +75,8 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
int off_x, off_y;
char *vbo_offset;
glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE, prog->matrix_uniform, &off_x, &off_y);
glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE,
prog->matrix_uniform, &off_x, &off_y);
max_points = 500;
num_points = 0;
@ -105,10 +107,12 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
if (!num_points) {
points = glamor_get_vbo_space(screen,
max_points * (2 * sizeof (INT16)),
max_points *
(2 * sizeof (INT16)),
&vbo_offset);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT,
glVertexAttribPointer(GLAMOR_VERTEX_POS,
2, GL_SHORT,
GL_FALSE, 0, vbo_offset);
}
@ -149,7 +153,8 @@ glamor_poly_glyph_blt(DrawablePtr drawable, GCPtr gc,
int start_x, int y, unsigned int nglyph,
CharInfoPtr *ppci, void *pglyph_base)
{
if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base))
if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci,
pglyph_base))
return;
miPolyGlyphBlt(drawable, gc, start_x, y, nglyph,
ppci, pglyph_base);
@ -160,10 +165,13 @@ glamor_poly_glyph_blt_nf(DrawablePtr drawable, GCPtr gc,
int start_x, int y, unsigned int nglyph,
CharInfoPtr *ppci, void *pglyph_base)
{
if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base))
if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci,
pglyph_base))
return TRUE;
if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
if (glamor_ddx_fallback_check_pixmap(drawable) &&
glamor_ddx_fallback_check_gc(gc)) {
return FALSE;
}
miPolyGlyphBlt(drawable, gc, start_x, y, nglyph,
ppci, pglyph_base);
return TRUE;
@ -179,8 +187,8 @@ glamor_image_glyph_blt_nf(DrawablePtr drawable, GCPtr gc,
}
static Bool
glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
DrawablePtr drawable, int w, int h, int x, int y)
glamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap,
DrawablePtr drawable, int w, int h, int x, int y)
{
ScreenPtr screen = drawable->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@ -188,65 +196,40 @@ glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
glamor_pixmap_private *pixmap_priv;
uint8_t *bitmap_data = bitmap->devPrivate.ptr;
int bitmap_stride = bitmap->devKind;
int off_x, off_y;
glamor_program *prog;
RegionPtr clip = gc->pCompositeClip;
int box_x, box_y;
int yy, xx;
GLfloat xscale, yscale;
float color[4];
unsigned long fg_pixel = gc->fgPixel;
float *points, *next_point;
int num_points = 0;
int num_points;
INT16 *points = NULL;
char *vbo_offset;
RegionPtr clip;
if (w * h > MAXINT / (2 * sizeof(float)))
return FALSE;
if (gc->fillStyle != FillSolid) {
glamor_fallback("gc fillstyle not solid\n");
return FALSE;
}
goto bail;
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return FALSE;
goto bail;
glamor_make_current(glamor_priv);
if (!glamor_set_alu(screen, gc->alu)) {
if (gc->alu == GXclear)
fg_pixel = 0;
else {
glamor_fallback("unsupported alu %x\n", gc->alu);
return FALSE;
}
}
if (!glamor_set_planemask(pixmap, gc->planemask)) {
glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
return FALSE;
}
prog = glamor_use_program_fill(pixmap, gc,
&glamor_priv->poly_glyph_blt_progs,
&glamor_facet_poly_glyph_blt);
if (!prog)
goto bail_ctx;
glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
glUseProgram(glamor_priv->solid_prog);
glamor_get_rgba_from_pixel(fg_pixel,
&color[0], &color[1], &color[2], &color[3],
format_for_pixmap(pixmap));
glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
points = glamor_get_vbo_space(screen, w * h * sizeof(float) * 2,
points = glamor_get_vbo_space(screen, w * h * sizeof(INT16) * 2,
&vbo_offset);
next_point = points;
clip = fbGetCompositeClip(gc);
num_points = 0;
/* Note that because fb sets miTranslate in the GC, our incoming X
* and Y are in screen coordinate space (same for spans, but not
* other operations).
*/
for (yy = 0; yy < h; yy++) {
uint8_t *bitmap_row = bitmap_data + yy * bitmap_stride;
for (xx = 0; xx < w; xx++) {
@ -255,63 +238,58 @@ glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
x + xx,
y + yy,
NULL)) {
next_point[0] = v_from_x_coord_x(xscale, x + xx + off_x + 0.5);
if (glamor_priv->yInverted)
next_point[1] = v_from_x_coord_y_inverted(yscale, y + yy + off_y + 0.5);
else
next_point[1] = v_from_x_coord_y(yscale, y + yy + off_y + 0.5);
next_point += 2;
*points++ = x + xx;
*points++ = y + yy;
num_points++;
}
}
}
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
GL_FALSE, 2 * sizeof(float),
vbo_offset);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT,
GL_FALSE, 0, vbo_offset);
glamor_put_vbo_space(screen);
glDrawArrays(GL_POINTS, 0, num_points);
glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE,
prog->matrix_uniform, NULL, NULL);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
return TRUE;
}
static Bool
_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
DrawablePtr pDrawable, int w, int h, int x, int y,
Bool fallback)
{
glamor_pixmap_private *pixmap_priv;
if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
&& glamor_ddx_fallback_check_pixmap(&pBitmap->drawable)
&& glamor_ddx_fallback_check_gc(pGC))
return FALSE;
pixmap_priv = glamor_get_pixmap_private(pBitmap);
if (pixmap_priv->type == GLAMOR_MEMORY) {
if (glamor_push_pixels_points(pGC, pBitmap, pDrawable, w, h, x, y))
return TRUE;
glDrawArrays(GL_POINTS, 0, num_points);
}
miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
glDisable(GL_COLOR_LOGIC_OP);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
return TRUE;
bail_ctx:
glDisable(GL_COLOR_LOGIC_OP);
bail:
return FALSE;
}
void
glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
DrawablePtr pDrawable, int w, int h, int x, int y)
{
_glamor_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y, TRUE);
if (glamor_push_pixels_gl(pGC, pBitmap, pDrawable, w, h, x, y))
return;
miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
}
Bool
glamor_push_pixels_nf(GCPtr pGC, PixmapPtr pBitmap,
DrawablePtr pDrawable, int w, int h, int x, int y)
glamor_push_pixels_nf(GCPtr gc, PixmapPtr bitmap,
DrawablePtr drawable, int w, int h, int x, int y)
{
return _glamor_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y, FALSE);
if (glamor_push_pixels_gl(gc, bitmap, drawable, w, h, x, y))
return TRUE;
if (glamor_ddx_fallback_check_pixmap(drawable) &&
glamor_ddx_fallback_check_pixmap(&bitmap->drawable) &&
glamor_ddx_fallback_check_gc(gc))
{
return FALSE;
}
miPushPixels(gc, bitmap, drawable, w, h, x, y);
return TRUE;
}

View File

@ -168,7 +168,7 @@ clear_mask_cache(struct glamor_glyph_mask_cache *maskcache)
struct glamor_glyph_mask_cache_entry *mce;
glamor_solid(maskcache->pixmap, 0, CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE,
MASK_CACHE_MAX_SIZE, GXcopy, 0xFFFFFFFF, 0);
MASK_CACHE_MAX_SIZE, 0);
mce = &maskcache->mcache[0];
while (cnt--) {
mce->width = 0;
@ -448,9 +448,9 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen,
box.y1 = y;
box.x2 = x + glyph->info.width;
box.y2 = y + glyph->info.height;
glamor_copy_n_to_n_nf(&scratch->drawable,
&pCachePixmap->drawable, NULL,
&box, 1, -x, -y, FALSE, FALSE, 0, NULL);
glamor_copy(&scratch->drawable,
&pCachePixmap->drawable, NULL,
&box, 1, -x, -y, FALSE, FALSE, 0, NULL);
if (scratch != pGlyphPixmap)
screen->DestroyPixmap(scratch);
@ -1433,7 +1433,7 @@ glamor_glyphs_via_mask(CARD8 op,
glamor_destroy_pixmap(mask_pixmap);
return;
}
glamor_solid(mask_pixmap, 0, 0, width, height, GXcopy, 0xFFFFFFFF, 0);
glamor_solid(mask_pixmap, 0, 0, width, height, 0);
component_alpha = NeedsComponent(mask_format->format);
mask = CreatePicture(0, &mask_pixmap->drawable,
mask_format, CPComponentAlpha,

View File

@ -699,7 +699,7 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
width),
(INT16) (dst_picture->pDrawable->
height),
glamor_priv->yInverted, vertices);
vertices);
if (tex_normalize) {
glamor_set_normalize_tcoords_tri_stripe(*xscale, *yscale,
@ -710,17 +710,14 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
(INT16) (dst_picture->
pDrawable->height +
y_source),
glamor_priv->yInverted,
tex_vertices);
}
else {
glamor_set_tcoords_tri_strip((INT16) (dst_picture->pDrawable->width),
(INT16) (dst_picture->pDrawable->height),
x_source, y_source,
glamor_set_tcoords_tri_strip(x_source, y_source,
(INT16) (dst_picture->pDrawable->width) +
x_source,
(INT16) (dst_picture->pDrawable->height) +
y_source, glamor_priv->yInverted,
y_source,
tex_vertices);
}
@ -1084,13 +1081,11 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
r2 = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.
radius);
glamor_set_circle_centre(width, height, c1x, c1y, glamor_priv->yInverted,
cxy);
glamor_set_circle_centre(width, height, c1x, c1y, cxy);
glUniform2fv(c1_uniform_location, 1, cxy);
glUniform1f(r1_uniform_location, r1);
glamor_set_circle_centre(width, height, c2x, c2y, glamor_priv->yInverted,
cxy);
glamor_set_circle_centre(width, height, c2x, c2y, cxy);
glUniform2fv(c2_uniform_location, 1, cxy);
glUniform1f(r2_uniform_location, r2);
@ -1322,7 +1317,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
linear.p1.x),
pixman_fixed_to_double(src_picture->pSourcePict->
linear.p1.y),
glamor_priv->yInverted, pt1);
pt1);
DEBUGF("pt1:(%f, %f) ---> (%f %f)\n",
pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.x),
pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.y),
@ -1333,7 +1328,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
linear.p2.x),
pixman_fixed_to_double(src_picture->pSourcePict->
linear.p2.y),
glamor_priv->yInverted, pt2);
pt2);
DEBUGF("pt2:(%f, %f) ---> (%f %f)\n",
pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.x),
pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.y),

View File

@ -797,9 +797,9 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv,
copy_box.y2 = temp_extent->y2 - temp_extent->y1;
dx = temp_extent->x1;
dy = temp_extent->y1;
glamor_copy_n_to_n(&priv->base.pixmap->drawable,
&temp_pixmap->drawable,
NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
glamor_copy(&priv->base.pixmap->drawable,
&temp_pixmap->drawable,
NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
// glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width,
// temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff00);
}
@ -829,9 +829,10 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv,
copy_box.x1, copy_box.y1, copy_box.x2,
copy_box.y2, dx, dy);
glamor_copy_n_to_n(&priv->base.pixmap->drawable,
&temp_pixmap->drawable,
NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
glamor_copy(&priv->base.pixmap->drawable,
&temp_pixmap->drawable,
NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
box++;
}
}

187
glamor/glamor_lines.c Normal file
View File

@ -0,0 +1,187 @@
/*
* Copyright © 2014 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
#include "glamor_program.h"
#include "glamor_transform.h"
#include "glamor_prepare.h"
static const glamor_facet glamor_facet_poly_lines = {
.name = "poly_lines",
.vs_vars = "attribute vec2 primitive;\n",
.vs_exec = (" vec2 pos = vec2(0.0,0.0);\n"
GLAMOR_POS(gl_Position, primitive.xy)),
};
static Bool
glamor_poly_lines_solid_gl(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points)
{
ScreenPtr screen = drawable->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv;
glamor_program *prog;
int off_x, off_y;
DDXPointPtr v;
char *vbo_offset;
int box_x, box_y;
int add_last;
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
goto bail;
add_last = 0;
if (gc->capStyle != CapNotLast)
add_last = 1;
if (n < 2)
return TRUE;
glamor_make_current(glamor_priv);
prog = glamor_use_program_fill(pixmap, gc,
&glamor_priv->poly_line_program,
&glamor_facet_poly_lines);
if (!prog)
goto bail_ctx;
/* Set up the vertex buffers for the points */
v = glamor_get_vbo_space(drawable->pScreen,
(n + add_last) * sizeof (DDXPointRec),
&vbo_offset);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
sizeof (DDXPointRec), vbo_offset);
if (mode == CoordModePrevious) {
int i;
DDXPointRec here = { 0, 0 };
for (i = 0; i < n; i++) {
here.x += points[i].x;
here.y += points[i].y;
v[i] = here;
}
} else {
memcpy(v, points, n * sizeof (DDXPointRec));
}
if (add_last) {
v[n].x = v[n-1].x + 1;
v[n].y = v[n-1].y;
}
glamor_put_vbo_space(screen);
glEnable(GL_SCISSOR_TEST);
glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
int nbox = RegionNumRects(gc->pCompositeClip);
BoxPtr box = RegionRects(gc->pCompositeClip);
glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE,
prog->matrix_uniform, &off_x, &off_y);
while (nbox--) {
glScissor(box->x1 + off_x,
box->y1 + off_y,
box->x2 - box->x1,
box->y2 - box->y1);
box++;
glDrawArrays(GL_LINE_STRIP, 0, n + add_last);
}
}
glDisable(GL_SCISSOR_TEST);
glDisable(GL_COLOR_LOGIC_OP);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
return TRUE;
bail_ctx:
glDisable(GL_COLOR_LOGIC_OP);
bail:
return FALSE;
}
static Bool
glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points)
{
if (gc->lineWidth != 0)
return FALSE;
switch (gc->lineStyle) {
case LineSolid:
return glamor_poly_lines_solid_gl(drawable, gc, mode, n, points);
case LineOnOffDash:
return glamor_poly_lines_dash_gl(drawable, gc, mode, n, points);
case LineDoubleDash:
if (gc->fillStyle == FillTiled)
return glamor_poly_lines_solid_gl(drawable, gc, mode, n, points);
else
return glamor_poly_lines_dash_gl(drawable, gc, mode, n, points);
default:
return FALSE;
}
}
static void
glamor_poly_lines_bail(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points)
{
glamor_fallback("to %p (%c)\n", drawable,
glamor_get_drawable_location(drawable));
miPolylines(drawable, gc, mode, n, points);
}
void
glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points)
{
if (glamor_poly_lines_gl(drawable, gc, mode, n, points))
return;
glamor_poly_lines_bail(drawable, gc, mode, n, points);
}
Bool
glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points)
{
if (glamor_poly_lines_gl(drawable, gc, mode, n, points))
return TRUE;
if (glamor_ddx_fallback_check_pixmap(drawable) &&
glamor_ddx_fallback_check_gc(gc))
{
return FALSE;
}
glamor_poly_lines_bail(drawable, gc, mode, n, points);
return TRUE;
}

View File

@ -45,24 +45,6 @@ glamor_upload_picture_to_texture(PicturePtr picture)
return glamor_upload_pixmap_to_texture(pixmap);
}
Bool
glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access)
{
if (!picture || !picture->pDrawable)
return TRUE;
return glamor_prepare_access(picture->pDrawable, access);
}
void
glamor_finish_access_picture(PicturePtr picture)
{
if (!picture || !picture->pDrawable)
return;
glamor_finish_access(picture->pDrawable);
}
/*
* We should already have drawable attached to it, if it has one.
* Then set the attached pixmap to is_picture format, and set

View File

@ -747,11 +747,6 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
glamor_get_screen_private(pixmap->drawable.pScreen);
static float vertices[8];
static float texcoords[8] = { 0, 1,
1, 1,
1, 0,
0, 0
};
static float texcoords_inv[8] = { 0, 0,
1, 0,
1, 1,
@ -760,11 +755,8 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
float *ptexcoords;
float dst_xscale, dst_yscale;
GLuint tex = 0;
int need_flip;
int need_free_bits = 0;
need_flip = !glamor_priv->yInverted;
if (bits == NULL)
goto ready_to_upload;
@ -798,7 +790,7 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
/* Try fast path firstly, upload the pixmap to the texture attached
* to the fbo directly. */
if (no_alpha == 0
&& revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING && !need_flip
&& revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING
#ifdef WALKAROUND_LARGE_TEXTURE_MAP
&& pixmap_priv->type != GLAMOR_TEXTURE_LARGE
#endif
@ -818,17 +810,14 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
return TRUE;
}
if (need_flip)
ptexcoords = texcoords;
else
ptexcoords = texcoords_inv;
ptexcoords = texcoords_inv;
pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale);
glamor_set_normalize_vcoords(pixmap_priv, dst_xscale,
dst_yscale,
x, y,
x + w, y + h,
glamor_priv->yInverted, vertices);
vertices);
/* Slow path, we need to flip y or wire alpha to 1. */
glamor_make_current(glamor_priv);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
@ -865,10 +854,7 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
/*
* Prepare to upload a pixmap to texture memory.
* no_alpha equals 1 means the format needs to wire alpha to 1.
* Two condtion need to setup a fbo for a pixmap
* 1. !yInverted, we need to do flip if we are not yInverted.
* 2. no_alpha != 0, we need to wire the alpha.
* */
*/
static int
glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
int revert, int swap_rb)
@ -896,8 +882,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
return 0;
if (!(no_alpha || (revert == REVERT_NORMAL)
|| (swap_rb != SWAP_NONE_UPLOADING)
|| !glamor_priv->yInverted)) {
|| (swap_rb != SWAP_NONE_UPLOADING))) {
/* We don't need a fbo, a simple texture uploading should work. */
flag = GLAMOR_CREATE_FBO_NO_FBO;
@ -939,26 +924,6 @@ glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits,
}
}
/*
* download sub region from a large region.
*/
static void
glamor_get_bits(char *dst_bits, int dst_stride, char *src_bits,
int src_stride, int bpp, int x, int y, int w, int h)
{
int j;
int byte_per_pixel;
byte_per_pixel = bpp / 8;
dst_bits += y * dst_stride + x * byte_per_pixel;
for (j = y; j < y + h; j++) {
memcpy(dst_bits, src_bits, w * byte_per_pixel);
src_bits += src_stride;
dst_bits += dst_stride;
}
}
Bool
glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
int h, int stride, void *bits, int pbo)
@ -1100,13 +1065,6 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
return ret;
}
void
glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
{
if (glamor_upload_pixmap_to_texture(pixmap) != GLAMOR_UPLOAD_DONE)
LogMessage(X_WARNING, "Failed to restore pixmap to texture.\n");
}
/*
* as gles2 only support a very small set of color format and
* type when do glReadPixel,
@ -1142,7 +1100,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
glamor_set_normalize_vcoords((struct glamor_pixmap_private *) NULL,
temp_xscale, temp_yscale, 0, 0, w, h,
glamor_priv->yInverted, vertices);
vertices);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
2 * sizeof(float), vertices);
@ -1153,7 +1111,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
source_yscale,
x, y,
x + w, y + h,
glamor_priv->yInverted, texcoords);
texcoords);
glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
2 * sizeof(float), texcoords);
@ -1176,330 +1134,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
return temp_fbo;
}
/*
* Download a sub region of pixmap to a specified memory region.
* The pixmap must have a valid FBO, otherwise return a NULL.
* */
static void *
_glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
GLenum type, int no_alpha,
int revert, int swap_rb,
int x, int y, int w, int h,
int stride, void *bits, int pbo,
glamor_access_t access)
{
glamor_pixmap_private *pixmap_priv;
GLenum gl_access = 0, gl_usage = 0;
void *data, *read;
glamor_screen_private *glamor_priv =
glamor_get_screen_private(pixmap->drawable.pScreen);
glamor_pixmap_fbo *temp_fbo = NULL;
int need_post_conversion = 0;
int need_free_data = 0;
int fbo_x_off, fbo_y_off;
data = bits;
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return NULL;
switch (access) {
case GLAMOR_ACCESS_RO:
gl_access = GL_READ_ONLY;
gl_usage = GL_STREAM_READ;
break;
case GLAMOR_ACCESS_RW:
gl_access = GL_READ_WRITE;
gl_usage = GL_DYNAMIC_DRAW;
break;
default:
ErrorF("Glamor: Invalid access code. %d\n", access);
assert(0);
}
glamor_make_current(glamor_priv);
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
need_post_conversion = (revert > REVERT_NORMAL);
if (need_post_conversion) {
if (pixmap->drawable.depth == 1) {
int temp_stride;
temp_stride = (((w * 8 + 7) / 8) + 3) & ~3;
data = malloc(temp_stride * h);
if (data == NULL)
return NULL;
need_free_data = 1;
}
}
pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
&& !need_post_conversion
&& (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) {
if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, x, y, w, h,
format, type, no_alpha,
revert, swap_rb))) {
free(data);
return NULL;
}
x = 0;
y = 0;
fbo_x_off = 0;
fbo_y_off = 0;
}
glPixelStorei(GL_PACK_ALIGNMENT, 4);
if (glamor_priv->has_pack_invert || glamor_priv->yInverted) {
if (!glamor_priv->yInverted) {
assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
glPixelStorei(GL_PACK_INVERT_MESA, 1);
}
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && data == NULL) {
assert(pbo > 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, gl_usage);
}
glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data);
if (!glamor_priv->yInverted) {
assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
glPixelStorei(GL_PACK_INVERT_MESA, 0);
}
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && bits == NULL) {
bits = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
}
else {
unsigned int temp_pbo;
int yy;
glamor_make_current(glamor_priv);
glGenBuffers(1, &temp_pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, temp_pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, GL_STREAM_READ);
glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, 0);
read = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
for (yy = 0; yy < pixmap->drawable.height; yy++)
memcpy((char *) data + yy * stride,
(char *) read + (h - yy - 1) * stride, stride);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glDeleteBuffers(1, &temp_pbo);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (need_post_conversion) {
/* As OpenGL desktop version never enters here.
* Don't need to consider if the pbo is valid.*/
bits = glamor_color_convert_to_bits(data, bits,
w, h,
stride, no_alpha, revert, swap_rb);
}
if (temp_fbo != NULL)
glamor_destroy_fbo(temp_fbo);
if (need_free_data)
free(data);
return bits;
}
void *
glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
int stride, void *bits, int pbo,
glamor_access_t access)
{
GLenum format, type;
int no_alpha, revert, swap_rb;
glamor_pixmap_private *pixmap_priv;
Bool force_clip;
if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format,
&type,
&no_alpha,
&revert, &swap_rb, 0)) {
glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
return NULL;
}
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return NULL;
force_clip = pixmap_priv->base.glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP
&& !glamor_check_fbo_size(pixmap_priv->base.glamor_priv, w, h);
if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE || force_clip) {
RegionRec region;
BoxRec box;
int n_region;
glamor_pixmap_clipped_regions *clipped_regions;
void *sub_bits;
int i, j;
sub_bits = malloc(h * stride);
if (sub_bits == NULL)
return FALSE;
box.x1 = x;
box.y1 = y;
box.x2 = x + w;
box.y2 = y + h;
RegionInitBoxes(&region, &box, 1);
if (!force_clip)
clipped_regions =
glamor_compute_clipped_regions(pixmap_priv, &region, &n_region,
0, 0, 0);
else
clipped_regions =
glamor_compute_clipped_regions_ext(pixmap_priv, &region,
&n_region,
pixmap_priv->large.block_w,
pixmap_priv->large.block_h,
0,
0);
DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h);
for (i = 0; i < n_region; i++) {
BoxPtr boxes;
int nbox;
int temp_stride;
void *temp_bits;
assert(pbo == 0);
SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
boxes = RegionRects(clipped_regions[i].region);
nbox = RegionNumRects(clipped_regions[i].region);
for (j = 0; j < nbox; j++) {
temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1,
pixmap->drawable.depth);
if (boxes[j].x1 == x && temp_stride == stride) {
temp_bits = (char *) bits + (boxes[j].y1 - y) * stride;
}
else {
temp_bits = sub_bits;
}
DEBUGF("download x %d y %d w %d h %d temp stride %d \n",
boxes[j].x1, boxes[j].y1,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1, temp_stride);
/* For large pixmap, we don't support pbo currently. */
assert(pbo == 0);
if (_glamor_download_sub_pixmap_to_cpu
(pixmap, format, type, no_alpha, revert, swap_rb,
boxes[j].x1, boxes[j].y1, boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1, temp_stride, temp_bits, pbo,
access) == FALSE) {
RegionUninit(&region);
free(sub_bits);
assert(0);
return NULL;
}
if (boxes[j].x1 != x || temp_stride != stride)
glamor_get_bits(bits, stride, temp_bits, temp_stride,
pixmap->drawable.bitsPerPixel,
boxes[j].x1 - x, boxes[j].y1 - y,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1);
}
RegionDestroy(clipped_regions[i].region);
}
free(sub_bits);
free(clipped_regions);
RegionUninit(&region);
return bits;
}
else
return _glamor_download_sub_pixmap_to_cpu(pixmap, format, type,
no_alpha, revert, swap_rb, x,
y, w, h, stride, bits, pbo,
access);
}
/**
* Move a pixmap to CPU memory.
* The input data is the pixmap's fbo.
* The output data is at pixmap->devPrivate.ptr. We always use pbo
* to read the fbo and then map it to va. If possible, we will use
* it directly as devPrivate.ptr.
* If successfully download a fbo to cpu then return TRUE.
* Otherwise return FALSE.
**/
Bool
glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
{
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
unsigned int stride;
void *data = NULL, *dst;
glamor_screen_private *glamor_priv =
glamor_get_screen_private(pixmap->drawable.pScreen);
int pbo = 0;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return TRUE;
glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DOWNLOAD,
"Downloading pixmap %p %dx%d depth%d\n",
pixmap,
pixmap->drawable.width,
pixmap->drawable.height, pixmap->drawable.depth);
stride = pixmap->devKind;
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
|| (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)
|| pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
data = malloc(stride * pixmap->drawable.height);
}
else {
glamor_make_current(glamor_priv);
if (pixmap_priv->base.fbo->pbo == 0)
glGenBuffers(1, &pixmap_priv->base.fbo->pbo);
pbo = pixmap_priv->base.fbo->pbo;
}
if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) {
stride = PixmapBytePad(pixmap->drawable.width, pixmap->drawable.depth);
pixmap_priv->base.drm_stride = pixmap->devKind;
pixmap->devKind = stride;
}
dst = glamor_download_sub_pixmap_to_cpu(pixmap, 0, 0,
pixmap->drawable.width,
pixmap->drawable.height,
pixmap->devKind, data, pbo, access);
if (!dst) {
if (data)
free(data);
return FALSE;
}
if (pbo != 0)
pixmap_priv->base.fbo->pbo_valid = 1;
pixmap_priv->base.gl_fbo = GLAMOR_FBO_DOWNLOADED;
pixmap->devPrivate.ptr = dst;
return TRUE;
}
/* fixup a fbo to the exact size as the pixmap. */
/* XXX LARGE pixmap? */
Bool
@ -1558,132 +1192,3 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
return ret;
}
/*
* We may use this function to reduce a large pixmap to a small sub
* pixmap. Two scenarios currently:
* 1. When fallback a large textured pixmap to CPU but we do need to
* do rendering within a small sub region, then we can just get a
* sub region.
*
* 2. When uploading a large pixmap to texture but we only need to
* use part of the source/mask picture. As glTexImage2D will be more
* efficient to upload a contingent region rather than a sub block
* in a large buffer. We use this function to gather the sub region
* to a contingent sub pixmap.
*
* The sub-pixmap must have the same format as the source pixmap.
*
* */
PixmapPtr
glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h,
glamor_access_t access)
{
glamor_screen_private *glamor_priv;
PixmapPtr sub_pixmap;
glamor_pixmap_private *sub_pixmap_priv, *pixmap_priv;
void *data;
int pbo;
int flag;
if (x < 0 || y < 0)
return NULL;
w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w;
h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h;
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return NULL;
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 ||
pixmap_priv->type == GLAMOR_TEXTURE_LARGE)
flag = GLAMOR_CREATE_PIXMAP_CPU;
else
flag = GLAMOR_CREATE_PIXMAP_MAP;
sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
pixmap->drawable.depth, flag);
if (sub_pixmap == NULL)
return NULL;
sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
pbo =
sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.
fbo->pbo : 0) : 0;
if (pixmap_priv->base.is_picture) {
sub_pixmap_priv->base.picture = pixmap_priv->base.picture;
sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
}
if (pbo)
data = NULL;
else
data = sub_pixmap->devPrivate.ptr;
data =
glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h,
sub_pixmap->devKind, data, pbo,
access);
if (data == NULL) {
fbDestroyPixmap(sub_pixmap);
return NULL;
}
if (pbo) {
assert(sub_pixmap->devPrivate.ptr == NULL);
sub_pixmap->devPrivate.ptr = data;
sub_pixmap_priv->base.fbo->pbo_valid = 1;
}
#if 0
struct pixman_box16 box;
PixmapPtr new_sub_pixmap;
int dx, dy;
box.x1 = 0;
box.y1 = 0;
box.x2 = w;
box.y2 = h;
dx = x;
dy = y;
new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
pixmap->drawable.depth,
GLAMOR_CREATE_PIXMAP_CPU);
glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap->drawable, NULL, &box,
1, dx, dy, 0, 0, 0, NULL);
glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1);
#endif
return sub_pixmap;
}
void
glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y,
int w, int h, glamor_access_t access)
{
void *bits;
int pbo;
glamor_pixmap_private *sub_pixmap_priv;
if (access != GLAMOR_ACCESS_RO) {
sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
if (sub_pixmap_priv->base.fbo && sub_pixmap_priv->base.fbo->pbo_valid) {
bits = NULL;
pbo = sub_pixmap_priv->base.fbo->pbo;
}
else {
bits = sub_pixmap->devPrivate.ptr;
pbo = 0;
}
assert(x >= 0 && y >= 0);
w = (w > sub_pixmap->drawable.width) ? sub_pixmap->drawable.width : w;
h = (h > sub_pixmap->drawable.height) ? sub_pixmap->drawable.height : h;
glamor_upload_sub_pixmap_to_texture(pixmap, x, y, w, h,
sub_pixmap->devKind, bits, pbo);
}
glamor_destroy_pixmap(sub_pixmap);
}

View File

@ -105,9 +105,6 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint
glDisable(GL_COLOR_LOGIC_OP);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
glamor_priv->state = RENDER_STATE;
glamor_priv->render_idle_cnt = 0;
return TRUE;
bail_ctx:

View File

@ -1,136 +0,0 @@
/*
* Copyright © 2009 Intel Corporation
* Copyright © 1998 Keith Packard
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*
*/
#include "glamor_priv.h"
/** @file glamor_polylines.c
*
* GC PolyFillRect implementation, taken straight from fb_fill.c
*/
/**
* glamor_poly_lines() checks if it can accelerate the lines as a group of
* horizontal or vertical lines (rectangles), and uses existing rectangle fill
* acceleration if so.
*/
static Bool
_glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
DDXPointPtr points, Bool fallback)
{
xRectangle *rects;
int x1, x2, y1, y2;
int i;
/* Don't try to do wide lines or non-solid fill style. */
if (gc->lineWidth != 0) {
/* This ends up in miSetSpans, which is accelerated as well as we
* can hope X wide lines will be.
*/
goto fail;
}
if (gc->lineStyle != LineSolid) {
glamor_fallback("non-solid fill line style %d\n", gc->lineStyle);
goto fail;
}
rects = malloc(sizeof(xRectangle) * (n - 1));
x1 = points[0].x;
y1 = points[0].y;
/* If we have any non-horizontal/vertical, fall back. */
for (i = 0; i < n - 1; i++) {
if (mode == CoordModePrevious) {
x2 = x1 + points[i + 1].x;
y2 = y1 + points[i + 1].y;
}
else {
x2 = points[i + 1].x;
y2 = points[i + 1].y;
}
if (x1 != x2 && y1 != y2) {
free(rects);
glamor_fallback("stub diagonal poly_line\n");
goto fail;
}
if (x1 < x2) {
rects[i].x = x1;
rects[i].width = x2 - x1 + 1;
}
else {
rects[i].x = x2;
rects[i].width = x1 - x2 + 1;
}
if (y1 < y2) {
rects[i].y = y1;
rects[i].height = y2 - y1 + 1;
}
else {
rects[i].y = y2;
rects[i].height = y1 - y2 + 1;
}
x1 = x2;
y1 = y2;
}
gc->ops->PolyFillRect(drawable, gc, n - 1, rects);
free(rects);
return TRUE;
fail:
if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)
&& glamor_ddx_fallback_check_gc(gc))
return FALSE;
switch (gc->lineStyle) {
case LineSolid:
if (gc->lineWidth == 0)
miZeroLine(drawable, gc, mode, n, points);
else
miWideLine(drawable, gc, mode, n, points);
break;
case LineOnOffDash:
case LineDoubleDash:
miWideDash(drawable, gc, mode, n, points);
break;
}
return TRUE;
}
void
glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
DDXPointPtr points)
{
_glamor_poly_lines(drawable, gc, mode, n, points, TRUE);
}
Bool
glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, int mode, int n,
DDXPointPtr points)
{
return _glamor_poly_lines(drawable, gc, mode, n, points, FALSE);
}

274
glamor/glamor_prepare.c Normal file
View File

@ -0,0 +1,274 @@
/*
* Copyright © 2014 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
#include "glamor_prepare.h"
#include "glamor_transfer.h"
/*
* Make a pixmap ready to draw with fb by
* creating a PBO large enough for the whole object
* and downloading all of the FBOs into it.
*/
static Bool
glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
int gl_access, gl_usage;
RegionRec region;
if (priv->type == GLAMOR_DRM_ONLY)
return FALSE;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
return TRUE;
RegionInit(&region, box, 1);
/* See if it's already mapped */
if (pixmap->devPrivate.ptr) {
/*
* Someone else has mapped this pixmap;
* we'll assume that it's directly mapped
* by a lower level driver
*/
if (!priv->base.prepared)
return TRUE;
/* In X, multiple Drawables can be stored in the same Pixmap (such as
* each individual window in a non-composited screen pixmap, or the
* reparented window contents inside the window-manager-decorated window
* pixmap on a composited screen).
*
* As a result, when doing a series of mappings for a fallback, we may
* need to add more boxes to the set of data we've downloaded, as we go.
*/
RegionSubtract(&region, &region, &priv->base.prepare_region);
if (!RegionNotEmpty(&region))
return TRUE;
if (access == GLAMOR_ACCESS_RW)
FatalError("attempt to remap buffer as writable");
if (priv->base.pbo) {
glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->base.pbo);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
pixmap->devPrivate.ptr = NULL;
}
} else {
RegionInit(&priv->base.prepare_region, box, 1);
if (glamor_priv->has_rw_pbo) {
if (priv->base.pbo == 0)
glGenBuffers(1, &priv->base.pbo);
if (access == GLAMOR_ACCESS_RW)
gl_usage = GL_DYNAMIC_DRAW;
else
gl_usage = GL_STREAM_READ;
glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->base.pbo);
glBufferData(GL_PIXEL_PACK_BUFFER,
pixmap->devKind * pixmap->drawable.height, NULL,
gl_usage);
} else {
pixmap->devPrivate.ptr = malloc(pixmap->devKind *
pixmap->drawable.height);
if (!pixmap->devPrivate.ptr)
return FALSE;
}
priv->base.map_access = access;
}
glamor_download_boxes(pixmap, RegionRects(&region), RegionNumRects(&region),
0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind);
RegionUninit(&region);
if (glamor_priv->has_rw_pbo) {
if (priv->base.map_access == GLAMOR_ACCESS_RW)
gl_access = GL_READ_WRITE;
else
gl_access = GL_READ_ONLY;
pixmap->devPrivate.ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
priv->base.prepared = TRUE;
return TRUE;
}
/*
* When we're done with the drawable, unmap the PBO, reupload
* if we were writing to it and then unbind it to release the memory
*/
static void
glamor_fini_pixmap(PixmapPtr pixmap)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
return;
if (!priv->base.prepared)
return;
if (glamor_priv->has_rw_pbo) {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->base.pbo);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
pixmap->devPrivate.ptr = NULL;
}
if (priv->base.map_access == GLAMOR_ACCESS_RW) {
glamor_upload_boxes(pixmap,
RegionRects(&priv->base.prepare_region),
RegionNumRects(&priv->base.prepare_region),
0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind);
}
RegionUninit(&priv->base.prepare_region);
if (glamor_priv->has_rw_pbo) {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glDeleteBuffers(1, &priv->base.pbo);
priv->base.pbo = 0;
} else {
free(pixmap->devPrivate.ptr);
pixmap->devPrivate.ptr = NULL;
}
priv->base.prepared = FALSE;
}
Bool
glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
{
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
BoxRec box;
int off_x, off_y;
glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
box.x1 = drawable->x + off_x;
box.x2 = box.x1 + drawable->width;
box.y1 = drawable->y + off_y;
box.y2 = box.y1 + drawable->height;
return glamor_prep_pixmap_box(pixmap, access, &box);
}
Bool
glamor_prepare_access_box(DrawablePtr drawable, glamor_access_t access,
int x, int y, int w, int h)
{
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
BoxRec box;
int off_x, off_y;
glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
box.x1 = drawable->x + x + off_x;
box.x2 = box.x1 + w;
box.y1 = drawable->y + y + off_y;
box.y2 = box.y1 + h;
return glamor_prep_pixmap_box(pixmap, access, &box);
}
void
glamor_finish_access(DrawablePtr drawable)
{
glamor_fini_pixmap(glamor_get_drawable_pixmap(drawable));
}
/*
* Make a picture ready to use with fb.
*/
Bool
glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access)
{
if (!picture || !picture->pDrawable)
return TRUE;
return glamor_prepare_access(picture->pDrawable, access);
}
Bool
glamor_prepare_access_picture_box(PicturePtr picture, glamor_access_t access,
int x, int y, int w, int h)
{
if (!picture || !picture->pDrawable)
return TRUE;
return glamor_prepare_access_box(picture->pDrawable, access,
x, y, w, h);
}
void
glamor_finish_access_picture(PicturePtr picture)
{
if (!picture || !picture->pDrawable)
return;
glamor_finish_access(picture->pDrawable);
}
/*
* Make a GC ready to use with fb. This just
* means making sure the appropriate fill pixmap is
* in CPU memory again
*/
Bool
glamor_prepare_access_gc(GCPtr gc)
{
switch (gc->fillStyle) {
case FillTiled:
return glamor_prepare_access(&gc->tile.pixmap->drawable,
GLAMOR_ACCESS_RO);
case FillStippled:
case FillOpaqueStippled:
return glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO);
}
return TRUE;
}
/*
* Free any temporary CPU pixmaps for the GC
*/
void
glamor_finish_access_gc(GCPtr gc)
{
switch (gc->fillStyle) {
case FillTiled:
glamor_finish_access(&gc->tile.pixmap->drawable);
break;
case FillStippled:
case FillOpaqueStippled:
glamor_finish_access(&gc->stipple->drawable);
break;
}
}

View File

@ -20,25 +20,33 @@
* OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
#ifndef _GLAMOR_PREPARE_H_
#define _GLAMOR_PREPARE_H_
Bool
glamor_poly_segment_nf(DrawablePtr drawable, GCPtr gc, int nseg,
xSegment *seg)
{
if (glamor_ddx_fallback_check_pixmap(drawable) &&
glamor_ddx_fallback_check_gc(gc)) {
return FALSE;
}
glamor_prepare_access(DrawablePtr drawable, glamor_access_t access);
miPolySegment(drawable, gc, nseg, seg);
return TRUE;
}
Bool
glamor_prepare_access_box(DrawablePtr drawable, glamor_access_t access,
int x, int y, int w, int h);
void
glamor_poly_segment(DrawablePtr drawable, GCPtr gc, int nseg,
xSegment *seg)
{
miPolySegment(drawable, gc, nseg, seg);
}
glamor_finish_access(DrawablePtr drawable);
Bool
glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access);
Bool
glamor_prepare_access_picture_box(PicturePtr picture, glamor_access_t access,
int x, int y, int w, int h);
void
glamor_finish_access_picture(PicturePtr picture);
Bool
glamor_prepare_access_gc(GCPtr gc);
void
glamor_finish_access_gc(GCPtr gc);
#endif /* _GLAMOR_PREPARE_H_ */

View File

@ -31,6 +31,7 @@
#include <xorg-server.h>
#include "glamor.h"
#include "xvdix.h"
#include <epoxy/gl.h>
#if GLAMOR_HAS_GBM
@ -193,13 +194,7 @@ struct glamor_saved_procs {
#define GLAMOR_TICK_AFTER(t0, t1) \
(((int)(t1) - (int)(t0)) < 0)
#define IDLE_STATE 0
#define RENDER_STATE 1
#define BLIT_STATE 2
#define RENDER_IDEL_MAX 32
typedef struct glamor_screen_private {
Bool yInverted;
unsigned int tick;
enum glamor_gl_flavor gl_flavor;
int glsl_version;
@ -208,16 +203,14 @@ typedef struct glamor_screen_private {
int has_map_buffer_range;
int has_buffer_storage;
int has_khr_debug;
int has_nv_texture_barrier;
int max_fbo_size;
int has_rw_pbo;
struct xorg_list
fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT];
unsigned long fbo_cache_watermark;
/* glamor_solid */
GLint solid_prog;
GLint solid_color_uniform_location;
/* glamor point shader */
glamor_program point_prog;
@ -235,6 +228,20 @@ typedef struct glamor_screen_private {
glamor_program te_text_prog;
glamor_program image_text_prog;
/* glamor copy shaders */
glamor_program copy_area_prog;
glamor_program copy_plane_prog;
/* glamor line shader */
glamor_program_fill poly_line_program;
/* glamor segment shaders */
glamor_program_fill poly_segment_program;
/* glamor dash line shader */
glamor_program_fill on_off_dash_line_progs;
glamor_program double_dash_line_prog;
/* vertext/elment_index buffer object for render */
GLuint vbo, ebo;
/** Next offset within the VBO that glamor_get_vbo_space() will use. */
@ -261,10 +268,6 @@ typedef struct glamor_screen_private {
GLint finish_access_revert[2];
GLint finish_access_swap_rb[2];
/* glamor_tile */
GLint tile_prog;
GLint tile_wh;
/* glamor gradient, 0 for small nstops, 1 for
large nstops and 2 for dynamic generate. */
GLint gradient_prog[SHADER_GRADIENT_COUNT][3];
@ -280,8 +283,6 @@ typedef struct glamor_screen_private {
char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1];
int delayed_fallback_pending;
int flags;
int state;
unsigned int render_idle_cnt;
ScreenPtr screen;
int dri3_enabled;
@ -430,6 +431,9 @@ typedef struct glamor_pixmap_private_base {
int drm_stride;
glamor_screen_private *glamor_priv;
PicturePtr picture;
GLuint pbo;
RegionRec prepare_region;
Bool prepared;
#if GLAMOR_HAS_GBM
EGLImageKHR image;
#endif
@ -528,7 +532,7 @@ glamor_pixmap_hcnt(glamor_pixmap_private *priv)
for (y = 0; y < glamor_pixmap_hcnt(priv); y++) \
for (x = 0; x < glamor_pixmap_wcnt(priv); x++)
/*
/*
* Pixmap dynamic status, used by dynamic upload feature.
*
* GLAMOR_NONE: initial status, don't need to do anything.
@ -544,19 +548,29 @@ typedef enum glamor_pixmap_status {
GLAMOR_UPLOAD_FAILED
} glamor_pixmap_status_t;
extern DevPrivateKey glamor_screen_private_key;
extern DevPrivateKey glamor_pixmap_private_key;
/* GC private structure. Currently holds only any computed dash pixmap */
typedef struct {
PixmapPtr dash;
PixmapPtr stipple;
DamagePtr stipple_damage;
} glamor_gc_private;
extern DevPrivateKeyRec glamor_gc_private_key;
extern DevPrivateKeyRec glamor_screen_private_key;
extern DevPrivateKeyRec glamor_pixmap_private_key;
static inline glamor_screen_private *
glamor_get_screen_private(ScreenPtr screen)
{
return (glamor_screen_private *)
dixLookupPrivate(&screen->devPrivates, glamor_screen_private_key);
dixLookupPrivate(&screen->devPrivates, &glamor_screen_private_key);
}
static inline void
glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv)
{
dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, priv);
dixSetPrivate(&screen->devPrivates, &glamor_screen_private_key, priv);
}
static inline glamor_pixmap_private *
@ -564,17 +578,23 @@ glamor_get_pixmap_private(PixmapPtr pixmap)
{
glamor_pixmap_private *priv;
priv = dixLookupPrivate(&pixmap->devPrivates, glamor_pixmap_private_key);
priv = dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key);
if (!priv) {
glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY);
priv = dixLookupPrivate(&pixmap->devPrivates,
glamor_pixmap_private_key);
&glamor_pixmap_private_key);
}
return priv;
}
void glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv);
static inline glamor_gc_private *
glamor_get_gc_private(GCPtr gc)
{
return dixLookupPrivate(&gc->devPrivates, &glamor_gc_private_key);
}
/**
* Returns TRUE if the given planemask covers all the significant bits in the
* pixel values for pDrawable.
@ -614,32 +634,13 @@ glamor_pixmap_fbo *glamor_create_fbo_array(glamor_screen_private *glamor_priv,
int flag, int block_w, int block_h,
glamor_pixmap_private *);
/* glamor_copyarea.c */
RegionPtr
glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int width, int height, int dstx, int dsty);
void glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc,
BoxPtr box, int nbox, int dx, int dy, Bool reverse,
Bool upsidedown, Pixel bitplane, void *closure);
/* glamor_core.c */
Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access);
void glamor_finish_access(DrawablePtr drawable);
Bool glamor_prepare_access_window(WindowPtr window);
void glamor_finish_access_window(WindowPtr window);
Bool glamor_prepare_access_gc(GCPtr gc);
void glamor_finish_access_gc(GCPtr gc);
void glamor_init_finish_access_shaders(ScreenPtr screen);
void glamor_fini_finish_access_shaders(ScreenPtr screen);
const Bool glamor_get_drawable_location(const DrawablePtr drawable);
void glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap,
int *x, int *y);
Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple,
int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
unsigned long fg_pixel, unsigned long bg_pixel,
int stipple_x, int stipple_y);
GLint glamor_compile_glsl_prog(GLenum type, const char *source);
void glamor_link_glsl_prog(ScreenPtr screen, GLint prog,
const char *format, ...) _X_ATTRIBUTE_PRINTF(3,4);
@ -651,7 +652,7 @@ int glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv);
void glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *, int, int, int, int);
/* nc means no check. caller must ensure this pixmap has valid fbo.
* usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly.
* usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly.
* */
void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv);
@ -665,17 +666,8 @@ Bool glamor_set_alu(ScreenPtr screen, unsigned char alu);
Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
/* glamor_fill.c */
Bool glamor_fill(DrawablePtr drawable,
GCPtr gc, int x, int y, int width, int height, Bool fallback);
Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
unsigned long fg_pixel);
Bool glamor_solid_boxes(PixmapPtr pixmap,
BoxPtr box, int nbox, unsigned long fg_pixel);
void glamor_init_solid_shader(ScreenPtr screen);
void glamor_fini_solid_shader(ScreenPtr screen);
void
glamor_track_stipple(GCPtr gc);
/* glamor_glyphs.c */
Bool glamor_realize_glyph_caches(ScreenPtr screen);
@ -687,10 +679,6 @@ void glamor_glyphs(CARD8 op,
INT16 xSrc,
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs);
/* glamor_polylines.c */
void glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
DDXPointPtr points);
/* glamor_render.c */
Bool glamor_composite_clipped_region(CARD8 op,
PicturePtr source,
@ -756,14 +744,6 @@ void glamor_trapezoids(CARD8 op,
PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
int ntrap, xTrapezoid *traps);
/* glamor_tile.c */
Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
int tile_x, int tile_y);
void glamor_init_tile_shader(ScreenPtr screen);
void glamor_fini_tile_shader(ScreenPtr screen);
/* glamor_gradient.c */
void glamor_init_gradient_shader(ScreenPtr screen);
void glamor_fini_gradient_shader(ScreenPtr screen);
@ -801,31 +781,6 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset);
void
glamor_put_vbo_space(ScreenPtr screen);
/**
* Download a pixmap's texture to cpu memory. If success,
* One copy of current pixmap's texture will be put into
* the pixmap->devPrivate.ptr. Will use pbo to map to
* the pointer if possible.
* The pixmap must be a gl texture pixmap. gl_fbo must be GLAMOR_FBO_NORMAL and
* gl_tex must be 1. Used by glamor_prepare_access.
*
*/
Bool glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access);
void *glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w,
int h, int stride, void *bits, int pbo,
glamor_access_t access);
/**
* Restore a pixmap's data which is downloaded by
* glamor_download_pixmap_to_cpu to its original
* gl texture. Used by glamor_finish_access.
*
* The pixmap must originally be a texture -- gl_fbo must be
* GLAMOR_FBO_NORMAL.
**/
void glamor_restore_pixmap_to_texture(PixmapPtr pixmap);
/**
* According to the flag,
* if the flag is GLAMOR_CREATE_FBO_NO_FBO then just ensure
@ -846,11 +801,6 @@ Bool glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
int h, int stride, void *bits,
int pbo);
PixmapPtr glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y,
int w, int h, glamor_access_t access);
void glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y,
int w, int h, glamor_access_t access);
glamor_pixmap_clipped_regions *
glamor_compute_clipped_regions(glamor_pixmap_private *priv,
RegionPtr region, int *clipped_nbox,
@ -909,20 +859,10 @@ Bool glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
GLenum type, int no_alpha, int revert,
int swap_rb, void *bits);
/**
* Destroy all the resources allocated on the uploading
* phase, includs the tex and fbo.
**/
void glamor_destroy_upload_pixmap(PixmapPtr pixmap);
int glamor_create_picture(PicturePtr picture);
void glamor_set_window_pixmap(WindowPtr pWindow, PixmapPtr pPixmap);
Bool glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access);
void glamor_finish_access_picture(PicturePtr picture);
void glamor_destroy_picture(PicturePtr picture);
/* fixup a fbo to the exact size as the pixmap. */
@ -935,11 +875,6 @@ void glamor_picture_format_fixup(PicturePtr picture,
void glamor_add_traps(PicturePtr pPicture,
INT16 x_off, INT16 y_off, int ntrap, xTrap *traps);
RegionPtr glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h,
int dstx, int dsty,
unsigned long bitPlane);
/* glamor_text.c */
int glamor_poly_text8(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count, char *chars);
@ -981,6 +916,48 @@ void
glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d);
/* glamor_dash.c */
Bool
glamor_poly_lines_dash_gl(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points);
Bool
glamor_poly_segment_dash_gl(DrawablePtr drawable, GCPtr gc,
int nseg, xSegment *segs);
/* glamor_lines.c */
void
glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points);
/* glamor_segs.c */
void
glamor_poly_segment(DrawablePtr drawable, GCPtr gc,
int nseg, xSegment *segs);
/* glamor_copy.c */
void
glamor_copy(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure);
RegionPtr
glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int width, int height, int dstx, int dsty);
RegionPtr
glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int width, int height, int dstx, int dsty,
unsigned long bitplane);
/* glamor_glyphblt.c */
void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
@ -996,17 +973,21 @@ void glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
void glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
DDXPointPtr ppt);
void glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
xSegment *pSeg);
void glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
DDXPointPtr ppt);
void glamor_composite_rectangles(CARD8 op,
PicturePtr dst,
xRenderColor *color,
int num_rects, xRectangle *rects);
/* glamor_util.c */
void
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned long fg_pixel);
void
glamor_solid_boxes(PixmapPtr pixmap,
BoxPtr box, int nbox, unsigned long fg_pixel);
/* glamor_xv */
typedef struct {
uint32_t transform_index;
@ -1028,15 +1009,41 @@ typedef struct {
int src_pix_w, src_pix_h;
} glamor_port_private;
void glamor_init_xv_shader(ScreenPtr screen);
void glamor_fini_xv_shader(ScreenPtr screen);
extern XvAttributeRec glamor_xv_attributes[];
extern int glamor_xv_num_attributes;
extern XvImageRec glamor_xv_images[];
extern int glamor_xv_num_images;
void glamor_xv_init_port(glamor_port_private *port_priv);
void glamor_xv_stop_video(glamor_port_private *port_priv);
int glamor_xv_set_port_attribute(glamor_port_private *port_priv,
Atom attribute, INT32 value);
int glamor_xv_get_port_attribute(glamor_port_private *port_priv,
Atom attribute, INT32 *value);
int glamor_xv_query_image_attributes(int id,
unsigned short *w, unsigned short *h,
int *pitches, int *offsets);
int glamor_xv_put_image(glamor_port_private *port_priv,
DrawablePtr pDrawable,
short src_x, short src_y,
short drw_x, short drw_y,
short src_w, short src_h,
short drw_w, short drw_h,
int id,
unsigned char *buf,
short width,
short height,
Bool sync,
RegionPtr clipBoxes);
void glamor_xv_core_init(ScreenPtr screen);
void glamor_xv_render(glamor_port_private *port_priv);
#include"glamor_utils.h"
/* Dynamic pixmap upload to texture if needed.
/* Dynamic pixmap upload to texture if needed.
* Sometimes, the target is a gl texture pixmap/picture,
* but the source or mask is in cpu memory. In that case,
* upload the source/mask to gl texture and then avoid
* upload the source/mask to gl texture and then avoid
* fallback the whole process to cpu. Most of the time,
* this will increase performance obviously. */

View File

@ -51,42 +51,51 @@ static const glamor_facet glamor_fill_tile = {
.use = use_tile,
};
#if 0
static Bool
use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog)
use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
{
return glamor_set_stippled(pixmap, gc, prog->fg_uniform, prog->fill_offset_uniform, prog->fill_size_uniform);
return glamor_set_stippled(pixmap, gc, prog->fg_uniform,
prog->fill_offset_uniform,
prog->fill_size_uniform);
}
static const glamor_facet glamor_fill_stipple = {
.name = "stipple",
.version = 130,
.vs_exec = " fill_pos = fill_offset + primitive.xy + pos;\n";
.fs_exec = (" if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
.vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n",
.fs_exec = (" float a = texture2D(sampler, fill_pos).w;\n"
" if (a == 0.0)\n"
" discard;\n"
" gl_FragColor = fg;\n")
.locations = glamor_program_location_fg | glamor_program_location_fill
" gl_FragColor = fg;\n"),
.locations = glamor_program_location_fg | glamor_program_location_fill,
.use = use_stipple,
};
static Bool
use_opaque_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
{
if (!use_stipple(pixmap, gc, prog, arg))
return FALSE;
glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
return TRUE;
}
static const glamor_facet glamor_fill_opaque_stipple = {
.name = "opaque_stipple",
.version = 130,
.vs_exec = " fill_pos = fill_offset + primitive.xy + pos;\n";
.fs_exec = (" if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
.vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n",
.fs_exec = (" float a = texture2D(sampler, fill_pos).w;\n"
" if (a == 0.0)\n"
" gl_FragColor = bg;\n"
" else\n"
" gl_FragColor = fg;\n"),
.locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill
.locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill,
.use = use_opaque_stipple
};
#endif
static const glamor_facet *glamor_facet_fill[4] = {
&glamor_fill_solid,
&glamor_fill_tile,
NULL,
NULL,
&glamor_fill_stipple,
&glamor_fill_opaque_stipple,
};
typedef struct {
@ -117,6 +126,16 @@ static glamor_location_var location_vars[] = {
.location = glamor_program_location_font,
.fs_vars = "uniform usampler2D font;\n",
},
{
.location = glamor_program_location_bitplane,
.fs_vars = ("uniform uvec4 bitplane;\n"
"uniform vec4 bitmul;\n"),
},
{
.location = glamor_program_location_dash,
.vs_vars = "uniform float dash_length;\n",
.fs_vars = "uniform sampler2D dash;\n",
},
};
#define NUM_LOCATION_VARS (sizeof location_vars / sizeof location_vars[0])
@ -196,6 +215,8 @@ static const glamor_facet facet_null_fill = {
.name = ""
};
#define DBG 0
static GLint
glamor_get_uniform(glamor_program *prog,
glamor_program_location location,
@ -281,7 +302,6 @@ glamor_build_program(ScreenPtr screen,
if (!vs_prog_string || !fs_prog_string)
goto fail;
#define DBG 0
#if DBG
ErrorF("\nPrograms for %s %s\nVertex shader:\n\n%s\n\nFragment Shader:\n\n%s",
prim->name, fill->name, vs_prog_string, fs_prog_string);
@ -318,6 +338,10 @@ glamor_build_program(ScreenPtr screen,
prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_offset");
prog->fill_size_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_size");
prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font");
prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane");
prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul");
prog->dash_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash");
prog->dash_length_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash_length");
if (glGetError() != GL_NO_ERROR)
goto fail;

View File

@ -29,6 +29,8 @@ typedef enum {
glamor_program_location_bg = 2,
glamor_program_location_fill = 4,
glamor_program_location_font = 8,
glamor_program_location_bitplane = 16,
glamor_program_location_dash = 32,
} glamor_program_location;
typedef enum {
@ -61,6 +63,10 @@ struct _glamor_program {
GLint fill_size_uniform;
GLint fill_offset_uniform;
GLint font_uniform;
GLint bitplane_uniform;
GLint bitmul_uniform;
GLint dash_uniform;
GLint dash_length_uniform;
glamor_program_location locations;
glamor_program_flag flags;
glamor_use prim_use;

View File

@ -651,11 +651,12 @@ glamor_composite_with_copy(CARD8 op,
if (region->extents.y2 + y_source - y_dest > source->pDrawable->height)
goto cleanup_region;
}
ret = glamor_copy_n_to_n_nf(source->pDrawable,
dest->pDrawable, NULL,
RegionRects(region), RegionNumRects(region),
x_source - x_dest, y_source - y_dest,
FALSE, FALSE, 0, NULL);
glamor_copy(source->pDrawable,
dest->pDrawable, NULL,
RegionRects(region), RegionNumRects(region),
x_source - x_dest, y_source - y_dest,
FALSE, FALSE, 0, NULL);
ret = TRUE;
cleanup_region:
return ret;
}
@ -792,30 +793,29 @@ glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv,
float *matrix,
float xscale, float yscale,
int x1, int y1, int x2, int y2,
int yInverted, float *texcoords,
float *texcoords,
int stride)
{
if (!matrix && repeat_type == RepeatNone)
glamor_set_normalize_tcoords_ext(priv, xscale, yscale,
x1, y1,
x2, y2, yInverted, texcoords, stride);
x2, y2, texcoords, stride);
else if (matrix && repeat_type == RepeatNone)
glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale,
yscale, x1, y1,
x2, y2,
yInverted,
texcoords, stride);
else if (!matrix && repeat_type != RepeatNone)
glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type,
xscale, yscale,
x1, y1,
x2, y2,
yInverted, texcoords, stride);
texcoords, stride);
else if (matrix && repeat_type != RepeatNone)
glamor_set_repeat_transformed_normalize_tcoords_ext(priv, repeat_type,
matrix, xscale,
yscale, x1, y1, x2,
y2, yInverted,
y2,
texcoords, stride);
}
@ -1265,7 +1265,7 @@ glamor_composite_with_shader(CARD8 op,
glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale,
dst_yscale, x_dest, y_dest,
x_dest + width, y_dest + height,
glamor_priv->yInverted, vertices,
vertices,
vb_stride);
vertices += 2;
if (key.source != SHADER_SOURCE_SOLID) {
@ -1275,7 +1275,6 @@ glamor_composite_with_shader(CARD8 op,
src_yscale, x_source,
y_source, x_source + width,
y_source + height,
glamor_priv->yInverted,
vertices, vb_stride);
vertices += 2;
}
@ -1287,7 +1286,6 @@ glamor_composite_with_shader(CARD8 op,
mask_yscale, x_mask,
y_mask, x_mask + width,
y_mask + height,
glamor_priv->yInverted,
vertices, vb_stride);
vertices += 2;
}
@ -1315,8 +1313,6 @@ glamor_composite_with_shader(CARD8 op,
glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
glDisable(GL_BLEND);
DEBUGF("finish rendering.\n");
glamor_priv->state = RENDER_STATE;
glamor_priv->render_idle_cnt = 0;
if (saved_source_format)
source->format = saved_source_format;
@ -1586,15 +1582,6 @@ _glamor_composite(CARD8 op,
RegionRec region;
BoxPtr extent;
int nbox, ok = FALSE;
PixmapPtr sub_dest_pixmap = NULL;
PixmapPtr sub_source_pixmap = NULL;
PixmapPtr sub_mask_pixmap = NULL;
int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y;
int source_x_off, source_y_off, saved_source_x, saved_source_y;
int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y;
DrawablePtr saved_dest_drawable;
DrawablePtr saved_source_drawable;
DrawablePtr saved_mask_drawable;
int force_clip = 0;
dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
@ -1737,34 +1724,13 @@ _glamor_composite(CARD8 op,
dest->pDrawable->width, dest->pDrawable->height,
glamor_get_picture_location(dest));
#define GET_SUB_PICTURE(p, access) do { \
glamor_get_drawable_deltas(p->pDrawable, p ##_pixmap, \
& p ##_x_off, & p ##_y_off); \
sub_ ##p ##_pixmap = glamor_get_sub_pixmap(p ##_pixmap, \
x_ ##p + p ##_x_off + p->pDrawable->x, \
y_ ##p + p ##_y_off + p->pDrawable->y, \
width, height, access); \
if (sub_ ##p ##_pixmap != NULL) { \
saved_ ##p ##_drawable = p->pDrawable; \
saved_ ##p ##_x = x_ ##p; \
saved_ ##p ##_y = y_ ##p; \
if (p->pCompositeClip) \
pixman_region_translate (p->pCompositeClip, \
-p->pDrawable->x - x_ ##p, \
-p->pDrawable->y - y_ ##p); \
p->pDrawable = &sub_ ##p ##_pixmap->drawable; \
x_ ##p = 0; \
y_ ##p = 0; \
} } while(0)
GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
if (source->pDrawable && !source->transform)
GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
if (mask && mask->pDrawable && !mask->transform)
GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW) &&
glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO) &&
glamor_prepare_access_picture(mask, GLAMOR_ACCESS_RO)) {
if (glamor_prepare_access_picture_box(dest, GLAMOR_ACCESS_RW,
x_dest, y_dest, width, height) &&
glamor_prepare_access_picture_box(source, GLAMOR_ACCESS_RO,
x_source, y_source, width, height) &&
glamor_prepare_access_picture_box(mask, GLAMOR_ACCESS_RO,
x_mask, y_mask, width, height))
{
fbComposite(op,
source, mask, dest,
x_source, y_source,
@ -1774,25 +1740,6 @@ _glamor_composite(CARD8 op,
glamor_finish_access_picture(source);
glamor_finish_access_picture(dest);
#define PUT_SUB_PICTURE(p, access) do { \
if (sub_ ##p ##_pixmap != NULL) { \
x_ ##p = saved_ ##p ##_x; \
y_ ##p = saved_ ##p ##_y; \
p->pDrawable = saved_ ##p ##_drawable; \
if (p->pCompositeClip) \
pixman_region_translate (p->pCompositeClip, \
p->pDrawable->x + x_ ##p, \
p->pDrawable->y + y_ ##p); \
glamor_put_sub_pixmap(sub_ ##p ##_pixmap, p ##_pixmap, \
x_ ##p + p ##_x_off + p->pDrawable->x, \
y_ ##p + p ##_y_off + p->pDrawable->y, \
width, height, access); \
}} while(0)
if (mask && mask->pDrawable)
PUT_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
if (source->pDrawable)
PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
done:
return ret;
}

188
glamor/glamor_segs.c Normal file
View File

@ -0,0 +1,188 @@
/*
* Copyright © 2014 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
#include "glamor_program.h"
#include "glamor_transform.h"
#include "glamor_prepare.h"
static const glamor_facet glamor_facet_poly_segment = {
.name = "poly_segment",
.vs_vars = "attribute vec2 primitive;\n",
.vs_exec = (" vec2 pos = vec2(0.0,0.0);\n"
GLAMOR_POS(gl_Position, primitive.xy)),
};
static Bool
glamor_poly_segment_solid_gl(DrawablePtr drawable, GCPtr gc,
int nseg, xSegment *segs)
{
ScreenPtr screen = drawable->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv;
glamor_program *prog;
int off_x, off_y;
xSegment *v;
char *vbo_offset;
int box_x, box_y;
int add_last;
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
goto bail;
add_last = 0;
if (gc->capStyle != CapNotLast)
add_last = 1;
glamor_make_current(glamor_priv);
prog = glamor_use_program_fill(pixmap, gc,
&glamor_priv->poly_segment_program,
&glamor_facet_poly_segment);
if (!prog)
goto bail_ctx;
/* Set up the vertex buffers for the points */
v = glamor_get_vbo_space(drawable->pScreen,
(nseg << add_last) * sizeof (xSegment),
&vbo_offset);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
sizeof(DDXPointRec), vbo_offset);
if (add_last) {
int i, j;
for (i = 0, j=0; i < nseg; i++) {
v[j++] = segs[i];
v[j].x1 = segs[i].x2;
v[j].y1 = segs[i].y2;
v[j].x2 = segs[i].x2+1;
v[j].y2 = segs[i].y2;
j++;
}
} else
memcpy(v, segs, nseg * sizeof (xSegment));
glamor_put_vbo_space(screen);
glEnable(GL_SCISSOR_TEST);
glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
int nbox = RegionNumRects(gc->pCompositeClip);
BoxPtr box = RegionRects(gc->pCompositeClip);
glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE,
prog->matrix_uniform, &off_x, &off_y);
while (nbox--) {
glScissor(box->x1 + off_x,
box->y1 + off_y,
box->x2 - box->x1,
box->y2 - box->y1);
box++;
glDrawArrays(GL_LINES, 0, nseg << (1 + add_last));
}
}
glDisable(GL_SCISSOR_TEST);
glDisable(GL_COLOR_LOGIC_OP);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
return TRUE;
bail_ctx:
glDisable(GL_COLOR_LOGIC_OP);
bail:
return FALSE;
}
static Bool
glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc,
int nseg, xSegment *segs)
{
if (gc->lineWidth != 0)
return FALSE;
switch (gc->lineStyle) {
case LineSolid:
return glamor_poly_segment_solid_gl(drawable, gc, nseg, segs);
case LineOnOffDash:
return glamor_poly_segment_dash_gl(drawable, gc, nseg, segs);
case LineDoubleDash:
if (gc->fillStyle == FillTiled)
return glamor_poly_segment_solid_gl(drawable, gc, nseg, segs);
else
return glamor_poly_segment_dash_gl(drawable, gc, nseg, segs);
default:
return FALSE;
}
}
static void
glamor_poly_segment_bail(DrawablePtr drawable, GCPtr gc,
int nseg, xSegment *segs)
{
glamor_fallback("to %p (%c)\n", drawable,
glamor_get_drawable_location(drawable));
if (gc->lineWidth == 0) {
if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
glamor_prepare_access_gc(gc)) {
fbPolySegment(drawable, gc, nseg, segs);
}
glamor_finish_access_gc(gc);
glamor_finish_access(drawable);
} else
miPolySegment(drawable, gc, nseg, segs);
}
void
glamor_poly_segment(DrawablePtr drawable, GCPtr gc,
int nseg, xSegment *segs)
{
if (glamor_poly_segment_gl(drawable, gc, nseg, segs))
return;
glamor_poly_segment_bail(drawable, gc, nseg, segs);
}
Bool
glamor_poly_segment_nf(DrawablePtr drawable, GCPtr gc,
int nseg, xSegment *segs)
{
if (glamor_poly_segment_gl(drawable, gc, nseg, segs))
return TRUE;
if (glamor_ddx_fallback_check_pixmap(drawable) &&
glamor_ddx_fallback_check_gc(gc))
{
return FALSE;
}
glamor_poly_segment_bail(drawable, gc, nseg, segs);
return TRUE;
}

View File

@ -326,9 +326,6 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src,
glamor_make_current(glamor_priv);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glamor_pixmap_loop(pixmap_priv, box_x, box_y) {

View File

@ -293,9 +293,6 @@ glamor_poly_text(DrawablePtr drawable, GCPtr gc,
glDisable(GL_COLOR_LOGIC_OP);
glamor_priv->state = RENDER_STATE;
glamor_priv->render_idle_cnt = 0;
*final_pos = x;
return TRUE;
@ -493,9 +490,6 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc,
(void) glamor_text(drawable, gc, glamor_font, prog,
x, y, count, chars, charinfo, sixteen);
glamor_priv->state = RENDER_STATE;
glamor_priv->render_idle_cnt = 0;
return TRUE;
bail:

View File

@ -1,293 +0,0 @@
/*
* Copyright © 2009 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
* Zhigang Gong <zhigang.gong@linux.intel.com>
*
*/
#include "glamor_priv.h"
/** @file glamor_tile.c
*
* Implements the basic fill-with-a-tile support used by multiple GC ops.
*/
void
glamor_init_tile_shader(ScreenPtr screen)
{
glamor_screen_private *glamor_priv;
const char *tile_vs =
"attribute vec4 v_position;\n"
"attribute vec4 v_texcoord0;\n"
"varying vec2 tile_texture;\n"
"void main()\n"
"{\n"
" gl_Position = v_position;\n"
" tile_texture = v_texcoord0.xy;\n"
"}\n";
const char *tile_fs =
GLAMOR_DEFAULT_PRECISION
"varying vec2 tile_texture;\n"
"uniform sampler2D sampler;\n"
"uniform vec2 wh;"
"void main()\n"
"{\n"
" vec2 rel_tex;"
" rel_tex = tile_texture * wh; \n"
" rel_tex = floor(rel_tex) + (fract(rel_tex) / wh); \n"
" gl_FragColor = texture2D(sampler, rel_tex);\n"
"}\n";
GLint fs_prog, vs_prog;
GLint sampler_uniform_location;
glamor_priv = glamor_get_screen_private(screen);
glamor_make_current(glamor_priv);
glamor_priv->tile_prog = glCreateProgram();
vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, tile_vs);
fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, tile_fs);
glAttachShader(glamor_priv->tile_prog, vs_prog);
glAttachShader(glamor_priv->tile_prog, fs_prog);
glBindAttribLocation(glamor_priv->tile_prog,
GLAMOR_VERTEX_POS, "v_position");
glBindAttribLocation(glamor_priv->tile_prog,
GLAMOR_VERTEX_SOURCE, "v_texcoord0");
glamor_link_glsl_prog(screen, glamor_priv->tile_prog, "tile");
sampler_uniform_location =
glGetUniformLocation(glamor_priv->tile_prog, "sampler");
glUseProgram(glamor_priv->tile_prog);
glUniform1i(sampler_uniform_location, 0);
glamor_priv->tile_wh =
glGetUniformLocation(glamor_priv->tile_prog, "wh");
}
void
glamor_fini_tile_shader(ScreenPtr screen)
{
glamor_screen_private *glamor_priv;
glamor_priv = glamor_get_screen_private(screen);
glamor_make_current(glamor_priv);
glDeleteProgram(glamor_priv->tile_prog);
}
static void
_glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
int x, int y, int width, int height, int tile_x, int tile_y)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
int tile_x1 = tile_x;
int tile_x2 = tile_x + width;
int tile_y1 = tile_y;
int tile_y2 = tile_y + height;
float vertices[8];
float source_texcoords[8];
GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale;
glamor_pixmap_private *src_pixmap_priv;
glamor_pixmap_private *dst_pixmap_priv;
float wh[4];
src_pixmap_priv = glamor_get_pixmap_private(tile);
dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale);
glamor_make_current(glamor_priv);
glUseProgram(glamor_priv->tile_prog);
glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv);
glUniform2fv(glamor_priv->tile_wh, 1, wh);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glamor_set_repeat_normalize_tcoords
(src_pixmap_priv, RepeatNormal,
src_xscale, src_yscale,
tile_x1, tile_y1,
tile_x2, tile_y2, glamor_priv->yInverted, source_texcoords);
glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
2 * sizeof(float), source_texcoords);
glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale,
x1, y1,
x2, y2, glamor_priv->yInverted, vertices);
glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
2 * sizeof(float), vertices);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
glamor_priv->state = RENDER_STATE;
glamor_priv->render_idle_cnt = 0;
}
Bool
glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
int x, int y, int width, int height,
unsigned char alu, unsigned long planemask, int tile_x, int tile_y)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
glamor_pixmap_private *dst_pixmap_priv;
glamor_pixmap_private *src_pixmap_priv;
dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
src_pixmap_priv = glamor_get_pixmap_private(tile);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv))
return FALSE;
if (glamor_priv->tile_prog == 0) {
glamor_fallback("Tiling unsupported\n");
goto fail;
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
/* XXX dynamic uploading candidate. */
glamor_fallback("Non-texture tile pixmap\n");
goto fail;
}
if (!glamor_set_planemask(pixmap, planemask)) {
glamor_fallback("unsupported planemask %lx\n", planemask);
goto fail;
}
glamor_make_current(glamor_priv);
if (!glamor_set_alu(screen, alu)) {
glamor_fallback("unsupported alu %x\n", alu);
goto fail;
}
if (dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
|| src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
glamor_pixmap_clipped_regions *clipped_dst_regions;
int n_dst_region, i, j, k;
BoxRec box;
RegionRec region;
box.x1 = x;
box.y1 = y;
box.x2 = x + width;
box.y2 = y + height;
RegionInitBoxes(&region, &box, 1);
clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
&region,
&n_dst_region, 0,
0, 0);
for (i = 0; i < n_dst_region; i++) {
int n_src_region;
glamor_pixmap_clipped_regions *clipped_src_regions;
BoxPtr current_boxes;
int n_current_boxes;
SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv,
clipped_dst_regions[i].block_idx);
if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
RegionTranslate(clipped_dst_regions[i].region,
tile_x - x, tile_y - y);
DEBUGF("tiled a large src pixmap. %dx%d \n",
tile->drawable.width, tile->drawable.height);
clipped_src_regions =
glamor_compute_clipped_regions(src_pixmap_priv,
clipped_dst_regions[i].
region, &n_src_region, 1, 0,
0);
DEBUGF("got %d src regions %d \n", n_src_region);
for (j = 0; j < n_src_region; j++) {
SET_PIXMAP_FBO_CURRENT(src_pixmap_priv,
clipped_src_regions[j].block_idx);
RegionTranslate(clipped_src_regions[j].region,
x - tile_x, y - tile_y);
current_boxes = RegionRects(clipped_src_regions[j].region);
n_current_boxes =
RegionNumRects(clipped_src_regions[j].region);
for (k = 0; k < n_current_boxes; k++) {
DEBUGF
("Tile on %d %d %d %d dst block id %d tile block id %d tilex %d tiley %d\n",
current_boxes[k].x1, current_boxes[k].y1,
current_boxes[k].x2 - current_boxes[k].x1,
current_boxes[k].y2 - current_boxes[k].y1,
clipped_dst_regions[i].block_idx,
clipped_src_regions[j].block_idx,
(tile_x + (current_boxes[k].x1 - x)),
tile_y + (current_boxes[k].y1 - y));
_glamor_tile(pixmap, tile,
current_boxes[k].x1, current_boxes[k].y1,
current_boxes[k].x2 - current_boxes[k].x1,
current_boxes[k].y2 - current_boxes[k].y1,
(tile_x + (current_boxes[k].x1 - x)),
(tile_y + (current_boxes[k].y1 - y)));
}
RegionDestroy(clipped_src_regions[j].region);
}
free(clipped_src_regions);
}
else {
current_boxes = RegionRects(clipped_dst_regions[i].region);
n_current_boxes = RegionNumRects(clipped_dst_regions[i].region);
for (k = 0; k < n_current_boxes; k++) {
_glamor_tile(pixmap, tile,
current_boxes[k].x1, current_boxes[k].y1,
current_boxes[k].x2 - current_boxes[k].x1,
current_boxes[k].y2 - current_boxes[k].y1,
(tile_x + (current_boxes[k].x1 - x)),
(tile_y + (current_boxes[k].y1 - y)));
}
}
RegionDestroy(clipped_dst_regions[i].region);
}
free(clipped_dst_regions);
RegionUninit(&region);
}
else
_glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);
glamor_set_alu(screen, GXcopy);
return TRUE;
fail:
return FALSE;
}

View File

@ -72,9 +72,6 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
glamor_make_current(glamor_priv);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
@ -90,27 +87,14 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
while (nbox--) {
/* compute drawable coordinates */
int x1 = boxes->x1 + dx_dst;
int x2 = boxes->x2 + dx_dst;
int y1 = boxes->y1 + dy_dst;
int y2 = boxes->y2 + dy_dst;
int x1 = MAX(boxes->x1 + dx_dst, box->x1);
int x2 = MIN(boxes->x2 + dx_dst, box->x2);
int y1 = MAX(boxes->y1 + dy_dst, box->y1);
int y2 = MIN(boxes->y2 + dy_dst, box->y2);
boxes++;
if (x1 < box->x1)
x1 = box->x1;
if (box->x2 < x2)
x2 = box->x2;
if (x2 <= x1)
continue;
if (y1 < box->y1)
y1 = box->y1;
if (box->y2 < y2)
y2 = box->y2;
if (y2 <= y1)
if (x2 <= x1 || y2 <= y1)
continue;
glPixelStorei(GL_UNPACK_SKIP_ROWS, y1 - dy_dst + dy_src);
@ -195,26 +179,14 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
while (nbox--) {
/* compute drawable coordinates */
int x1 = boxes->x1 + dx_src;
int x2 = boxes->x2 + dx_src;
int y1 = boxes->y1 + dy_src;
int y2 = boxes->y2 + dy_src;
int x1 = MAX(boxes->x1 + dx_src, box->x1);
int x2 = MIN(boxes->x2 + dx_src, box->x2);
int y1 = MAX(boxes->y1 + dy_src, box->y1);
int y2 = MIN(boxes->y2 + dy_src, box->y2);
boxes++;
if (x1 < box->x1)
x1 = box->x1;
if (box->x2 < x2)
x2 = box->x2;
if (y1 < box->y1)
y1 = box->y1;
if (box->y2 < y2)
y2 = box->y2;
if (x2 <= x1)
continue;
if (y2 <= y1)
if (x2 <= x1 || y2 <= y1)
continue;
glPixelStorei(GL_PACK_SKIP_PIXELS, x1 - dx_src + dx_dst);

View File

@ -198,6 +198,64 @@ glamor_set_tiled(PixmapPtr pixmap,
size_uniform);
}
static PixmapPtr
glamor_get_stipple_pixmap(GCPtr gc)
{
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
ScreenPtr screen = gc->pScreen;
PixmapPtr bitmap;
PixmapPtr pixmap;
GCPtr scratch_gc;
ChangeGCVal changes[2];
if (gc_priv->stipple)
return gc_priv->stipple;
bitmap = gc->stipple;
if (!bitmap)
goto bail;
pixmap = glamor_create_pixmap(screen,
bitmap->drawable.width,
bitmap->drawable.height,
8, GLAMOR_CREATE_NO_LARGE);
if (!pixmap)
goto bail;
scratch_gc = GetScratchGC(8, screen);
if (!scratch_gc)
goto bail_pixmap;
changes[0].val = 0xff;
changes[1].val = 0x00;
if (ChangeGC(NullClient, scratch_gc,
GCForeground|GCBackground, changes) != Success)
goto bail_gc;
ValidateGC(&pixmap->drawable, scratch_gc);
(*scratch_gc->ops->CopyPlane)(&bitmap->drawable,
&pixmap->drawable,
scratch_gc,
0, 0,
bitmap->drawable.width,
bitmap->drawable.height,
0, 0, 0x1);
FreeScratchGC(scratch_gc);
gc_priv->stipple = pixmap;
glamor_track_stipple(gc);
return pixmap;
bail_gc:
FreeScratchGC(scratch_gc);
bail_pixmap:
glamor_destroy_pixmap(pixmap);
bail:
return NULL;
}
Bool
glamor_set_stippled(PixmapPtr pixmap,
GCPtr gc,
@ -205,11 +263,19 @@ glamor_set_stippled(PixmapPtr pixmap,
GLint offset_uniform,
GLint size_uniform)
{
PixmapPtr stipple;
stipple = glamor_get_stipple_pixmap(gc);
if (!stipple)
return FALSE;
if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
return FALSE;
if (!glamor_set_texture(pixmap, gc->stipple, gc->patOrg.x, gc->patOrg.y, offset_uniform, size_uniform))
return FALSE;
return TRUE;
return glamor_set_texture(pixmap,
stipple,
-gc->patOrg.x,
-gc->patOrg.y,
offset_uniform,
size_uniform);
}

View File

@ -908,7 +908,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
clipped_vtx_tmp[5] = clipped_vtx[(i + 2) * 2 + 1];
glamor_set_normalize_tri_vcoords(dst_xscale, dst_yscale,
clipped_vtx_tmp,
glamor_priv->yInverted,
vertices);
DEBUGF("vertices of triangle: (%f X %f), (%f X %f), "
"(%f X %f)\n", vertices[0], vertices[1],
@ -920,14 +919,12 @@ _glamor_trapezoids_with_shader(CARD8 op,
glamor_set_transformed_normalize_tri_tcoords
(source_pixmap_priv, src_matrix, src_xscale,
src_yscale, clipped_vtx_tmp,
glamor_priv->yInverted, source_texcoords);
source_texcoords);
}
else {
glamor_set_normalize_tri_tcoords(src_xscale,
src_yscale,
clipped_vtx_tmp,
glamor_priv->
yInverted,
source_texcoords);
}
@ -1392,12 +1389,8 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
}
/* First, clear all to zero */
if (!glamor_solid(pixmap, 0, 0, pixmap_priv->base.pixmap->drawable.width,
pixmap_priv->base.pixmap->drawable.height,
GXclear, 0xFFFFFFFF, 0)) {
DEBUGF("glamor_solid failed, fallback\n");
return FALSE;
}
glamor_solid(pixmap, 0, 0, pixmap_priv->base.pixmap->drawable.width,
pixmap_priv->base.pixmap->drawable.height, 0);
glamor_make_current(glamor_priv);
@ -1443,11 +1436,9 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
miTrapezoidBounds(1, ptrap, &one_trap_bound);
vertices += 2;
glamor_set_tcoords_ext((pixmap_priv->base.pixmap->drawable.width),
(pixmap_priv->base.pixmap->drawable.height),
(one_trap_bound.x1), (one_trap_bound.y1),
glamor_set_tcoords_ext((one_trap_bound.x1), (one_trap_bound.y1),
(one_trap_bound.x2), (one_trap_bound.y2),
glamor_priv->yInverted, vertices, stride);
vertices, stride);
DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f,"
"rightbottom: %f X %f, leftbottom : %f X %f\n", vertices[0],
vertices[1], vertices[1 * stride], vertices[1 * stride + 1],
@ -1467,8 +1458,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
one_trap_bound.y1,
one_trap_bound.x2,
one_trap_bound.y2,
glamor_priv->yInverted, vertices,
stride);
vertices, stride);
DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f,"
"rightbottom: %f X %f, leftbottom : %f X %f\n", vertices[0],
vertices[1], vertices[1 * stride], vertices[1 * stride + 1],

79
glamor/glamor_utils.c Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright © 2014 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
void
glamor_solid_boxes(PixmapPtr pixmap,
BoxPtr box, int nbox, unsigned long fg_pixel)
{
DrawablePtr drawable = &pixmap->drawable;
GCPtr gc;
xRectangle *rect;
int n;
rect = malloc(nbox * sizeof (xRectangle));
if (!rect)
return;
for (n = 0; n < nbox; n++) {
rect[n].x = box[n].x1;
rect[n].y = box[n].y1;
rect[n].width = box[n].x2 - box[n].x1;
rect[n].height = box[n].y2 - box[n].y1;
}
gc = GetScratchGC(drawable->depth, drawable->pScreen);
if (gc) {
ChangeGCVal vals[1];
vals[0].val = fg_pixel;
ChangeGC(NullClient, gc, GCForeground, vals);
ValidateGC(drawable, gc);
gc->ops->PolyFillRect(drawable, gc, nbox, rect);
FreeScratchGC(gc);
}
free(rect);
}
void
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned long fg_pixel)
{
DrawablePtr drawable = &pixmap->drawable;
GCPtr gc;
ChangeGCVal vals[1];
xRectangle rect;
vals[0].val = fg_pixel;
gc = GetScratchGC(drawable->depth, drawable->pScreen);
if (!gc)
return;
ChangeGC(NullClient, gc, GCForeground, vals);
ValidateGC(drawable, gc);
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
gc->ops->PolyFillRect(drawable, gc, 1, &rect);
FreeScratchGC(gc);
}

View File

@ -32,6 +32,8 @@
#ifndef __GLAMOR_UTILS_H__
#define __GLAMOR_UTILS_H__
#include "glamor_prepare.h"
#define v_from_x_coord_x(_xscale_, _x_) ( 2 * (_x_) * (_xscale_) - 1.0)
#define v_from_x_coord_y(_yscale_, _y_) (-2 * (_y_) * (_yscale_) + 1.0)
#define v_from_x_coord_y_inverted(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0)
@ -311,21 +313,17 @@
} while(0)
#define _glamor_set_normalize_tpoint(xscale, yscale, _tx_, _ty_, \
texcoord, yInverted) \
texcoord) \
do { \
(texcoord)[0] = t_from_x_coord_x(xscale, _tx_); \
if (_X_LIKELY(yInverted)) \
(texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_);\
else \
(texcoord)[1] = t_from_x_coord_y(yscale, _ty_); \
(texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_); \
DEBUGF("normalized point tx %f ty %f \n", (texcoord)[0], \
(texcoord)[1]); \
} while(0)
#define glamor_set_transformed_point(priv, matrix, xscale, \
yscale, texcoord, \
x, y, \
yInverted) \
x, y) \
do { \
float tx, ty; \
int fbo_x_off, fbo_y_off; \
@ -337,10 +335,7 @@
tx += fbo_x_off; \
ty += fbo_y_off; \
(texcoord)[0] = t_from_x_coord_x(xscale, tx); \
if (_X_LIKELY(yInverted)) \
(texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty); \
else \
(texcoord)[1] = t_from_x_coord_y(yscale, ty); \
(texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty); \
DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]); \
} while(0)
@ -349,18 +344,14 @@
xscale, \
yscale, \
vtx, \
yInverted, \
texcoords) \
do { \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords, (vtx)[0], (vtx)[1], \
yInverted); \
texcoords, (vtx)[0], (vtx)[1]); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords+2, (vtx)[2], (vtx)[3], \
yInverted); \
texcoords+2, (vtx)[2], (vtx)[3]); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords+4, (vtx)[4], (vtx)[5], \
yInverted); \
texcoords+4, (vtx)[4], (vtx)[5]); \
} while (0)
#define glamor_set_transformed_normalize_tcoords_ext( priv, \
@ -368,21 +359,17 @@
xscale, \
yscale, \
tx1, ty1, tx2, ty2, \
yInverted, texcoords, \
texcoords, \
stride) \
do { \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords, tx1, ty1, \
yInverted); \
texcoords, tx1, ty1); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords + 1 * stride, tx2, ty1, \
yInverted); \
texcoords + 1 * stride, tx2, ty1); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords + 2 * stride, tx2, ty2, \
yInverted); \
texcoords + 2 * stride, tx2, ty2); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords + 3 * stride, tx1, ty2, \
yInverted); \
texcoords + 3 * stride, tx1, ty2); \
} while (0)
#define glamor_set_transformed_normalize_tcoords( priv, \
@ -390,35 +377,31 @@
xscale, \
yscale, \
tx1, ty1, tx2, ty2, \
yInverted, texcoords) \
texcoords) \
do { \
glamor_set_transformed_normalize_tcoords_ext( priv, \
matrix, \
xscale, \
yscale, \
tx1, ty1, tx2, ty2, \
yInverted, texcoords, \
texcoords, \
2); \
} while (0)
#define glamor_set_normalize_tri_tcoords(xscale, \
yscale, \
vtx, \
yInverted, \
texcoords) \
do { \
_glamor_set_normalize_tpoint(xscale, yscale, \
(vtx)[0], (vtx)[1], \
texcoords, \
yInverted); \
texcoords); \
_glamor_set_normalize_tpoint(xscale, yscale, \
(vtx)[2], (vtx)[3], \
texcoords+2, \
yInverted); \
texcoords+2); \
_glamor_set_normalize_tpoint(xscale, yscale, \
(vtx)[4], (vtx)[5], \
texcoords+4, \
yInverted); \
texcoords+4); \
} while (0)
#define glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \
@ -428,14 +411,13 @@
yscale, \
_x1_, _y1_, \
_x2_, _y2_, \
yInverted, \
texcoords, \
stride) \
do { \
if (_X_LIKELY(priv->type != GLAMOR_TEXTURE_LARGE)) { \
glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, \
yscale, _x1_, _y1_, \
_x2_, _y2_, yInverted, \
_x2_, _y2_, \
texcoords, stride); \
} else { \
float tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4; \
@ -462,13 +444,13 @@
DEBUGF("repeat transformed %f %f %f %f %f %f %f %f\n", ttx1, tty1, \
ttx2, tty2, ttx3, tty3, ttx4, tty4); \
_glamor_set_normalize_tpoint(xscale, yscale, ttx1, tty1, \
texcoords, yInverted); \
texcoords); \
_glamor_set_normalize_tpoint(xscale, yscale, ttx2, tty2, \
texcoords + 1 * stride, yInverted); \
texcoords + 1 * stride); \
_glamor_set_normalize_tpoint(xscale, yscale, ttx3, tty3, \
texcoords + 2 * stride, yInverted); \
texcoords + 2 * stride); \
_glamor_set_normalize_tpoint(xscale, yscale, ttx4, tty4, \
texcoords + 3 * stride, yInverted); \
texcoords + 3 * stride); \
} \
} while (0)
@ -479,7 +461,6 @@
yscale, \
_x1_, _y1_, \
_x2_, _y2_, \
yInverted, \
texcoords) \
do { \
glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \
@ -489,14 +470,13 @@
yscale, \
_x1_, _y1_, \
_x2_, _y2_, \
yInverted, \
texcoords, \
2); \
} while (0)
#define _glamor_set_normalize_tcoords(xscale, yscale, tx1, \
ty1, tx2, ty2, \
yInverted, vertices, stride) \
vertices, stride) \
do { \
/* vertices may be write-only, so we use following \
* temporary variable. */ \
@ -505,21 +485,15 @@
(vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2); \
(vertices)[2 * stride] = _t2_; \
(vertices)[3 * stride] = _t0_; \
if (_X_LIKELY(yInverted)) { \
(vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1); \
(vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2);\
} \
else { \
(vertices)[1] = _t1_ = t_from_x_coord_y(yscale, ty1); \
(vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y(yscale, ty2);\
} \
(vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1); \
(vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2); \
(vertices)[1 * stride + 1] = _t1_; \
(vertices)[3 * stride + 1] = _t5_; \
} while(0)
#define glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \
x1, y1, x2, y2, \
yInverted, vertices, stride) \
vertices, stride) \
do { \
if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \
float tx1, tx2, ty1, ty2; \
@ -530,26 +504,26 @@
ty1 = y1 + fbo_y_off; \
ty2 = y2 + fbo_y_off; \
_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
tx2, ty2, yInverted, vertices, \
tx2, ty2, vertices, \
stride); \
} else \
_glamor_set_normalize_tcoords(xscale, yscale, x1, y1, \
x2, y2, yInverted, vertices, stride);\
x2, y2, vertices, stride); \
} while(0)
#define glamor_set_normalize_tcoords(priv, xscale, yscale, \
x1, y1, x2, y2, \
yInverted, vertices) \
vertices) \
do { \
glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \
x1, y1, x2, y2, \
yInverted, vertices, 2); \
vertices, 2); \
} while(0)
#define glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \
xscale, yscale, \
_x1_, _y1_, _x2_, _y2_, \
yInverted, vertices, stride)\
vertices, stride) \
do { \
if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \
float tx1, tx2, ty1, ty2; \
@ -564,130 +538,99 @@
_x1_, _y1_, _x2_, _y2_); \
} \
_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
tx2, ty2, yInverted, vertices, \
tx2, ty2, vertices, \
stride); \
} else \
_glamor_set_normalize_tcoords(xscale, yscale, _x1_, _y1_, \
_x2_, _y2_, yInverted, vertices, \
_x2_, _y2_, vertices, \
stride); \
} while(0)
#define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \
xscale, yscale, \
_x1_, _y1_, _x2_, _y2_, \
yInverted, vertices) \
vertices) \
do { \
glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \
xscale, yscale, \
_x1_, _y1_, _x2_, _y2_, \
yInverted, vertices, 2); \
vertices, 2); \
} while(0)
#define glamor_set_normalize_tcoords_tri_stripe(xscale, yscale, \
x1, y1, x2, y2, \
yInverted, vertices) \
vertices) \
do { \
(vertices)[0] = t_from_x_coord_x(xscale, x1); \
(vertices)[2] = t_from_x_coord_x(xscale, x2); \
(vertices)[6] = (vertices)[2]; \
(vertices)[4] = (vertices)[0]; \
if (_X_LIKELY(yInverted)) { \
(vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \
(vertices)[7] = t_from_x_coord_y_inverted(yscale, y2); \
} \
else { \
(vertices)[1] = t_from_x_coord_y(yscale, y1); \
(vertices)[7] = t_from_x_coord_y(yscale, y2); \
} \
(vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \
(vertices)[7] = t_from_x_coord_y_inverted(yscale, y2); \
(vertices)[3] = (vertices)[1]; \
(vertices)[5] = (vertices)[7]; \
} while(0)
#define glamor_set_tcoords(width, height, x1, y1, x2, y2, \
yInverted, vertices) \
#define glamor_set_tcoords(x1, y1, x2, y2, vertices) \
do { \
(vertices)[0] = (x1); \
(vertices)[2] = (x2); \
(vertices)[4] = (vertices)[2]; \
(vertices)[6] = (vertices)[0]; \
if (_X_LIKELY(yInverted)) { \
(vertices)[1] = (y1); \
(vertices)[5] = (y2); \
} \
else { \
(vertices)[1] = height - (y2); \
(vertices)[5] = height - (y1); \
} \
(vertices)[1] = (y1); \
(vertices)[5] = (y2); \
(vertices)[3] = (vertices)[1]; \
(vertices)[7] = (vertices)[5]; \
} while(0)
#define glamor_set_tcoords_ext(width, height, x1, y1, x2, y2, \
yInverted, vertices, stride) \
#define glamor_set_tcoords_ext(x1, y1, x2, y2, vertices, stride) \
do { \
(vertices)[0] = (x1); \
(vertices)[1*stride] = (x2); \
(vertices)[2*stride] = (vertices)[1*stride]; \
(vertices)[3*stride] = (vertices)[0]; \
if (_X_LIKELY(yInverted)) { \
(vertices)[1] = (y1); \
(vertices)[2*stride + 1] = (y2); \
} \
else { \
(vertices)[1] = height - (y2); \
(vertices)[2*stride + 1] = height - (y1); \
} \
(vertices)[1] = (y1); \
(vertices)[2*stride + 1] = (y2); \
(vertices)[1*stride + 1] = (vertices)[1]; \
(vertices)[3*stride + 1] = (vertices)[2*stride + 1]; \
} while(0)
#define glamor_set_normalize_one_vcoord(xscale, yscale, x, y, \
yInverted, vertices) \
vertices) \
do { \
(vertices)[0] = v_from_x_coord_x(xscale, x); \
if (_X_LIKELY(yInverted)) { \
(vertices)[1] = v_from_x_coord_y_inverted(yscale, y); \
} else { \
(vertices)[1] = v_from_x_coord_y(yscale, y); \
} \
(vertices)[1] = v_from_x_coord_y_inverted(yscale, y); \
} while(0)
#define glamor_set_normalize_tri_vcoords(xscale, yscale, vtx, \
yInverted, vertices) \
vertices) \
do { \
glamor_set_normalize_one_vcoord(xscale, yscale, \
(vtx)[0], (vtx)[1], \
yInverted, vertices); \
vertices); \
glamor_set_normalize_one_vcoord(xscale, yscale, \
(vtx)[2], (vtx)[3], \
yInverted, vertices+2); \
vertices+2); \
glamor_set_normalize_one_vcoord(xscale, yscale, \
(vtx)[4], (vtx)[5], \
yInverted, vertices+4); \
vertices+4); \
} while(0)
#define glamor_set_tcoords_tri_strip(width, height, x1, y1, x2, y2, \
yInverted, vertices) \
#define glamor_set_tcoords_tri_strip(x1, y1, x2, y2, vertices) \
do { \
(vertices)[0] = (x1); \
(vertices)[2] = (x2); \
(vertices)[6] = (vertices)[2]; \
(vertices)[4] = (vertices)[0]; \
if (_X_LIKELY(yInverted)) { \
(vertices)[1] = (y1); \
(vertices)[7] = (y2); \
} \
else { \
(vertices)[1] = height - (y2); \
(vertices)[7] = height - (y1); \
} \
(vertices)[1] = (y1); \
(vertices)[7] = (y2); \
(vertices)[3] = (vertices)[1]; \
(vertices)[5] = (vertices)[7]; \
} while(0)
#define glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \
x1, y1, x2, y2, \
yInverted, vertices, stride) \
vertices, stride) \
do { \
int fbo_x_off, fbo_y_off; \
/* vertices may be write-only, so we use following \
@ -699,29 +642,22 @@
x2 + fbo_x_off); \
(vertices)[2 * stride] = _t2_; \
(vertices)[3 * stride] = _t0_; \
if (_X_LIKELY(yInverted)) { \
(vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale, \
y1 + fbo_y_off); \
(vertices)[2 * stride + 1] = _t5_ = \
v_from_x_coord_y_inverted(yscale, \
y2 + fbo_y_off); \
} \
else { \
(vertices)[1] = _t1_ = v_from_x_coord_y(yscale, y1 + fbo_y_off); \
(vertices)[2 * stride + 1] = _t5_ = v_from_x_coord_y(yscale, \
y2 + fbo_y_off); \
} \
(vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale, \
y1 + fbo_y_off); \
(vertices)[2 * stride + 1] = _t5_ = \
v_from_x_coord_y_inverted(yscale, \
y2 + fbo_y_off); \
(vertices)[1 * stride + 1] = _t1_; \
(vertices)[3 * stride + 1] = _t5_; \
} while(0)
#define glamor_set_normalize_vcoords(priv, xscale, yscale, \
x1, y1, x2, y2, \
yInverted, vertices) \
vertices) \
do { \
glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \
x1, y1, x2, y2, \
yInverted, vertices, 2); \
vertices, 2); \
} while(0)
#define glamor_set_const_ext(params, nparam, vertices, nverts, stride) \
@ -736,44 +672,30 @@
#define glamor_set_normalize_vcoords_tri_strip(xscale, yscale, \
x1, y1, x2, y2, \
yInverted, vertices) \
vertices) \
do { \
(vertices)[0] = v_from_x_coord_x(xscale, x1); \
(vertices)[2] = v_from_x_coord_x(xscale, x2); \
(vertices)[6] = (vertices)[2]; \
(vertices)[4] = (vertices)[0]; \
if (_X_LIKELY(yInverted)) { \
(vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \
(vertices)[7] = v_from_x_coord_y_inverted(yscale, y2); \
} \
else { \
(vertices)[1] = v_from_x_coord_y(yscale, y1); \
(vertices)[7] = v_from_x_coord_y(yscale, y2); \
} \
(vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \
(vertices)[7] = v_from_x_coord_y_inverted(yscale, y2); \
(vertices)[3] = (vertices)[1]; \
(vertices)[5] = (vertices)[7]; \
} while(0)
#define glamor_set_normalize_pt(xscale, yscale, x, y, \
yInverted, pt) \
pt) \
do { \
(pt)[0] = t_from_x_coord_x(xscale, x); \
if (_X_LIKELY(yInverted)) { \
(pt)[1] = t_from_x_coord_y_inverted(yscale, y); \
} else { \
(pt)[1] = t_from_x_coord_y(yscale, y); \
} \
(pt)[1] = t_from_x_coord_y_inverted(yscale, y); \
} while(0)
#define glamor_set_circle_centre(width, height, x, y, \
yInverted, c) \
c) \
do { \
(c)[0] = (float)x; \
if (_X_LIKELY(yInverted)) { \
(c)[1] = (float)y; \
} else { \
(c)[1] = (float)height - (float)y; \
} \
(c)[1] = (float)y; \
} while(0)
inline static void

View File

@ -36,12 +36,10 @@
#include <dix-config.h>
#endif
#include "xf86xv.h"
#define GLAMOR_FOR_XORG
#include "glamor_priv.h"
#include <X11/extensions/Xv.h>
#include "fourcc.h"
#include "../hw/xfree86/common/fourcc.h"
/* Reference color space transform data */
typedef struct tagREF_TRANSFORM {
float RefLuma;
@ -90,7 +88,28 @@ static const char *xv_ps = GLAMOR_DEFAULT_PRECISION
"gl_FragColor = temp1;\n"
"}\n";
void
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
XvAttributeRec glamor_xv_attributes[] = {
{XvSettable | XvGettable, -1000, 1000, (char *)"XV_BRIGHTNESS"},
{XvSettable | XvGettable, -1000, 1000, (char *)"XV_CONTRAST"},
{XvSettable | XvGettable, -1000, 1000, (char *)"XV_SATURATION"},
{XvSettable | XvGettable, -1000, 1000, (char *)"XV_HUE"},
{XvSettable | XvGettable, 0, 1, (char *)"XV_COLORSPACE"},
{0, 0, 0, NULL}
};
int glamor_xv_num_attributes = ARRAY_SIZE(glamor_xv_attributes) - 1;
Atom glamorBrightness, glamorContrast, glamorSaturation, glamorHue,
glamorColorspace, glamorGamma;
XvImageRec glamor_xv_images[] = {
XVIMAGE_YV12,
XVIMAGE_I420,
};
int glamor_xv_num_images = ARRAY_SIZE(glamor_xv_images);
static void
glamor_init_xv_shader(ScreenPtr screen)
{
glamor_screen_private *glamor_priv;
@ -113,43 +132,12 @@ glamor_init_xv_shader(ScreenPtr screen)
}
#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
static Atom xvBrightness, xvContrast, xvSaturation, xvHue, xvColorspace,
xvGamma;
#define NUM_ATTRIBUTES 5
static XF86AttributeRec Attributes_glamor[NUM_ATTRIBUTES + 1] = {
{XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
{XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
{XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
{XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
{XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
{0, 0, 0, NULL}
};
#define NUM_FORMATS 3
static XF86VideoFormatRec Formats[NUM_FORMATS] = {
{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
};
#define NUM_IMAGES 2
static XF86ImageRec Images[NUM_IMAGES] = {
XVIMAGE_YV12,
XVIMAGE_I420,
};
static void
glamor_xv_stop_video(ScrnInfoPtr pScrn, void *data, Bool cleanup)
void
glamor_xv_stop_video(glamor_port_private *port_priv)
{
glamor_port_private *port_priv = (glamor_port_private *) data;
int i;
if (!cleanup)
return;
for (i = 0; i < 3; i++) {
if (port_priv->src_pix[i]) {
glamor_destroy_pixmap(port_priv->src_pix[i]);
@ -158,46 +146,42 @@ glamor_xv_stop_video(ScrnInfoPtr pScrn, void *data, Bool cleanup)
}
}
static int
glamor_xv_set_port_attribute(ScrnInfoPtr pScrn,
Atom attribute, INT32 value, void *data)
int
glamor_xv_set_port_attribute(glamor_port_private *port_priv,
Atom attribute, INT32 value)
{
glamor_port_private *port_priv = (glamor_port_private *) data;
if (attribute == xvBrightness)
if (attribute == glamorBrightness)
port_priv->brightness = ClipValue(value, -1000, 1000);
else if (attribute == xvHue)
else if (attribute == glamorHue)
port_priv->hue = ClipValue(value, -1000, 1000);
else if (attribute == xvContrast)
else if (attribute == glamorContrast)
port_priv->contrast = ClipValue(value, -1000, 1000);
else if (attribute == xvSaturation)
else if (attribute == glamorSaturation)
port_priv->saturation = ClipValue(value, -1000, 1000);
else if (attribute == xvGamma)
else if (attribute == glamorGamma)
port_priv->gamma = ClipValue(value, 100, 10000);
else if (attribute == xvColorspace)
else if (attribute == glamorColorspace)
port_priv->transform_index = ClipValue(value, 0, 1);
else
return BadMatch;
return Success;
}
static int
glamor_xv_get_port_attribute(ScrnInfoPtr pScrn,
Atom attribute, INT32 *value, void *data)
int
glamor_xv_get_port_attribute(glamor_port_private *port_priv,
Atom attribute, INT32 *value)
{
glamor_port_private *port_priv = (glamor_port_private *) data;
if (attribute == xvBrightness)
if (attribute == glamorBrightness)
*value = port_priv->brightness;
else if (attribute == xvHue)
else if (attribute == glamorHue)
*value = port_priv->hue;
else if (attribute == xvContrast)
else if (attribute == glamorContrast)
*value = port_priv->contrast;
else if (attribute == xvSaturation)
else if (attribute == glamorSaturation)
*value = port_priv->saturation;
else if (attribute == xvGamma)
else if (attribute == glamorGamma)
*value = port_priv->gamma;
else if (attribute == xvColorspace)
else if (attribute == glamorColorspace)
*value = port_priv->transform_index;
else
return BadMatch;
@ -205,20 +189,8 @@ glamor_xv_get_port_attribute(ScrnInfoPtr pScrn,
return Success;
}
static void
glamor_xv_query_best_size(ScrnInfoPtr pScrn,
Bool motion,
short vid_w, short vid_h,
short drw_w, short drw_h,
unsigned int *p_w, unsigned int *p_h, void *data)
{
*p_w = drw_w;
*p_h = drw_h;
}
static int
glamor_xv_query_image_attributes(ScrnInfoPtr pScrn,
int id,
int
glamor_xv_query_image_attributes(int id,
unsigned short *w, unsigned short *h,
int *pitches, int *offsets)
{
@ -258,8 +230,8 @@ static REF_TRANSFORM trans[2] = {
{1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0} /* BT.709 */
};
static void
glamor_display_textured_video(glamor_port_private *port_priv)
void
glamor_xv_render(glamor_port_private *port_priv)
{
ScreenPtr screen = port_priv->pPixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@ -282,6 +254,9 @@ glamor_display_textured_video(glamor_port_private *port_priv)
int ref = port_priv->transform_index;
GLint uloc, sampler_loc;
if (!glamor_priv->xv_prog)
glamor_init_xv_shader(screen);
cont = RTFContrast(port_priv->contrast);
bright = RTFBrightness(port_priv->brightness);
gamma = (float) port_priv->gamma / 1000.0;
@ -385,7 +360,7 @@ glamor_display_textured_video(glamor_port_private *port_priv)
dsty,
dstx + dstw,
dsty + dsth,
glamor_priv->yInverted, vertices);
vertices);
glamor_set_normalize_tcoords(src_pixmap_priv[0],
src_xscale[0],
@ -394,7 +369,7 @@ glamor_display_textured_video(glamor_port_private *port_priv)
srcy,
srcx + srcw,
srcy + srch,
glamor_priv->yInverted, texcoords);
texcoords);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
@ -405,8 +380,9 @@ glamor_display_textured_video(glamor_port_private *port_priv)
DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
}
static int
glamor_xv_put_image(ScrnInfoPtr pScrn,
int
glamor_xv_put_image(glamor_port_private *port_priv,
DrawablePtr pDrawable,
short src_x, short src_y,
short drw_x, short drw_y,
short src_w, short src_h,
@ -416,35 +392,15 @@ glamor_xv_put_image(ScrnInfoPtr pScrn,
short width,
short height,
Bool sync,
RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
RegionPtr clipBoxes)
{
ScreenPtr screen = pDrawable->pScreen;
glamor_port_private *port_priv = (glamor_port_private *) data;
INT32 x1, x2, y1, y2;
ScreenPtr pScreen = pDrawable->pScreen;
int srcPitch, srcPitch2;
BoxRec dstBox;
int top, nlines;
int s2offset, s3offset, tmp;
s2offset = s3offset = srcPitch2 = 0;
/* Clip */
x1 = src_x;
x2 = src_x + src_w;
y1 = src_y;
y2 = src_y + src_h;
dstBox.x1 = drw_x;
dstBox.x2 = drw_x + drw_w;
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
if (!xf86XVClipVideoHelper
(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height))
return Success;
if ((x1 >= x2) || (y1 >= y2))
return Success;
srcPitch = width;
srcPitch2 = width >> 1;
@ -457,11 +413,11 @@ glamor_xv_put_image(ScrnInfoPtr pScrn,
glamor_destroy_pixmap(port_priv->src_pix[i]);
port_priv->src_pix[0] =
glamor_create_pixmap(screen, width, height, 8, 0);
glamor_create_pixmap(pScreen, width, height, 8, 0);
port_priv->src_pix[1] =
glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 0);
port_priv->src_pix[2] =
glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 0);
port_priv->src_pix_w = width;
port_priv->src_pix_h = height;
@ -470,8 +426,8 @@ glamor_xv_put_image(ScrnInfoPtr pScrn,
return BadAlloc;
}
top = (y1 >> 16) & ~1;
nlines = ((y2 + 0xffff) >> 16) - top;
top = (src_y) & ~1;
nlines = (src_y + height) - top;
switch (id) {
case FOURCC_YV12:
@ -505,7 +461,7 @@ glamor_xv_put_image(ScrnInfoPtr pScrn,
}
if (pDrawable->type == DRAWABLE_WINDOW)
port_priv->pPixmap = (*screen->GetWindowPixmap) ((WindowPtr) pDrawable);
port_priv->pPixmap = pScreen->GetWindowPixmap((WindowPtr) pDrawable);
else
port_priv->pPixmap = (PixmapPtr) pDrawable;
@ -524,83 +480,30 @@ glamor_xv_put_image(ScrnInfoPtr pScrn,
port_priv->w = width;
port_priv->h = height;
port_priv->pDraw = pDrawable;
glamor_display_textured_video(port_priv);
glamor_xv_render(port_priv);
return Success;
}
static XF86VideoEncodingRec DummyEncodingGLAMOR[1] = {
{
0,
"XV_IMAGE",
8192, 8192,
{1, 1}
}
};
XF86VideoAdaptorPtr
glamor_xv_init(ScreenPtr screen, int num_texture_ports)
void
glamor_xv_init_port(glamor_port_private *port_priv)
{
glamor_port_private *port_priv;
XF86VideoAdaptorPtr adapt;
int i;
port_priv->brightness = 0;
port_priv->contrast = 0;
port_priv->saturation = 0;
port_priv->hue = 0;
port_priv->gamma = 1000;
port_priv->transform_index = 0;
glamor_init_xv_shader(screen);
adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
(sizeof(glamor_port_private) + sizeof(DevUnion)));
if (adapt == NULL)
return NULL;
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
xvContrast = MAKE_ATOM("XV_CONTRAST");
xvSaturation = MAKE_ATOM("XV_SATURATION");
xvHue = MAKE_ATOM("XV_HUE");
xvGamma = MAKE_ATOM("XV_GAMMA");
xvColorspace = MAKE_ATOM("XV_COLORSPACE");
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
adapt->flags = 0;
adapt->name = "GLAMOR Textured Video";
adapt->nEncodings = 1;
adapt->pEncodings = DummyEncodingGLAMOR;
adapt->nFormats = NUM_FORMATS;
adapt->pFormats = Formats;
adapt->nPorts = num_texture_ports;
adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
adapt->pAttributes = Attributes_glamor;
adapt->nAttributes = NUM_ATTRIBUTES;
port_priv =
(glamor_port_private *) (&adapt->pPortPrivates[num_texture_ports]);
adapt->pImages = Images;
adapt->nImages = NUM_IMAGES;
adapt->PutVideo = NULL;
adapt->PutStill = NULL;
adapt->GetVideo = NULL;
adapt->GetStill = NULL;
adapt->StopVideo = glamor_xv_stop_video;
adapt->SetPortAttribute = glamor_xv_set_port_attribute;
adapt->GetPortAttribute = glamor_xv_get_port_attribute;
adapt->QueryBestSize = glamor_xv_query_best_size;
adapt->PutImage = glamor_xv_put_image;
adapt->ReputImage = NULL;
adapt->QueryImageAttributes = glamor_xv_query_image_attributes;
for (i = 0; i < num_texture_ports; i++) {
glamor_port_private *pPriv = &port_priv[i];
pPriv->brightness = 0;
pPriv->contrast = 0;
pPriv->saturation = 0;
pPriv->hue = 0;
pPriv->gamma = 1000;
pPriv->transform_index = 0;
REGION_NULL(pScreen, &pPriv->clip);
adapt->pPortPrivates[i].ptr = (void *) (pPriv);
}
return adapt;
REGION_NULL(pScreen, &port_priv->clip);
}
void
glamor_xv_core_init(ScreenPtr screen)
{
glamorBrightness = MAKE_ATOM("XV_BRIGHTNESS");
glamorContrast = MAKE_ATOM("XV_CONTRAST");
glamorSaturation = MAKE_ATOM("XV_SATURATION");
glamorHue = MAKE_ATOM("XV_HUE");
glamorGamma = MAKE_ATOM("XV_GAMMA");
glamorColorspace = MAKE_ATOM("XV_COLORSPACE");
}

View File

@ -35,9 +35,14 @@ XV_SRCS = ephyrvideo.c
endif
if GLAMOR
if XV
GLAMOR_XV_SRCS = ephyr_glamor_xv.c
endif
GLAMOR_SRCS = \
ephyr_glamor_glx.c \
ephyr_glamor_glx.h \
$(GLAMOR_XV_SRCS) \
$()
endif

View File

@ -650,7 +650,9 @@ ephyrInitScreen(ScreenPtr pScreen)
#ifdef XV
if (!ephyrNoXV) {
if (!ephyrInitVideo(pScreen)) {
if (ephyr_glamor)
ephyr_glamor_xv_init(pScreen);
else if (!ephyrInitVideo(pScreen)) {
EPHYR_LOG_ERROR("failed to initialize xvideo\n");
}
else {

View File

@ -224,4 +224,14 @@ void ephyr_glamor_host_paint_rect(ScreenPtr pScreen);
Bool ephyrInitVideo(ScreenPtr pScreen);
/* ephyr_glamor_xv.c */
#ifdef GLAMOR
void ephyr_glamor_xv_init(ScreenPtr screen);
#else /* !GLAMOR */
static inline void
ephyr_glamor_xv_init(ScreenPtr screen)
{
}
#endif /* !GLAMOR */
#endif

View File

@ -52,6 +52,7 @@
static Display *dpy;
static XVisualInfo *visual_info;
static GLXFBConfig fb_config;
Bool ephyr_glamor_gles2;
/** @} */
/**
@ -145,6 +146,10 @@ ephyr_glamor_setup_texturing_shader(struct ephyr_glamor *glamor)
"}\n";
const char *fs_source =
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"\n"
"varying vec2 t;\n"
"uniform sampler2D s; /* initially 0 */\n"
"\n"
@ -276,7 +281,24 @@ ephyr_glamor_glx_screen_init(xcb_window_t win)
glx_win = glXCreateWindow(dpy, fb_config, win, NULL);
ctx = glXCreateContext(dpy, visual_info, NULL, True);
if (ephyr_glamor_gles2) {
static const int context_attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES_PROFILE_BIT_EXT,
0,
};
if (epoxy_has_glx_extension(dpy, DefaultScreen(dpy),
"GLX_EXT_create_context_es2_profile")) {
ctx = glXCreateContextAttribsARB(dpy, fb_config, NULL, True,
context_attribs);
} else {
FatalError("Xephyr -glamor_gles2 rquires "
"GLX_EXT_create_context_es2_profile\n");
}
} else {
ctx = glXCreateContext(dpy, visual_info, NULL, True);
}
if (ctx == NULL)
FatalError("glXCreateContext failed\n");

View File

@ -0,0 +1,161 @@
/*
* Copyright © 2014 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <kdrive-config.h>
#endif
#include "kdrive.h"
#include "kxv.h"
#include "ephyr.h"
#include "glamor_priv.h"
#include <X11/extensions/Xv.h>
#include "fourcc.h"
#define NUM_FORMATS 3
static KdVideoFormatRec Formats[NUM_FORMATS] = {
{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
};
static void
ephyr_glamor_xv_stop_video(KdScreenInfo *screen, void *data, Bool cleanup)
{
if (!cleanup)
return;
glamor_xv_stop_video(data);
}
static int
ephyr_glamor_xv_set_port_attribute(KdScreenInfo *screen,
Atom attribute, INT32 value, void *data)
{
return glamor_xv_set_port_attribute(data, attribute, value);
}
static int
ephyr_glamor_xv_get_port_attribute(KdScreenInfo *screen,
Atom attribute, INT32 *value, void *data)
{
return glamor_xv_get_port_attribute(data, attribute, value);
}
static void
ephyr_glamor_xv_query_best_size(KdScreenInfo *screen,
Bool motion,
short vid_w, short vid_h,
short drw_w, short drw_h,
unsigned int *p_w, unsigned int *p_h,
void *data)
{
*p_w = drw_w;
*p_h = drw_h;
}
static int
ephyr_glamor_xv_query_image_attributes(KdScreenInfo *screen,
int id,
unsigned short *w, unsigned short *h,
int *pitches, int *offsets)
{
return glamor_xv_query_image_attributes(id, w, h, pitches, offsets);
}
static int
ephyr_glamor_xv_put_image(KdScreenInfo *screen,
DrawablePtr pDrawable,
short src_x, short src_y,
short drw_x, short drw_y,
short src_w, short src_h,
short drw_w, short drw_h,
int id,
unsigned char *buf,
short width,
short height,
Bool sync,
RegionPtr clipBoxes, void *data)
{
return glamor_xv_put_image(data, pDrawable,
src_x, src_y,
drw_x, drw_y,
src_w, src_h,
drw_w, drw_h,
id, buf, width, height, sync, clipBoxes);
}
void
ephyr_glamor_xv_init(ScreenPtr screen)
{
KdVideoAdaptorRec *adaptor;
glamor_port_private *port_privates;
KdVideoEncodingRec encoding = {
0,
"XV_IMAGE",
/* These sizes should probably be GL_MAX_TEXTURE_SIZE instead
* of 2048, but our context isn't set up yet.
*/
2048, 2048,
{1, 1}
};
int i;
glamor_xv_core_init(screen);
adaptor = xnfcalloc(1, sizeof(*adaptor));
adaptor->name = "glamor textured video";
adaptor->type = XvWindowMask | XvInputMask | XvImageMask;
adaptor->flags = 0;
adaptor->nEncodings = 1;
adaptor->pEncodings = &encoding;
adaptor->pFormats = Formats;
adaptor->nFormats = NUM_FORMATS;
adaptor->nPorts = 16; /* Some absurd number */
port_privates = xnfcalloc(adaptor->nPorts,
sizeof(glamor_port_private));
adaptor->pPortPrivates = xnfcalloc(adaptor->nPorts,
sizeof(glamor_port_private *));
for (i = 0; i < adaptor->nPorts; i++) {
adaptor->pPortPrivates[i].ptr = &port_privates[i];
glamor_xv_init_port(&port_privates[i]);
}
adaptor->pAttributes = glamor_xv_attributes;
adaptor->nAttributes = glamor_xv_num_attributes;
adaptor->pImages = glamor_xv_images;
adaptor->nImages = glamor_xv_num_images;
adaptor->StopVideo = ephyr_glamor_xv_stop_video;
adaptor->SetPortAttribute = ephyr_glamor_xv_set_port_attribute;
adaptor->GetPortAttribute = ephyr_glamor_xv_get_port_attribute;
adaptor->QueryBestSize = ephyr_glamor_xv_query_best_size;
adaptor->PutImage = ephyr_glamor_xv_put_image;
adaptor->QueryImageAttributes = ephyr_glamor_xv_query_image_attributes;
KdXVScreenInit(screen, adaptor, 1);
}

View File

@ -35,7 +35,7 @@ extern Bool EphyrWantGrayScale;
extern Bool EphyrWantResize;
extern Bool kdHasPointer;
extern Bool kdHasKbd;
extern Bool ephyr_glamor;
extern Bool ephyr_glamor, ephyr_glamor_gles2;
#ifdef GLXEXT
extern Bool ephyrNoDRI;
@ -138,6 +138,7 @@ ddxUseMsg(void)
ErrorF("-resizeable Make Xephyr windows resizeable\n");
#ifdef GLAMOR
ErrorF("-glamor Enable 2D acceleration using glamor\n");
ErrorF("-glamor_gles2 Enable 2D acceleration using glamor (with GLES2 only)\n");
#endif
ErrorF
("-fakexa Simulate acceleration using software rendering\n");
@ -251,6 +252,15 @@ ddxProcessArgument(int argc, char **argv, int i)
ephyrFuncs.finiAccel = ephyr_glamor_fini;
return 1;
}
else if (!strcmp (argv[i], "-glamor_gles2")) {
ephyr_glamor = TRUE;
ephyr_glamor_gles2 = TRUE;
ephyrFuncs.initAccel = ephyr_glamor_init;
ephyrFuncs.enableAccel = ephyr_glamor_enable;
ephyrFuncs.disableAccel = ephyr_glamor_disable;
ephyrFuncs.finiAccel = ephyr_glamor_fini;
return 1;
}
#endif
else if (!strcmp(argv[i], "-fakexa")) {
ephyrFuncs.initAccel = ephyrDrawInit;

View File

@ -69,7 +69,7 @@ static Bool ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv * a_this);
static Bool ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this,
ScreenPtr a_screen);
static Bool ephyrXVPrivIsAttrValueValid(KdAttributePtr a_attrs,
static Bool ephyrXVPrivIsAttrValueValid(XvAttributePtr a_attrs,
int a_attrs_len,
const char *a_attr_name,
int a_attr_value, Bool *a_is_valid);
@ -363,7 +363,7 @@ translate_xv_attributes(KdVideoAdaptorPtr adaptor,
it = xcb_xv_query_port_attributes_attributes_iterator(reply);
for (i = 0; i < reply->num_attributes; i++) {
KdAttributePtr attribute = &adaptor->pAttributes[i];
XvAttributePtr attribute = &adaptor->pAttributes[i];
attribute->flags = it.data->flags;
attribute->min_value = it.data->min;
@ -397,7 +397,7 @@ translate_xv_image_formats(KdVideoAdaptorPtr adaptor,
return FALSE;
adaptor->nImages = reply->num_formats;
adaptor->pImages = calloc(reply->num_formats, sizeof(KdImageRec));
adaptor->pImages = calloc(reply->num_formats, sizeof(XvImageRec));
if (!adaptor->pImages) {
free(reply);
return FALSE;
@ -405,7 +405,7 @@ translate_xv_image_formats(KdVideoAdaptorPtr adaptor,
formats = xcb_xv_list_image_formats_format(reply);
for (i = 0; i < reply->num_formats; i++) {
KdImagePtr image = &adaptor->pImages[i];
XvImagePtr image = &adaptor->pImages[i];
image->id = formats[i].id;
image->type = formats[i].type;
@ -612,11 +612,7 @@ ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv * a_this)
static Bool
ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
{
KdScreenPriv(a_screen);
KdScreenInfo *screen = pScreenPriv->screen;
Bool is_ok = FALSE;
KdVideoAdaptorPtr *adaptors = NULL, *registered_adaptors = NULL;
int num_registered_adaptors = 0, i = 0, num_adaptors = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_this && a_screen, FALSE);
@ -624,38 +620,22 @@ ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
if (!a_this->num_adaptors)
goto out;
num_registered_adaptors =
KdXVListGenericAdaptors(screen, &registered_adaptors);
num_adaptors = num_registered_adaptors + a_this->num_adaptors;
adaptors = calloc(num_adaptors, sizeof(KdVideoAdaptorPtr));
if (!adaptors) {
EPHYR_LOG_ERROR("failed to allocate adaptors tab\n");
goto out;
}
memmove(adaptors, registered_adaptors, num_registered_adaptors);
for (i = 0; i < a_this->num_adaptors; i++) {
*(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i];
}
if (!KdXVScreenInit(a_screen, adaptors, num_adaptors)) {
if (!KdXVScreenInit(a_screen, a_this->adaptors, a_this->num_adaptors)) {
EPHYR_LOG_ERROR("failed to register adaptors\n");
goto out;
}
EPHYR_LOG("there are %d registered adaptors\n", num_adaptors);
EPHYR_LOG("there are %d registered adaptors\n", a_this->num_adaptors);
is_ok = TRUE;
out:
free(registered_adaptors);
registered_adaptors = NULL;
free(adaptors);
adaptors = NULL;
EPHYR_LOG("leave\n");
return is_ok;
}
static Bool
ephyrXVPrivIsAttrValueValid(KdAttributePtr a_attrs,
ephyrXVPrivIsAttrValueValid(XvAttributePtr a_attrs,
int a_attrs_len,
const char *a_attr_name,
int a_attr_value, Bool *a_is_valid)

View File

@ -287,7 +287,8 @@ hostx_set_title(char *title)
int
hostx_init(void)
{
uint32_t attr;
uint32_t attrs[2];
uint32_t attr_mask = 0;
xcb_cursor_t empty_cursor;
xcb_pixmap_t cursor_pxm;
uint16_t red, green, blue;
@ -299,7 +300,7 @@ hostx_init(void)
const xcb_query_extension_reply_t *shm_rep;
xcb_screen_t *xscreen;
attr =
attrs[0] =
XCB_EVENT_MASK_BUTTON_PRESS
| XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_POINTER_MOTION
@ -307,6 +308,7 @@ hostx_init(void)
| XCB_EVENT_MASK_KEY_RELEASE
| XCB_EVENT_MASK_EXPOSURE
| XCB_EVENT_MASK_STRUCTURE_NOTIFY;
attr_mask |= XCB_CW_EVENT_MASK;
EPHYR_DBG("mark");
#ifdef GLAMOR
@ -325,9 +327,18 @@ hostx_init(void)
HostX.gc = xcb_generate_id(HostX.conn);
HostX.depth = xscreen->root_depth;
#ifdef GLAMOR
if (ephyr_glamor)
if (ephyr_glamor) {
HostX.visual = ephyr_glamor_get_visual();
else
if (HostX.visual->visual_id != xscreen->root_visual) {
attrs[1] = xcb_generate_id(HostX.conn);
attr_mask |= XCB_CW_COLORMAP;
xcb_create_colormap(HostX.conn,
XCB_COLORMAP_ALLOC_NONE,
attrs[1],
HostX.winroot,
HostX.visual->visual_id);
}
} else
#endif
HostX.visual = xcb_aux_find_visual_by_id(xscreen,xscreen->root_visual);
@ -379,9 +390,9 @@ hostx_init(void)
scrpriv->win_height,
0,
XCB_WINDOW_CLASS_COPY_FROM_PARENT,
XCB_COPY_FROM_PARENT,
XCB_CW_EVENT_MASK,
&attr);
HostX.visual->visual_id,
attr_mask,
attrs);
}
else {
xcb_create_window(HostX.conn,
@ -391,9 +402,9 @@ hostx_init(void)
0,0,100,100, /* will resize */
0,
XCB_WINDOW_CLASS_COPY_FROM_PARENT,
XCB_COPY_FROM_PARENT,
XCB_CW_EVENT_MASK,
&attr);
HostX.visual->visual_id,
attr_mask,
attrs);
hostx_set_win_title(screen,
"(ctrl+shift grabs mouse and keyboard)");
@ -1234,8 +1245,7 @@ ephyr_glamor_init(ScreenPtr screen)
glamor_init(screen,
GLAMOR_USE_SCREEN |
GLAMOR_USE_PICTURE_SCREEN |
GLAMOR_INVERTED_Y_AXIS);
GLAMOR_USE_PICTURE_SCREEN);
return TRUE;
}

View File

@ -98,7 +98,7 @@ static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
/* misc */
static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr *, int);
static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr, int);
static DevPrivateKeyRec KdXVWindowKeyRec;
@ -116,49 +116,6 @@ static unsigned long PortResource = 0;
#define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \
dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey))
static KdXVInitGenericAdaptorPtr *GenDrivers = NULL;
static int NumGenDrivers = 0;
int
KdXVRegisterGenericAdaptorDriver(KdXVInitGenericAdaptorPtr InitFunc)
{
KdXVInitGenericAdaptorPtr *newdrivers;
/* fprintf(stderr,"KdXVRegisterGenericAdaptorDriver\n"); */
newdrivers = realloc(GenDrivers, sizeof(KdXVInitGenericAdaptorPtr) *
(1 + NumGenDrivers));
if (!newdrivers)
return 0;
GenDrivers = newdrivers;
GenDrivers[NumGenDrivers++] = InitFunc;
return 1;
}
int
KdXVListGenericAdaptors(KdScreenInfo * screen, KdVideoAdaptorPtr ** adaptors)
{
int i, j, n, num;
KdVideoAdaptorPtr *DrivAdap, *new;
num = 0;
*adaptors = NULL;
for (i = 0; i < NumGenDrivers; i++) {
n = GenDrivers[i] (screen, &DrivAdap);
if (0 == n)
continue;
new = realloc(*adaptors, sizeof(KdVideoAdaptorPtr) * (num + n));
if (NULL == new)
continue;
*adaptors = new;
for (j = 0; j < n; j++, num++)
(*adaptors)[num] = DrivAdap[j];
}
return num;
}
KdVideoAdaptorPtr
KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen)
{
@ -172,7 +129,7 @@ KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr)
}
Bool
KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr * adaptors, int num)
KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr adaptors, int num)
{
KdXVScreenPtr ScreenPriv;
XvScreenPtr pxvs;
@ -282,7 +239,7 @@ KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
}
static Bool
KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr infoPtr, int number)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
@ -295,15 +252,11 @@ KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
XvPortRecPrivatePtr portPriv;
XvPortPtr pPort, pp;
int numPort;
KdAttributePtr attributePtr;
XvAttributePtr pAttribute, pat;
KdVideoFormatPtr formatPtr;
XvFormatPtr pFormat, pf;
int numFormat, totFormat;
KdVideoEncodingPtr encodingPtr;
XvEncodingPtr pEncode, pe;
KdImagePtr imagePtr;
XvImagePtr pImage, pi;
int numVisuals;
VisualPtr pVisual;
int i;
@ -315,7 +268,7 @@ KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
return FALSE;
for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
adaptorPtr = infoPtr[na];
adaptorPtr = &infoPtr[na];
if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
!adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
@ -381,26 +334,24 @@ KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
}
if (adaptorPtr->nImages &&
(pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
for (i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
i < adaptorPtr->nImages; i++, pi++, imagePtr++) {
memcpy(pi, imagePtr, sizeof(*pi));
}
(pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
memcpy(pa->pImages, adaptorPtr->pImages,
adaptorPtr->nImages * sizeof(XvImageRec));
pa->nImages = adaptorPtr->nImages;
pa->pImages = pImage;
}
if (adaptorPtr->nAttributes &&
(pAttribute =
calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) {
for (pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i =
0; i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) {
memcpy(pat, attributePtr, sizeof(*pat));
pat->name = strdup(attributePtr->name);
(pa->pAttributes = calloc(adaptorPtr->nAttributes,
sizeof(XvAttributeRec)))) {
memcpy(pa->pAttributes, adaptorPtr->pAttributes,
adaptorPtr->nAttributes * sizeof(XvAttributeRec));
for (i = 0; i < adaptorPtr->nAttributes; i++) {
pa->pAttributes[i].name =
strdup(adaptorPtr->pAttributes[i].name);
}
pa->nAttributes = adaptorPtr->nAttributes;
pa->pAttributes = pAttribute;
}
totFormat = adaptorPtr->nFormats;

View File

@ -56,8 +56,6 @@ of the copyright holder.
#define VIDEO_OVERLAID_STILLS 0x00000008
#define VIDEO_CLIP_TO_VIEWPORT 0x00000010
typedef XvImageRec KdImageRec, *KdImagePtr;
typedef struct {
KdScreenInfo *screen;
int id;
@ -121,7 +119,7 @@ typedef enum {
typedef struct {
int id;
char *name;
const char *name;
unsigned short width, height;
XvRationalRec rate;
} KdVideoEncodingRec, *KdVideoEncodingPtr;
@ -131,12 +129,10 @@ typedef struct {
short class;
} KdVideoFormatRec, *KdVideoFormatPtr;
typedef XvAttributeRec KdAttributeRec, *KdAttributePtr;
typedef struct {
unsigned int type;
int flags;
char *name;
const char *name;
int nEncodings;
KdVideoEncodingPtr pEncodings;
int nFormats;
@ -144,9 +140,9 @@ typedef struct {
int nPorts;
DevUnion *pPortPrivates;
int nAttributes;
KdAttributePtr pAttributes;
XvAttributePtr pAttributes;
int nImages;
KdImagePtr pImages;
XvImagePtr pImages;
PutVideoFuncPtr PutVideo;
PutStillFuncPtr PutStill;
GetVideoFuncPtr GetVideo;
@ -161,16 +157,7 @@ typedef struct {
} KdVideoAdaptorRec, *KdVideoAdaptorPtr;
Bool
KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr * Adaptors, int num);
typedef int (*KdXVInitGenericAdaptorPtr) (KdScreenInfo * screen,
KdVideoAdaptorPtr ** Adaptors);
int
KdXVRegisterGenericAdaptorDriver(KdXVInitGenericAdaptorPtr InitFunc);
int
KdXVListGenericAdaptors(KdScreenInfo * screen, KdVideoAdaptorPtr ** Adaptors);
KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr Adaptors, int num);
void

View File

@ -359,15 +359,11 @@ xf86XVInitAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr * infoPtr, int number)
XvPortRecPrivatePtr portPriv;
XvPortPtr pPort, pp;
int numPort;
XF86AttributePtr attributePtr;
XvAttributePtr pAttribute, pat;
XF86VideoFormatPtr formatPtr;
XvFormatPtr pFormat, pf;
int numFormat, totFormat;
XF86VideoEncodingPtr encodingPtr;
XvEncodingPtr pEncode, pe;
XF86ImagePtr imagePtr;
XvImagePtr pImage, pi;
int numVisuals;
VisualPtr pVisual;
int i;
@ -445,49 +441,24 @@ xf86XVInitAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr * infoPtr, int number)
}
if (adaptorPtr->nImages &&
(pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
for (i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
i < adaptorPtr->nImages; i++, pi++, imagePtr++) {
pi->id = imagePtr->id;
pi->type = imagePtr->type;
pi->byte_order = imagePtr->byte_order;
memcpy(pi->guid, imagePtr->guid, 16);
pi->bits_per_pixel = imagePtr->bits_per_pixel;
pi->format = imagePtr->format;
pi->num_planes = imagePtr->num_planes;
pi->depth = imagePtr->depth;
pi->red_mask = imagePtr->red_mask;
pi->green_mask = imagePtr->green_mask;
pi->blue_mask = imagePtr->blue_mask;
pi->y_sample_bits = imagePtr->y_sample_bits;
pi->u_sample_bits = imagePtr->u_sample_bits;
pi->v_sample_bits = imagePtr->v_sample_bits;
pi->horz_y_period = imagePtr->horz_y_period;
pi->horz_u_period = imagePtr->horz_u_period;
pi->horz_v_period = imagePtr->horz_v_period;
pi->vert_y_period = imagePtr->vert_y_period;
pi->vert_u_period = imagePtr->vert_u_period;
pi->vert_v_period = imagePtr->vert_v_period;
memcpy(pi->component_order, imagePtr->component_order, 32);
pi->scanline_order = imagePtr->scanline_order;
}
(pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
memcpy(pa->pImages, adaptorPtr->pImages,
adaptorPtr->nImages * sizeof(XvImageRec));
pa->nImages = adaptorPtr->nImages;
pa->pImages = pImage;
}
if (adaptorPtr->nAttributes &&
(pAttribute =
calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) {
for (pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i =
0; i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) {
pat->flags = attributePtr->flags;
pat->min_value = attributePtr->min_value;
pat->max_value = attributePtr->max_value;
pat->name = strdup(attributePtr->name);
(pa->pAttributes = calloc(adaptorPtr->nAttributes,
sizeof(XvAttributeRec)))) {
memcpy(pa->pAttributes, adaptorPtr->pAttributes,
adaptorPtr->nAttributes * sizeof(XvAttributeRec));
for (i = 0; i < adaptorPtr->nAttributes; i++) {
pa->pAttributes[i].name =
strdup(adaptorPtr->pAttributes[i].name);
}
pa->nAttributes = adaptorPtr->nAttributes;
pa->pAttributes = pAttribute;
}
totFormat = adaptorPtr->nFormats;

View File

@ -42,34 +42,7 @@
*/
#define VIDEO_CLIP_TO_VIEWPORT 0x00000010
typedef struct {
int id;
int type;
int byte_order;
unsigned char guid[16];
int bits_per_pixel;
int format;
int num_planes;
/* for RGB formats only */
int depth;
unsigned int red_mask;
unsigned int green_mask;
unsigned int blue_mask;
/* for YUV formats only */
unsigned int y_sample_bits;
unsigned int u_sample_bits;
unsigned int v_sample_bits;
unsigned int horz_y_period;
unsigned int horz_u_period;
unsigned int horz_v_period;
unsigned int vert_y_period;
unsigned int vert_u_period;
unsigned int vert_v_period;
char component_order[32];
int scanline_order;
} XF86ImageRec, *XF86ImagePtr;
typedef XvImageRec XF86ImageRec, *XF86ImagePtr;
typedef struct {
ScrnInfoPtr pScrn;
@ -147,12 +120,7 @@ typedef struct {
short class;
} XF86VideoFormatRec, *XF86VideoFormatPtr;
typedef struct {
int flags;
int min_value;
int max_value;
const char *name;
} XF86AttributeRec, *XF86AttributePtr;
typedef XvAttributeRec XF86AttributeRec, *XF86AttributePtr;
typedef struct {
unsigned int type;

View File

@ -24,7 +24,7 @@ module_LTLIBRARIES = libglamoregl.la
libglamoregl_la_SOURCES = \
$(top_srcdir)/glamor/glamor_egl.c \
$(top_srcdir)/glamor/glamor_eglmodule.c \
$(top_srcdir)/glamor/glamor_xv.c \
glamor_xf86_xv.c \
$()
libglamoregl_la_LDFLAGS = \
@ -38,6 +38,7 @@ libglamoregl_la_LIBADD = \
AM_CPPFLAGS = $(XORG_INCS) \
-I$(top_srcdir)/dri3 \
-I$(top_srcdir)/glamor \
$()
AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS)

View File

@ -0,0 +1,185 @@
/*
* Copyright © 2013 Red Hat
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Dave Airlie <airlied@redhat.com>
*
* some code is derived from the xf86-video-ati radeon driver, mainly
* the calculations.
*/
/** @file glamor_xf86_xv.c
*
* This implements the XF86 XV interface, and calls into glamor core
* for its support of the suspiciously similar XF86 and Kdrive
* device-dependent XV interfaces.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#define GLAMOR_FOR_XORG
#include "glamor_priv.h"
#include <X11/extensions/Xv.h>
#include "fourcc.h"
#define NUM_FORMATS 3
static XF86VideoFormatRec Formats[NUM_FORMATS] = {
{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
};
static void
glamor_xf86_xv_stop_video(ScrnInfoPtr pScrn, void *data, Bool cleanup)
{
if (!cleanup)
return;
glamor_xv_stop_video(data);
}
static int
glamor_xf86_xv_set_port_attribute(ScrnInfoPtr pScrn,
Atom attribute, INT32 value, void *data)
{
return glamor_xv_set_port_attribute(data, attribute, value);
}
static int
glamor_xf86_xv_get_port_attribute(ScrnInfoPtr pScrn,
Atom attribute, INT32 *value, void *data)
{
return glamor_xv_get_port_attribute(data, attribute, value);
}
static void
glamor_xf86_xv_query_best_size(ScrnInfoPtr pScrn,
Bool motion,
short vid_w, short vid_h,
short drw_w, short drw_h,
unsigned int *p_w, unsigned int *p_h, void *data)
{
*p_w = drw_w;
*p_h = drw_h;
}
static int
glamor_xf86_xv_query_image_attributes(ScrnInfoPtr pScrn,
int id,
unsigned short *w, unsigned short *h,
int *pitches, int *offsets)
{
return glamor_xv_query_image_attributes(id, w, h, pitches, offsets);
}
static int
glamor_xf86_xv_put_image(ScrnInfoPtr pScrn,
short src_x, short src_y,
short drw_x, short drw_y,
short src_w, short src_h,
short drw_w, short drw_h,
int id,
unsigned char *buf,
short width,
short height,
Bool sync,
RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
{
return glamor_xv_put_image(data, pDrawable,
src_x, src_y,
drw_x, drw_y,
src_w, src_h,
drw_w, drw_h,
id, buf, width, height, sync, clipBoxes);
}
static XF86VideoEncodingRec DummyEncodingGLAMOR[1] = {
{
0,
"XV_IMAGE",
8192, 8192,
{1, 1}
}
};
XF86VideoAdaptorPtr
glamor_xv_init(ScreenPtr screen, int num_texture_ports)
{
glamor_port_private *port_priv;
XF86VideoAdaptorPtr adapt;
int i;
glamor_xv_core_init(screen);
adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
(sizeof(glamor_port_private) + sizeof(DevUnion)));
if (adapt == NULL)
return NULL;
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
adapt->flags = 0;
adapt->name = "GLAMOR Textured Video";
adapt->nEncodings = 1;
adapt->pEncodings = DummyEncodingGLAMOR;
adapt->nFormats = NUM_FORMATS;
adapt->pFormats = Formats;
adapt->nPorts = num_texture_ports;
adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
adapt->pAttributes = glamor_xv_attributes;
adapt->nAttributes = glamor_xv_num_attributes;
port_priv =
(glamor_port_private *) (&adapt->pPortPrivates[num_texture_ports]);
adapt->pImages = glamor_xv_images;
adapt->nImages = glamor_xv_num_images;
adapt->PutVideo = NULL;
adapt->PutStill = NULL;
adapt->GetVideo = NULL;
adapt->GetStill = NULL;
adapt->StopVideo = glamor_xf86_xv_stop_video;
adapt->SetPortAttribute = glamor_xf86_xv_set_port_attribute;
adapt->GetPortAttribute = glamor_xf86_xv_get_port_attribute;
adapt->QueryBestSize = glamor_xf86_xv_query_best_size;
adapt->PutImage = glamor_xf86_xv_put_image;
adapt->ReputImage = NULL;
adapt->QueryImageAttributes = glamor_xf86_xv_query_image_attributes;
for (i = 0; i < num_texture_ports; i++) {
glamor_port_private *pPriv = &port_priv[i];
pPriv->brightness = 0;
pPriv->contrast = 0;
pPriv->saturation = 0;
pPriv->hue = 0;
pPriv->gamma = 1000;
pPriv->transform_index = 0;
REGION_NULL(pScreen, &pPriv->clip);
adapt->pPortPrivates[i].ptr = (void *) (pPriv);
}
return adapt;
}

11
mi/mi.h
View File

@ -67,6 +67,11 @@ typedef struct _miDash *miDashPtr;
/* miarc.c */
extern _X_EXPORT void miWideArc(DrawablePtr pDraw,
GCPtr pGC,
int narcs,
xArc * parcs);
extern _X_EXPORT void miPolyArc(DrawablePtr /*pDraw */ ,
GCPtr /*pGC */ ,
int /*narcs */ ,
@ -452,6 +457,12 @@ extern _X_EXPORT void miWideDash(DrawablePtr /*pDrawable */ ,
DDXPointPtr /*pPts */
);
extern _X_EXPORT void miPolylines(DrawablePtr pDrawable,
GCPtr pGC,
int mode,
int npt,
DDXPointPtr pPts);
/* miwindow.c */
extern _X_EXPORT void miClearToBackground(WindowPtr /*pWin */ ,

View File

@ -886,7 +886,7 @@ miFillWideEllipse(DrawablePtr pDraw, GCPtr pGC, xArc * parc)
*/
void
miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
{
int i;
xArc *parc;
@ -3396,3 +3396,12 @@ drawQuadrant(struct arc_def *def,
y--;
}
}
void
miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
{
if (pGC->lineWidth == 0)
miZeroPolyArc(pDraw, pGC, narcs, parcs);
else
miWideArc(pDraw, pGC, narcs, parcs);
}

View File

@ -476,26 +476,16 @@ miFillArcSliceSetup(xArc * arc, miArcSliceRec * slice, GCPtr pGC)
*wids++ = slw; \
}
static void
miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
static int
miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
{
int x, y, e;
int yk, xk, ym, xm, dx, dy, xorg, yorg;
int slw;
miFillArcRec info;
DDXPointPtr points;
DDXPointPtr pts;
int *widths;
int *wids;
points = malloc(sizeof(DDXPointRec) * arc->height);
if (!points)
return;
widths = malloc(sizeof(int) * arc->height);
if (!widths) {
free(points);
return;
}
miFillArcSetup(arc, &info);
MIFILLARCSETUP();
if (pGC->miTranslate) {
@ -508,31 +498,19 @@ miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
MIFILLARCSTEP(slw);
ADDSPANS();
}
(*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
free(widths);
free(points);
return pts - points;
}
static void
miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
static int
miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
{
int x, y;
int xorg, yorg, dx, dy, slw;
double e, yk, xk, ym, xm;
miFillArcDRec info;
DDXPointPtr points;
DDXPointPtr pts;
int *widths;
int *wids;
points = malloc(sizeof(DDXPointRec) * arc->height);
if (!points)
return;
widths = malloc(sizeof(int) * arc->height);
if (!widths) {
free(points);
return;
}
miFillArcDSetup(arc, &info);
MIFILLARCSETUP();
if (pGC->miTranslate) {
@ -545,9 +523,7 @@ miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
MIFILLARCSTEP(slw);
ADDSPANS();
}
(*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
free(widths);
free(points);
return pts - points;
}
#define ADDSPAN(l,r) \
@ -572,17 +548,15 @@ miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
ADDSPAN(xl, xc); \
}
static void
miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
static int
miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
{
int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
int x, y, e;
miFillArcRec info;
miArcSliceRec slice;
int ya, xl, xr, xc;
DDXPointPtr points;
DDXPointPtr pts;
int *widths;
int *wids;
miFillArcSetup(arc, &info);
@ -591,14 +565,6 @@ miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
slw = arc->height;
if (slice.flip_top || slice.flip_bot)
slw += (arc->height >> 1) + 1;
points = malloc(sizeof(DDXPointRec) * slw);
if (!points)
return;
widths = malloc(sizeof(int) * slw);
if (!widths) {
free(points);
return;
}
if (pGC->miTranslate) {
xorg += pDraw->x;
yorg += pDraw->y;
@ -622,13 +588,11 @@ miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
ADDSLICESPANS(slice.flip_bot);
}
}
(*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
free(widths);
free(points);
return pts - points;
}
static void
miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
static int
miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
{
int x, y;
int dx, dy, xorg, yorg, slw;
@ -636,9 +600,7 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
miFillArcDRec info;
miArcSliceRec slice;
int ya, xl, xr, xc;
DDXPointPtr points;
DDXPointPtr pts;
int *widths;
int *wids;
miFillArcDSetup(arc, &info);
@ -647,14 +609,6 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
slw = arc->height;
if (slice.flip_top || slice.flip_bot)
slw += (arc->height >> 1) + 1;
points = malloc(sizeof(DDXPointRec) * slw);
if (!points)
return;
widths = malloc(sizeof(int) * slw);
if (!widths) {
free(points);
return;
}
if (pGC->miTranslate) {
xorg += pDraw->x;
yorg += pDraw->y;
@ -678,35 +632,69 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
ADDSLICESPANS(slice.flip_bot);
}
}
(*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
free(widths);
free(points);
return pts - points;
}
/* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
* Since we don't have to worry about overlapping segments, we can just
* fill each arc as it comes.
*/
void
miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
{
int i;
xArc *arc;
for (i = narcs, arc = parcs; --i >= 0; arc++) {
if (miFillArcEmpty(arc))
continue;
if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) {
if (miCanFillArc(arc))
miFillEllipseI(pDraw, pGC, arc);
else
miFillEllipseD(pDraw, pGC, arc);
/* Limit the number of spans in a single draw request to avoid integer
* overflow in the computation of the span buffer size.
*/
#define MAX_SPANS_PER_LOOP (4 * 1024 * 1024)
void
miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs_all, xArc * parcs)
{
while (narcs_all > 0) {
int narcs;
int i;
xArc *arc;
int nspans = 0;
DDXPointPtr pts, points;
int *wids, *widths;
int n;
for (narcs = 0, arc = parcs; narcs < narcs_all; narcs++, arc++) {
if (narcs && nspans + arc->height > MAX_SPANS_PER_LOOP)
break;
nspans += arc->height;
}
else {
if (miCanFillArc(arc))
miFillArcSliceI(pDraw, pGC, arc);
else
miFillArcSliceD(pDraw, pGC, arc);
pts = points = malloc (sizeof (DDXPointRec) * nspans +
sizeof(int) * nspans);
if (points) {
wids = widths = (int *) (points + nspans);
for (i = 0, arc = parcs; i < narcs; arc++, i++) {
if (miFillArcEmpty(arc))
continue;
if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
{
if (miCanFillArc(arc))
n = miFillEllipseI(pDraw, pGC, arc, pts, wids);
else
n = miFillEllipseD(pDraw, pGC, arc, pts, wids);
}
else
{
if (miCanFillArc(arc))
n = miFillArcSliceI(pDraw, pGC, arc, pts, wids);
else
n = miFillArcSliceD(pDraw, pGC, arc, pts, wids);
}
pts += n;
wids += n;
}
nspans = pts - points;
if (nspans)
(*pGC->ops->FillSpans) (pDraw, pGC, nspans, points,
widths, FALSE);
free (points);
}
parcs += narcs;
narcs_all -= narcs;
}
}

View File

@ -1979,3 +1979,23 @@ miWideDash(DrawablePtr pDrawable, GCPtr pGC,
if (spanData)
miCleanupSpanData(pDrawable, pGC, spanData);
}
void
miPolylines(DrawablePtr drawable,
GCPtr gc,
int mode,
int n,
DDXPointPtr points)
{
if (gc->lineWidth == 0) {
if (gc->lineStyle == LineSolid)
miZeroLine(drawable, gc, mode, n, points);
else
miZeroDashLine(drawable, gc, mode, n, points);
} else {
if (gc->lineStyle == LineSolid)
miWideLine(drawable, gc, mode, n, points);
else
miWideDash(drawable, gc, mode, n, points);
}
}

View File

@ -656,7 +656,7 @@ miZeroPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
for (arc = parcs, i = narcs; --i >= 0; arc++) {
if (!miCanZeroArc(arc))
miPolyArc(pDraw, pGC, 1, arc);
miWideArc(pDraw, pGC, 1, arc);
else {
if (arc->width > arc->height)
n = arc->width + (arc->height >> 1);

View File

@ -179,14 +179,6 @@ miZeroLine(DrawablePtr pDraw, GCPtr pGC, int mode, /* Origin or Previous */
MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
while (--npt > 0) {
if (Nspans > 0)
(*pGC->ops->FillSpans) (pDraw, pGC, Nspans, pspanInit,
pwidthInit, FALSE);
Nspans = 0;
new_span = TRUE;
spans = pspanInit - 1;
widths = pwidthInit - 1;
x1 = x2;
y1 = y2;
oc1 = oc2;
@ -208,6 +200,14 @@ miZeroLine(DrawablePtr pDraw, GCPtr pGC, int mode, /* Origin or Previous */
CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
if (ady + 1 > (list_len - Nspans)) {
(*pGC->ops->FillSpans) (pDraw, pGC, Nspans, pspanInit,
pwidthInit, FALSE);
Nspans = 0;
spans = pspanInit - 1;
widths = pwidthInit - 1;
}
new_span = TRUE;
if (adx > ady) {
e1 = ady << 1;
e2 = e1 - (adx << 1);