glamor.c 13.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * Copyright © 2008 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>
 *
 */

Eric Anholt's avatar
Eric Anholt committed
28
/** @file glamor.c
29 30 31 32 33
 * This file covers the initialization and teardown of glamor, and has various
 * functions not responsible for performing rendering.
 */

#include <stdlib.h>
Eric Anholt's avatar
Eric Anholt committed
34

35 36
#include "glamor_priv.h"

37
static DevPrivateKeyRec glamor_screen_private_key_index;
38
DevPrivateKey glamor_screen_private_key = &glamor_screen_private_key_index;
39
static DevPrivateKeyRec glamor_pixmap_private_key_index;
Eric Anholt's avatar
Eric Anholt committed
40
DevPrivateKey glamor_pixmap_private_key = &glamor_pixmap_private_key_index;
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

/**
 * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable.
 *
 * @param drawable the drawable being requested.
 *
 * This function returns the backing pixmap for a drawable, whether it is a
 * redirected window, unredirected window, or already a pixmap.  Note that
 * coordinate translation is needed when drawing to the backing pixmap of a
 * redirected window, and the translation coordinates are provided by calling
 * exaGetOffscreenPixmap() on the drawable.
 */
PixmapPtr
glamor_get_drawable_pixmap(DrawablePtr drawable)
{
Zhigang Gong's avatar
Zhigang Gong committed
56 57 58 59 60
	if (drawable->type == DRAWABLE_WINDOW)
		return drawable->
		    pScreen->GetWindowPixmap((WindowPtr) drawable);
	else
		return (PixmapPtr) drawable;
61 62
}

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
_X_EXPORT void
glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type)
{
	glamor_pixmap_private *pixmap_priv;
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(pixmap->drawable.pScreen);

	pixmap_priv = glamor_get_pixmap_private(pixmap);
	if (pixmap_priv == NULL) {
		pixmap_priv = calloc(sizeof(*pixmap_priv), 1);
		dixSetPrivate(&pixmap->devPrivates,
			      glamor_pixmap_private_key, pixmap_priv);
		pixmap_priv->container = pixmap;
		pixmap_priv->glamor_priv = glamor_priv;
	}
	pixmap_priv->type = type;
}

Zhigang Gong's avatar
Zhigang Gong committed
81
_X_EXPORT void
82
glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
83
{
Zhigang Gong's avatar
Zhigang Gong committed
84 85
	ScreenPtr screen = pixmap->drawable.pScreen;
	glamor_pixmap_private *pixmap_priv;
86 87
	glamor_screen_private *glamor_priv;
	glamor_gl_dispatch *dispatch;
88
	glamor_pixmap_fbo *fbo;
Zhigang Gong's avatar
Zhigang Gong committed
89

90 91
	glamor_priv = glamor_get_screen_private(screen);
	dispatch  = &glamor_priv->dispatch;
Zhigang Gong's avatar
Zhigang Gong committed
92
	pixmap_priv = glamor_get_pixmap_private(pixmap);
93

94 95 96
	if (pixmap_priv->fbo) {
		fbo = glamor_pixmap_detach_fbo(pixmap_priv);
		glamor_destroy_fbo(fbo);
Zhigang Gong's avatar
Zhigang Gong committed
97 98
	}

99 100 101
	fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width,
					 pixmap->drawable.height,
					 pixmap->drawable.depth, tex, 0);
102

103 104 105
	if (fbo == NULL) {
		ErrorF("XXX fail to create fbo.\n");
		return;
Zhigang Gong's avatar
Zhigang Gong committed
106 107
	}

108
	glamor_pixmap_attach_fbo(pixmap, fbo);
109 110
}

111
void
112
glamor_set_screen_pixmap(PixmapPtr screen_pixmap)
113
{
Zhigang Gong's avatar
Zhigang Gong committed
114
	glamor_pixmap_private *pixmap_priv;
115
	glamor_screen_private *glamor_priv;
Zhigang Gong's avatar
Zhigang Gong committed
116

117
	glamor_priv = glamor_get_screen_private(screen_pixmap->drawable.pScreen);
118
	pixmap_priv = glamor_get_pixmap_private(screen_pixmap);
119 120 121 122
	glamor_priv->screen_fbo = pixmap_priv->fbo->fb;

	pixmap_priv->fbo->width = screen_pixmap->drawable.width;
	pixmap_priv->fbo->height = screen_pixmap->drawable.height;
123 124
}

