glamor.c 13.2 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 81
_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
82
_X_EXPORT void
83 84
glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex)
{
Zhigang Gong's avatar
Zhigang Gong committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
	ScreenPtr screen = pixmap->drawable.pScreen;
	glamor_pixmap_private *pixmap_priv;
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(screen);

	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->tex = tex;

	/* Create a framebuffer object wrapping the texture so that we can render
	 * to it.
	 */
	pixmap_priv->gl_fbo = 1;
	if (tex != 0) {
		glamor_pixmap_ensure_fb(pixmap);
		pixmap_priv->gl_tex = 1;
	} else {
		pixmap_priv->fb = 0;
		pixmap_priv->gl_tex = 0;
	}

	if (pixmap->devKind == 0)
		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0,
					   (((w *
					      pixmap->drawable.
					      bitsPerPixel + 7) / 8) +
					    3) & ~3, NULL);
119 120
}

121 122
/* Set screen pixmap. If tex equal to 0, means it is called from ephyr. */
void
Zhigang Gong's avatar
Zhigang Gong committed
123 124
glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h,
				 unsigned int tex)
125
{
Zhigang Gong's avatar
Zhigang Gong committed
126 127 128 129 130 131 132 133
	PixmapPtr pixmap = screen->GetScreenPixmap(screen);
	glamor_pixmap_private *pixmap_priv;
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(screen);

	glamor_set_pixmap_texture(pixmap, w, h, tex);
	pixmap_priv = glamor_get_pixmap_private(pixmap);
	glamor_priv->screen_fbo = pixmap_priv->fb;
134 135
}

136
PixmapPtr
137
glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
Eric Anholt's avatar
Eric Anholt committed
138
		     unsigned int usage)
139
{
Zhigang Gong's avatar
Zhigang Gong committed
140 141 142
	PixmapPtr pixmap;
	GLenum format;
	GLuint tex;
143
	glamor_pixmap_type_t type = GLAMOR_TEXTURE_ONLY;
Zhigang Gong's avatar
Zhigang Gong committed
144 145 146 147 148 149 150 151 152 153 154 155
	glamor_pixmap_private *pixmap_priv;
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(screen);
	glamor_gl_dispatch *dispatch = &glamor_priv->dispatch;
	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. */
156
		type = GLAMOR_MEMORY;
Zhigang Gong's avatar
Zhigang Gong committed
157 158 159 160 161 162
		pixmap = fbCreatePixmap(screen, w, h, depth, usage);
		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0,
					   (((w *
					      pixmap->
					      drawable.bitsPerPixel +
					      7) / 8) + 3) & ~3, NULL);
163
#if 0
Zhigang Gong's avatar
Zhigang Gong committed
164 165 166 167
		if (usage != GLAMOR_CREATE_PIXMAP_CPU)
			glamor_fallback("choose cpu memory for pixmap %p ,"
					" %d x %d depth %d\n", pixmap, w,
					h, depth);
168
#endif
Zhigang Gong's avatar
Zhigang Gong committed
169 170
	} else
		pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
171

Zhigang Gong's avatar
Zhigang Gong committed
172 173 174 175 176
	pixmap_priv = calloc(1, sizeof(*pixmap_priv));
	dixSetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key,
		      pixmap_priv);
	pixmap_priv->container = pixmap;
	pixmap_priv->glamor_priv = glamor_priv;
Eric Anholt's avatar
Eric Anholt committed
177

178 179
	pixmap_priv->type = type;
	if (w == 0 || h == 0 || type == GLAMOR_MEMORY)
Zhigang Gong's avatar
Zhigang Gong committed
180
		return pixmap;
181

Zhigang Gong's avatar
Zhigang Gong committed
182
	switch (depth) {
Zhigang Gong's avatar
Zhigang Gong committed
183
#if 0
Zhigang Gong's avatar
Zhigang Gong committed
184 185 186
	case 8:
		format = GL_ALPHA;
		break;
Zhigang Gong's avatar
Zhigang Gong committed
187
#endif
Zhigang Gong's avatar
Zhigang Gong committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
	case 24:
		format = GL_RGB;
		break;
	default:
		format = GL_RGBA;
		break;
	}

	/* Create the texture used to store the pixmap's data. */
	dispatch->glGenTextures(1, &tex);
	dispatch->glBindTexture(GL_TEXTURE_2D, tex);
	dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
				  GL_NEAREST);
	dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
				  GL_NEAREST);
	dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format,
			       GL_UNSIGNED_BYTE, NULL);

	glamor_set_pixmap_texture(pixmap, w, h, tex);
207

Zhigang Gong's avatar
Zhigang Gong committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
	return pixmap;
}