125
PixmapPtr
126
glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
Eric Anholt's avatar
Eric Anholt committed
127
		     unsigned int usage)
128
{
Zhigang Gong's avatar
Zhigang Gong committed
129
	PixmapPtr pixmap;
130
	glamor_pixmap_type_t type = GLAMOR_TEXTURE_ONLY;
Zhigang Gong's avatar
Zhigang Gong committed
131 132 133 134
	glamor_pixmap_private *pixmap_priv;
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(screen);
	glamor_gl_dispatch *dispatch = &glamor_priv->dispatch;
135 136 137 138
	glamor_pixmap_fbo *fbo;
	int pitch;
	int flag;

Zhigang Gong's avatar
Zhigang Gong committed
139 140 141 142 143 144 145 146
	if (w > 32767 || h > 32767)
		return NullPixmap;

	if (!glamor_check_fbo_size(glamor_priv, w, h)
	    || !glamor_check_fbo_depth(depth)
	    || usage == GLAMOR_CREATE_PIXMAP_CPU) {
		/* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo.
		   If we exceed such limitation, we have to use framebuffer. */
147
		return fbCreatePixmap(screen, w, h, depth, usage);
Zhigang Gong's avatar
Zhigang Gong committed
148 149
	} else
		pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
150

Zhigang Gong's avatar
Zhigang Gong committed
151
	pixmap_priv = calloc(1, sizeof(*pixmap_priv));
152 153 154 155 156 157

	if (!pixmap_priv)
		return fbCreatePixmap(screen, w, h, depth, usage);

	dixSetPrivate(&pixmap->devPrivates,
		      glamor_pixmap_private_key,
Zhigang Gong's avatar
Zhigang Gong committed
158
		      pixmap_priv);
159

Zhigang Gong's avatar
Zhigang Gong committed
160 161
	pixmap_priv->container = pixmap;
	pixmap_priv->glamor_priv = glamor_priv;
162
	pixmap_priv->type = type;
163 164

	if (w == 0 || h == 0)
Zhigang Gong's avatar
Zhigang Gong committed
165
		return pixmap;
166

167
	fbo = glamor_create_fbo(glamor_priv, w, h, depth, usage);
168 169 170 171 172 173 174 175

	if (fbo == NULL) {
		fbDestroyPixmap(pixmap);
		free(pixmap_priv);
		return fbCreatePixmap(screen, w, h, depth, usage);
	}

	glamor_pixmap_attach_fbo(pixmap, fbo);
176

177 178
	pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
	screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
Zhigang Gong's avatar
Zhigang Gong committed
179 180 181 182 183 184 185
	return pixmap;
}

void
glamor_destroy_textured_pixmap(PixmapPtr pixmap)
{
	if (pixmap->refcnt == 1) {
186 187 188
		glamor_pixmap_private *pixmap_priv;

		pixmap_priv = glamor_get_pixmap_private(pixmap);
Zhigang Gong's avatar
Zhigang Gong committed
189
		if (pixmap_priv != NULL) {
190 191 192 193
			glamor_pixmap_fbo *fbo;
			fbo = glamor_pixmap_detach_fbo(pixmap_priv);
			if (fbo)
				glamor_destroy_fbo(fbo);
Zhigang Gong's avatar
Zhigang Gong committed
194 195 196
			free(pixmap_priv);
		}
	}
197 198
}

199
Bool
200 201
glamor_destroy_pixmap(PixmapPtr pixmap)
{
Zhigang Gong's avatar
Zhigang Gong committed
202 203 204 205 206 207 208 209 210 211 212
	glamor_destroy_textured_pixmap(pixmap);
	return fbDestroyPixmap(pixmap);
}

void
glamor_block_handler(ScreenPtr screen)
{
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(screen);
	glamor_gl_dispatch *dispatch = &glamor_priv->dispatch;

213
	glamor_priv->tick++;
Zhigang Gong's avatar
Zhigang Gong committed
214
	dispatch->glFlush();
Zhigang Gong's avatar
Zhigang Gong committed
215
	dispatch->glFinish();
216
	glamor_fbo_expire(glamor_priv);
217
}
Eric Anholt's avatar
Eric Anholt committed
218

219
static void
Zhigang Gong's avatar
Zhigang Gong committed
220 221
_glamor_block_handler(void *data, OSTimePtr timeout,
		      void *last_select_mask)
222
{
Zhigang Gong's avatar
Zhigang Gong committed
223 224
	glamor_gl_dispatch *dispatch = data;
	dispatch->glFlush();
225
	dispatch->glFinish();
226 227 228
}

static void
Zhigang Gong's avatar
Zhigang Gong committed
229
_glamor_wakeup_handler(void *data, int result, void *last_select_mask)
230 231 232
{
}

Zhigang Gong's avatar
Zhigang Gong committed
233
static void
234 235
glamor_set_debug_level(int *debug_level)
{
Zhigang Gong's avatar
Zhigang Gong committed
236 237 238 239 240 241
	char *debug_level_string;
	debug_level_string = getenv("GLAMOR_DEBUG");
	if (debug_level_string
	    && sscanf(debug_level_string, "%d", debug_level) == 1)
		return;
	*debug_level = 0;
242 243 244 245
}

int glamor_debug_level;

Eric Anholt's avatar
Eric Anholt committed
246 247
/** Set up glamor for an already-configured GL context. */
Bool
248
glamor_init(ScreenPtr screen, unsigned int flags)
Eric Anholt's avatar
Eric Anholt committed
249
{
Zhigang Gong's avatar
Zhigang Gong committed
250 251
	glamor_screen_private *glamor_priv;
	int gl_version;
252

253
#ifdef RENDER
Zhigang Gong's avatar
Zhigang Gong committed
254
	PictureScreenPtr ps = GetPictureScreenIfSet(screen);
255
#endif
Zhigang Gong's avatar
Zhigang Gong committed
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
	if (flags & ~GLAMOR_VALID_FLAGS) {
		ErrorF("glamor_init: Invalid flags %x\n", flags);
		return FALSE;
	}
	glamor_priv = calloc(1, sizeof(*glamor_priv));
	if (glamor_priv == NULL)
		return FALSE;

	if (flags & GLAMOR_INVERTED_Y_AXIS) {
		glamor_priv->yInverted = 1;
	} else
		glamor_priv->yInverted = 0;

	if (!dixRegisterPrivateKey
	    (glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
		LogMessage(X_WARNING,
			   "glamor%d: Failed to allocate screen private\n",
			   screen->myNum);
		goto fail;
	}

	dixSetPrivate(&screen->devPrivates, glamor_screen_private_key,
		      glamor_priv);

	if (!dixRegisterPrivateKey
	    (glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) {
		LogMessage(X_WARNING,
			   "glamor%d: Failed to allocate pixmap private\n",
			   screen->myNum);
		goto fail;;
	}

	gl_version = glamor_gl_get_version();
289

290
#ifndef GLAMOR_GLES2
Zhigang Gong's avatar
Zhigang Gong committed
291 292 293 294
	if (gl_version < GLAMOR_GL_VERSION_ENCODE(1, 3)) {
		ErrorF("Require OpenGL version 1.3 or latter.\n");
		goto fail;
	}
295
#else
Zhigang Gong's avatar
Zhigang Gong committed
296 297 298 299
	if (gl_version < GLAMOR_GL_VERSION_ENCODE(2, 0)) {
		ErrorF("Require Open GLES2.0 or latter.\n");
		goto fail;
	}
300
#endif
301

Zhigang Gong's avatar
Zhigang Gong committed
302 303
	glamor_gl_dispatch_init(screen, &glamor_priv->dispatch,
				gl_version);
Zhigang Gong's avatar
Zhigang Gong committed
304 305

#ifdef GLAMOR_GLES2
Zhigang Gong's avatar
Zhigang Gong committed
306 307 308 309
	if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) {
		ErrorF("GL_EXT_texture_format_BGRA8888 required\n");
		goto fail;
	}
310 311
#endif

Zhigang Gong's avatar
Zhigang Gong committed
312 313 314 315 316 317
	glamor_priv->has_pack_invert =
	    glamor_gl_has_extension("GL_MESA_pack_invert");
	glamor_priv->has_fbo_blit =
	    glamor_gl_has_extension("GL_EXT_framebuffer_blit");
	glamor_priv->dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE,
					    &glamor_priv->max_fbo_size);
318

Zhigang Gong's avatar
Zhigang Gong committed
319
	glamor_set_debug_level(&glamor_debug_level);
320

Zhigang Gong's avatar
Zhigang Gong committed
321
	if (flags & GLAMOR_USE_SCREEN) {
322 323 324 325 326 327 328
		if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler,
						    _glamor_wakeup_handler,
						    (void *)
						    &glamor_priv->dispatch)) {
			goto fail;
		}