void
glamor_destroy_textured_pixmap(PixmapPtr pixmap)
{
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(pixmap->drawable.pScreen);
	glamor_gl_dispatch *dispatch = &glamor_priv->dispatch;
	if (pixmap->refcnt == 1) {
		glamor_pixmap_private *pixmap_priv =
		    glamor_get_pixmap_private(pixmap);
		if (pixmap_priv != NULL) {
			if (pixmap_priv->fb)
				dispatch->glDeleteFramebuffers(1,
							       &pixmap_priv->fb);
			if (pixmap_priv->tex)
				dispatch->glDeleteTextures(1,
							   &pixmap_priv->tex);
			if (pixmap_priv->pbo)
				dispatch->glDeleteBuffers(1,
							  &pixmap_priv->pbo);
			free(pixmap_priv);
		}
	}
233 234
}

235
Bool
236 237
glamor_destroy_pixmap(PixmapPtr pixmap)
{
Zhigang Gong's avatar
Zhigang Gong committed
238 239 240 241 242 243 244 245 246 247 248 249
	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;

	dispatch->glFlush();
250
}
Eric Anholt's avatar
Eric Anholt committed
251

252
static void
Zhigang Gong's avatar
Zhigang Gong committed
253 254
_glamor_block_handler(void *data, OSTimePtr timeout,
		      void *last_select_mask)
255
{
Zhigang Gong's avatar
Zhigang Gong committed
256 257
	glamor_gl_dispatch *dispatch = data;
	dispatch->glFlush();
258 259 260
}

static void
Zhigang Gong's avatar
Zhigang Gong committed
261
_glamor_wakeup_handler(void *data, int result, void *last_select_mask)
262 263 264
{
}

Zhigang Gong's avatar
Zhigang Gong committed
265
static void
266 267
glamor_set_debug_level(int *debug_level)
{
Zhigang Gong's avatar
Zhigang Gong committed
268 269 270 271 272 273
	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;
274 275 276 277
}

int glamor_debug_level;

Eric Anholt's avatar
Eric Anholt committed
278 279
/** Set up glamor for an already-configured GL context. */
Bool
280
glamor_init(ScreenPtr screen, unsigned int flags)
Eric Anholt's avatar
Eric Anholt committed
281
{
Zhigang Gong's avatar
Zhigang Gong committed
282 283
	glamor_screen_private *glamor_priv;
	int gl_version;
284

285
#ifdef RENDER
Zhigang Gong's avatar
Zhigang Gong committed
286
	PictureScreenPtr ps = GetPictureScreenIfSet(screen);
287
#endif
Zhigang Gong's avatar
Zhigang Gong committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
	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();
321

322
#ifndef GLAMOR_GLES2
Zhigang Gong's avatar
Zhigang Gong committed
323 324 325 326
	if (gl_version < GLAMOR_GL_VERSION_ENCODE(1, 3)) {
		ErrorF("Require OpenGL version 1.3 or latter.\n");
		goto fail;
	}
327
#else
Zhigang Gong's avatar
Zhigang Gong committed
328 329 330 331
	if (gl_version < GLAMOR_GL_VERSION_ENCODE(2, 0)) {
		ErrorF("Require Open GLES2.0 or latter.\n");
		goto fail;
	}
332
#endif
333

Zhigang Gong's avatar
Zhigang Gong committed
334 335
	glamor_gl_dispatch_init(screen, &glamor_priv->dispatch,
				gl_version);
Zhigang Gong's avatar
Zhigang Gong committed
336 337

#ifdef GLAMOR_GLES2
Zhigang Gong's avatar
Zhigang Gong committed
338 339 340 341
	if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) {
		ErrorF("GL_EXT_texture_format_BGRA8888 required\n");
		goto fail;
	}
342 343
#endif

Zhigang Gong's avatar
Zhigang Gong committed
344 345 346 347 348 349
	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);
350

Zhigang Gong's avatar
Zhigang Gong committed
351
	glamor_set_debug_level(&glamor_debug_level);
352

Zhigang Gong's avatar
Zhigang Gong committed
353
	if (flags & GLAMOR_USE_SCREEN) {
354 355 356 357 358 359 360
		if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler,
						    _glamor_wakeup_handler,
						    (void *)
						    &glamor_priv->dispatch)) {
			goto fail;
		}

Zhigang Gong's avatar
Zhigang Gong committed
361 362
		glamor_priv->saved_close_screen = screen->CloseScreen;
		screen->CloseScreen = glamor_close_screen;
363

Zhigang Gong's avatar
Zhigang Gong committed
364 365
		glamor_priv->saved_create_gc = screen->CreateGC;
		screen->CreateGC = glamor_create_gc;
366

Zhigang Gong's avatar
Zhigang Gong committed
367 368
		glamor_priv->saved_create_pixmap = screen->CreatePixmap;
		screen->CreatePixmap = glamor_create_pixmap;
369

Zhigang Gong's avatar
Zhigang Gong committed
370 371
		glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap;
		screen->DestroyPixmap = glamor_destroy_pixmap;
372

Zhigang Gong's avatar
Zhigang Gong committed
373 374
		glamor_priv->saved_get_spans = screen->GetSpans;
		screen->GetSpans = glamor_get_spans;
375