329
		glamor_priv->saved_procs.close_screen = screen->CloseScreen;
Zhigang Gong's avatar
Zhigang Gong committed
330
		screen->CloseScreen = glamor_close_screen;
331

332
		glamor_priv->saved_procs.create_gc = screen->CreateGC;
Zhigang Gong's avatar
Zhigang Gong committed
333
		screen->CreateGC = glamor_create_gc;
334

335
		glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap;
Zhigang Gong's avatar
Zhigang Gong committed
336
		screen->CreatePixmap = glamor_create_pixmap;
337

338
		glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap;
Zhigang Gong's avatar
Zhigang Gong committed
339
		screen->DestroyPixmap = glamor_destroy_pixmap;
340

341
		glamor_priv->saved_procs.get_spans = screen->GetSpans;
Zhigang Gong's avatar
Zhigang Gong committed
342
		screen->GetSpans = glamor_get_spans;
343

344
		glamor_priv->saved_procs.get_image = screen->GetImage;
345
		screen->GetImage = glamor_get_image;
346

347
		glamor_priv->saved_procs.change_window_attributes =
Zhigang Gong's avatar
Zhigang Gong committed
348 349 350
		    screen->ChangeWindowAttributes;
		screen->ChangeWindowAttributes =
		    glamor_change_window_attributes;
351

352
		glamor_priv->saved_procs.copy_window = screen->CopyWindow;
Zhigang Gong's avatar
Zhigang Gong committed
353
		screen->CopyWindow = glamor_copy_window;
354

355
		glamor_priv->saved_procs.bitmap_to_region =
Zhigang Gong's avatar
Zhigang Gong committed
356 357 358
		    screen->BitmapToRegion;
		screen->BitmapToRegion = glamor_bitmap_to_region;
	}
359
#ifdef RENDER
Zhigang Gong's avatar
Zhigang Gong committed
360
	if (flags & GLAMOR_USE_PICTURE_SCREEN) {
361
		glamor_priv->saved_procs.composite = ps->Composite;
Zhigang Gong's avatar
Zhigang Gong committed
362 363
		ps->Composite = glamor_composite;

364
		glamor_priv->saved_procs.trapezoids = ps->Trapezoids;
Zhigang Gong's avatar
Zhigang Gong committed
365 366
		ps->Trapezoids = glamor_trapezoids;

367
		glamor_priv->saved_procs.glyphs = ps->Glyphs;
Zhigang Gong's avatar
Zhigang Gong committed
368 369
		ps->Glyphs = glamor_glyphs;

370
		glamor_priv->saved_procs.triangles = ps->Triangles;
Zhigang Gong's avatar
Zhigang Gong committed
371 372
		ps->Triangles = glamor_triangles;

373
		glamor_priv->saved_procs.addtraps = ps->AddTraps;
374 375
		ps->AddTraps = glamor_add_traps;

376
		glamor_priv->saved_procs.unrealize_glyph = ps->UnrealizeGlyph;
Zhigang Gong's avatar
Zhigang Gong committed
377 378
		ps->UnrealizeGlyph = glamor_glyph_unrealize;
	}
379
	glamor_priv->saved_procs.create_picture = ps->CreatePicture;
380
	ps->CreatePicture = glamor_create_picture;
Zhigang Gong's avatar
Zhigang Gong committed
381

382
	glamor_priv->saved_procs.destroy_picture = ps->DestroyPicture;
383
	ps->DestroyPicture = glamor_destroy_picture;
Zhigang Gong's avatar
Zhigang Gong committed
384
	glamor_init_composite_shaders(screen);
385
#endif
386
	glamor_init_pixmap_fbo(screen);
Zhigang Gong's avatar
Zhigang Gong committed
387 388 389 390 391
	glamor_init_solid_shader(screen);
	glamor_init_tile_shader(screen);
	glamor_init_putimage_shaders(screen);
	glamor_init_finish_access_shaders(screen);
	glamor_pixmap_init(screen);
392

393
#ifdef GLAMOR_GLES2
Zhigang Gong's avatar
Zhigang Gong committed
394
	glamor_priv->gl_flavor = GLAMOR_GL_ES2;
395
#else
Zhigang Gong's avatar
Zhigang Gong committed
396
	glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP;
397
#endif
398
	glamor_priv->flags = flags;
399

Zhigang Gong's avatar
Zhigang Gong committed
400
	return TRUE;
401

Zhigang Gong's avatar
Zhigang Gong committed
402 403 404 405 406
      fail:
	free(glamor_priv);
	dixSetPrivate(&screen->devPrivates, glamor_screen_private_key,
		      NULL);
	return FALSE;
Eric Anholt's avatar
Eric Anholt committed
407 408
}

409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
static void
glamor_release_screen_priv(ScreenPtr screen)
{
	glamor_screen_private *glamor_priv;

	glamor_priv = glamor_get_screen_private(screen);
#ifdef RENDER
	glamor_fini_composite_shaders(screen);
#endif
	glamor_fini_pixmap_fbo(screen);
	glamor_fini_solid_shader(screen);
	glamor_fini_tile_shader(screen);
	glamor_fini_putimage_shaders(screen);
	glamor_fini_finish_access_shaders(screen);
	glamor_pixmap_fini(screen);
	free(glamor_priv);

	dixSetPrivate(&screen->devPrivates, glamor_screen_private_key,
		      NULL);
}

Zhigang Gong's avatar
Zhigang Gong committed
430
Bool
431
glamor_close_screen(int idx, ScreenPtr screen)
432
{
433 434 435 436 437
	glamor_screen_private *glamor_priv;
	int flags;

	glamor_priv = glamor_get_screen_private(screen);
	flags = glamor_priv->flags;
438
#ifdef RENDER
Zhigang Gong's avatar
Zhigang Gong committed
439
	PictureScreenPtr ps = GetPictureScreenIfSet(screen);
440
#endif
Zhigang Gong's avatar
Zhigang Gong committed
441
	glamor_glyphs_fini(screen);
442 443 444 445 446 447 448 449 450 451 452 453
	if (flags & GLAMOR_USE_SCREEN) {

		screen->CloseScreen = glamor_priv->saved_procs.close_screen;
		screen->CreateGC = glamor_priv->saved_procs.create_gc;
		screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap;
		screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap;
		screen->GetSpans = glamor_priv->saved_procs.get_spans;
		screen->ChangeWindowAttributes =
		    glamor_priv->saved_procs.change_window_attributes;
		screen->CopyWindow = glamor_priv->saved_procs.copy_window;
		screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region;
	}
454
#ifdef RENDER
455 456
	if (ps && (flags & GLAMOR_USE_PICTURE_SCREEN)) {

457 458 459 460 461
		ps->Composite = glamor_priv->saved_procs.composite;
		ps->Trapezoids = glamor_priv->saved_procs.trapezoids;
		ps->Glyphs = glamor_priv->saved_procs.glyphs;
		ps->Triangles = glamor_priv->saved_procs.triangles;
		ps->CreatePicture = glamor_priv->saved_procs.create_picture;
Zhigang Gong's avatar
Zhigang Gong committed
462
	}
463
#endif
464
	glamor_release_screen_priv(screen);
Zhigang Gong's avatar
Zhigang Gong committed
465

466 467 468 469
	if (flags & GLAMOR_USE_SCREEN)
		return screen->CloseScreen(idx, screen);
	else
		return TRUE;
470 471
}

472

473 474 475
void
glamor_fini(ScreenPtr screen)
{
Zhigang Gong's avatar
Zhigang Gong committed
476
	/* Do nothing currently. */
477
}