Zhigang Gong's avatar
Zhigang Gong committed
376
		glamor_priv->saved_get_image = screen->GetImage;
377
		screen->GetImage = glamor_get_image;
378

Zhigang Gong's avatar
Zhigang Gong committed
379 380 381 382
		glamor_priv->saved_change_window_attributes =
		    screen->ChangeWindowAttributes;
		screen->ChangeWindowAttributes =
		    glamor_change_window_attributes;
383

Zhigang Gong's avatar
Zhigang Gong committed
384 385
		glamor_priv->saved_copy_window = screen->CopyWindow;
		screen->CopyWindow = glamor_copy_window;
386

Zhigang Gong's avatar
Zhigang Gong committed
387 388 389 390
		glamor_priv->saved_bitmap_to_region =
		    screen->BitmapToRegion;
		screen->BitmapToRegion = glamor_bitmap_to_region;
	}
391
#ifdef RENDER
Zhigang Gong's avatar
Zhigang Gong committed
392 393 394 395 396 397 398 399 400 401 402 403 404
	if (flags & GLAMOR_USE_PICTURE_SCREEN) {
		glamor_priv->saved_composite = ps->Composite;
		ps->Composite = glamor_composite;

		glamor_priv->saved_trapezoids = ps->Trapezoids;
		ps->Trapezoids = glamor_trapezoids;

		glamor_priv->saved_glyphs = ps->Glyphs;
		ps->Glyphs = glamor_glyphs;

		glamor_priv->saved_triangles = ps->Triangles;
		ps->Triangles = glamor_triangles;

405 406 407
		glamor_priv->saved_addtraps = ps->AddTraps;
		ps->AddTraps = glamor_add_traps;

Zhigang Gong's avatar
Zhigang Gong committed
408 409 410
		glamor_priv->saved_unrealize_glyph = ps->UnrealizeGlyph;
		ps->UnrealizeGlyph = glamor_glyph_unrealize;
	}
411 412
	glamor_priv->saved_create_picture = ps->CreatePicture;
	ps->CreatePicture = glamor_create_picture;
Zhigang Gong's avatar
Zhigang Gong committed
413

414 415
	glamor_priv->saved_destroy_picture = ps->DestroyPicture;
	ps->DestroyPicture = glamor_destroy_picture;
Zhigang Gong's avatar
Zhigang Gong committed
416
	glamor_init_composite_shaders(screen);
417
#endif
Zhigang Gong's avatar
Zhigang Gong committed
418 419 420 421 422
	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);
423

424
#ifdef GLAMOR_GLES2
Zhigang Gong's avatar
Zhigang Gong committed
425
	glamor_priv->gl_flavor = GLAMOR_GL_ES2;
426
#else
Zhigang Gong's avatar
Zhigang Gong committed
427
	glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP;
428 429
#endif

Zhigang Gong's avatar
Zhigang Gong committed
430
	return TRUE;
431

Zhigang Gong's avatar
Zhigang Gong committed
432 433 434 435 436
      fail:
	free(glamor_priv);
	dixSetPrivate(&screen->devPrivates, glamor_screen_private_key,
		      NULL);
	return FALSE;
Eric Anholt's avatar
Eric Anholt committed
437 438
}

Zhigang Gong's avatar
Zhigang Gong committed
439
Bool
440
glamor_close_screen(int idx, ScreenPtr screen)
441
{
Zhigang Gong's avatar
Zhigang Gong committed
442 443
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(screen);
444
#ifdef RENDER
Zhigang Gong's avatar
Zhigang Gong committed
445
	PictureScreenPtr ps = GetPictureScreenIfSet(screen);
446
#endif
Zhigang Gong's avatar
Zhigang Gong committed
447 448 449 450 451 452 453 454 455 456
	glamor_glyphs_fini(screen);
	screen->CloseScreen = glamor_priv->saved_close_screen;
	screen->CreateGC = glamor_priv->saved_create_gc;
	screen->CreatePixmap = glamor_priv->saved_create_pixmap;
	screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap;
	screen->GetSpans = glamor_priv->saved_get_spans;
	screen->ChangeWindowAttributes =
	    glamor_priv->saved_change_window_attributes;
	screen->CopyWindow = glamor_priv->saved_copy_window;
	screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region;
457
#ifdef RENDER
Zhigang Gong's avatar
Zhigang Gong committed
458 459 460 461 462 463 464
	if (ps) {
		ps->Composite = glamor_priv->saved_composite;
		ps->Trapezoids = glamor_priv->saved_trapezoids;
		ps->Glyphs = glamor_priv->saved_glyphs;
		ps->Triangles = glamor_priv->saved_triangles;
		ps->CreatePicture = glamor_priv->saved_create_picture;
	}
465
#endif
Zhigang Gong's avatar
Zhigang Gong committed
466 467 468 469 470
	if (glamor_priv->vb)
		free(glamor_priv->vb);
	free(glamor_priv);
	return screen->CloseScreen(idx, screen);

471 472 473 474 475
}

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