summaryrefslogtreecommitdiff
path: root/Build/source/libs/cairo/cairo-1.12.8/src/drm/cairo-drm-i915-shader.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/cairo/cairo-1.12.8/src/drm/cairo-drm-i915-shader.c')
-rw-r--r--Build/source/libs/cairo/cairo-1.12.8/src/drm/cairo-drm-i915-shader.c2893
1 files changed, 0 insertions, 2893 deletions
diff --git a/Build/source/libs/cairo/cairo-1.12.8/src/drm/cairo-drm-i915-shader.c b/Build/source/libs/cairo/cairo-1.12.8/src/drm/cairo-drm-i915-shader.c
deleted file mode 100644
index a1911d0a4e1..00000000000
--- a/Build/source/libs/cairo/cairo-1.12.8/src/drm/cairo-drm-i915-shader.c
+++ /dev/null
@@ -1,2893 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * Contributor(s):
- * Chris Wilson <chris@chris-wilson.co.uk>
- */
-
-#include "cairoint.h"
-
-#include "cairo-error-private.h"
-#include "cairo-drm-i915-private.h"
-#include "cairo-surface-offset-private.h"
-#include "cairo-surface-subsurface-private.h"
-#include "cairo-surface-snapshot-private.h"
-
-#if 0
-static cairo_status_t
-i915_packed_pixel_surface_finish (void *abstract_surface)
-{
- i915_packed_pixel_surface_t *surface = abstract_surface;
- i915_device_t *device;
-
- device = i915_device_acquire (&surface->device->intel.base);
-
- intel_bo_destroy (&device->intel, surface->bo);
-
- if (surface->is_current_texture) {
- if (surface->is_current_texture & CURRENT_SOURCE)
- device->current_source = NULL;
- if (surface->is_current_texture & CURRENT_MASK)
- device->current_mask = NULL;
- device->current_n_samplers = 0;
- }
-
- i915_device_release (device);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static const cairo_surface_backend_t i915_packed_pixel_surface_backend = {
- I915_PACKED_PIXEL_SURFACE_TYPE,
- i915_packed_pixel_surface_finish,
-};
-
-static cairo_surface_t *
-i915_packed_pixel_surface_create (i915_device_t *device,
- i915_packed_pixel_t pixel,
- const uint8_t *data,
- uint32_t length,
- uint32_t width, uint32_t height)
-{
- i915_packed_pixel_surface_t *surface;
- cairo_content_t content;
- uint32_t tiling, size;
- uint32_t stride, half_stride;
- uint32_t i;
-
- if (width > 2048 || height > 2048)
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
-
- surface = malloc (sizeof (i915_packed_pixel_surface_t));
- if (unlikely (surface == NULL))
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
- tiling = I915_TILING_NONE; /* XXX */
- half_stride = stride = i915_tiling_stride (tiling, width/2);
- if (stride < width)
- stride *= 2 ;
- height = i915_tiling_height (tiling, height);
-
- switch (surface->pixel = pixel) {
- case YUV_I420:
- content = CAIRO_CONTENT_COLOR;
-
- surface->offset[0] = 0;
- surface->width[0] = width;
- surface->height[0] = height;
- surface->stride[0] = stride;
- surface->map0[0] = MAPSURF_8BIT | MT_8BIT_I8 | MS3_tiling (tiling);
- surface->map0[0] |= ((height - 1) << MS3_HEIGHT_SHIFT) |
- ((width - 1) << MS3_WIDTH_SHIFT);
- surface->map1[0] = (stride / 4 - 1) << MS4_PITCH_SHIFT;
-
- surface->offset[1] = stride * height;
- surface->width[1] = width / 2;
- surface->height[1] = height / 2;
- surface->stride[1] = half_stride;
- surface->map0[1] = MAPSURF_8BIT | MT_8BIT_I8 | MS3_tiling (tiling);
- surface->map0[1] |= ((height/2 - 1) << MS3_HEIGHT_SHIFT) |
- ((width/2 - 1) << MS3_WIDTH_SHIFT);
- surface->map1[1] = (half_stride / 4 - 1) << MS4_PITCH_SHIFT;
-
- if (width < half_stride) {
- surface->offset[2] = stride * height + half_stride / 2;
- size = stride * height + half_stride * height / 2;
- } else {
- surface->offset[2] = stride * height + half_stride * height / 2;
- size = stride * height + half_stride * height;
- }
- surface->width[2] = width / 2;
- surface->height[2] = height / 2;
- surface->stride[2] = half_stride;
- surface->map0[2] = MAPSURF_8BIT | MT_8BIT_I8 | MS3_tiling (tiling);
- surface->map0[2] |= ((height/2 - 1) << MS3_HEIGHT_SHIFT) |
- ((width/2 - 1) << MS3_WIDTH_SHIFT);
- surface->map1[2] = (half_stride / 4 - 1) << MS4_PITCH_SHIFT;
- break;
-
- case NONE:
- case YUV_YV12:
- case YUV_YUY2:
- case YUV_UYVY:
- ASSERT_NOT_REACHED;
- break;
- }
-
- _cairo_surface_init (&surface->base,
- &i915_packed_pixel_surface_backend,
- content);
-
- surface->bo = intel_bo_create (&device->intel, size, FALSE);
- assert (surface->bo->tiling == I915_TILING_NONE);
- if (unlikely (surface->bo == NULL)) {
- free (surface);
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- if (tiling == I915_TILING_NONE) {
- intel_bo_t *bo = surface->bo;
- uint32_t dst;
- int uv;
-
- dst = surface->offset[0];
- if (width == stride) {
- size = stride * height;
- intel_bo_write (&device->intel, bo, dst, size, data);
- data += size;
- } else {
- for (i = 0; i < height; i++) {
- intel_bo_write (&device->intel, bo, dst, width, data);
- dst += stride;
- data += width;
- }
- }
-
- for (uv = 1; uv <= 2; uv++) {
- dst = surface->offset[uv];
- if (width / 2 == half_stride) {
- size = half_stride * height / 2;
- intel_bo_write (&device->intel, bo, dst, size, data);
- data += size;
- } else {
- size = width / 2;
- for (i = 0; i < height / 2; i++) {
- intel_bo_write (&device->intel, bo, dst, size, data);
- dst += half_stride;
- data += size;
- }
- }
- }
- } else {
- uint8_t *dst, *base;
-
- base = intel_bo_map (&device->intel, surface->bo);
-
- dst = base + surface->offset[0];
- if (width == stride) {
- size = stride * height;
- memcpy (dst, data, size);
- data += size;
- } else {
- for (i = 0; i < height; i++) {
- memcpy (dst, data, width);
- dst += stride;
- data += width;
- }
- }
-
- dst = base + surface->offset[1];
- if (width / 2 == half_stride) {
- size = half_stride * height / 2;
- memcpy (dst, data, size);
- data += size;
- } else {
- size = width / 2;
- for (i = 0; i < height / 2; i++) {
- memcpy (dst, data, size);
- dst += half_stride;
- data += size;
- }
- }
-
- dst = base + surface->offset[2];
- if (width / 2 == half_stride) {
- size = half_stride * height / 2;
- memcpy (dst, data, size);
- data += size;
- } else {
- size = width / 2;
- for (i = 0; i < height / 2; i++) {
- memcpy (dst, data, size);
- dst += half_stride;
- data += size;
- }
- }
- }
-
- surface->device = device;
- surface->is_current_texture = 0;
-
- return &surface->base;
-}
-
-static cairo_int_status_t
-i915_clone_yuv (i915_surface_t *surface,
- cairo_surface_t *source,
- int width, int height,
- cairo_surface_t **clone_out)
-{
- const uint8_t *mime_data = NULL;
- unsigned int mime_data_length;
- cairo_surface_t *clone;
-
- cairo_surface_get_mime_data (source, "video/x-raw-yuv/i420",
- &mime_data, &mime_data_length);
- if (mime_data == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- clone =
- i915_packed_pixel_surface_create ((i915_device_t *) surface->base.device,
- YUV_I420,
- mime_data, mime_data_length,
- width, height);
- if (clone == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- if (unlikely (clone->status))
- return clone->status;
-
- *clone_out = clone;
- return CAIRO_STATUS_SUCCESS;
-}
-#endif
-
-/* Max instruction count: 4 */
-static void
-i915_shader_linear_color (i915_device_t *device,
- enum i915_shader_linear_mode mode,
- int in, int c0, int c1, int out)
-{
- int tmp = FS_U0;
-
- switch (mode) {
- case LINEAR_TEXTURE:
- ASSERT_NOT_REACHED;
- case LINEAR_NONE:
- tmp = in;
- break;
-
- case LINEAR_REPEAT:
- i915_fs_frc (tmp, i915_fs_operand (in, X, X, X, X));
- break;
-#if 0
- case LINEAR_REFLECT:
- /* XXX needs an extra constant: C2 [0.5, 2.0, x, x] */
- i915_fs_mul (tmp, in, 0.5);
- i915_fs_frc (tmp, i915_fs_operand_reg (tmp));
- i915_fs_mul (tmp, tmp, 2.0);
- i915_fs_add (tmp, i915_fs_operand_one (),
- i915_fs_operand_reg_negate (tmp));
- i915_fs_cmp (tmp,
- i915_fs_operand_reg (tmp),
- i915_fs_operand_reg (tmp),
- i915_fs_operand_reg_negate (tmp));
- i915_fs_add (tmp, i915_fs_operand_one (),
- i915_fs_operand_reg_negate (tmp));
-#endif
- case LINEAR_PAD:
- i915_fs_max (tmp,
- i915_fs_operand_zero (),
- i915_fs_operand (in, X, X, X, X));
- i915_fs_min (tmp,
- i915_fs_operand_one (),
- i915_fs_operand_reg (tmp));
- break;
- }
-
- /* interpolate */
- i915_fs_mad (out, 0,
- i915_fs_operand (tmp, NEG_X, NEG_X, NEG_X, NEG_X),
- i915_fs_operand_reg (c0),
- i915_fs_operand_reg (c0));
- i915_fs_mad (out, 0,
- i915_fs_operand (tmp, X, X, X, X),
- i915_fs_operand_reg (c1),
- i915_fs_operand_reg (out));
-}
-
-static void
-i915_shader_radial_init (struct i915_shader_radial *r,
- const cairo_radial_pattern_t *radial)
-{
- double dx, dy, dr, r1;
-
- dx = radial->cd2.center.x - radial->cd1.center.x;
- dy = radial->cd2.center.y - radial->cd1.center.y;
- dr = radial->cd2.radius - radial->cd1.radius;
-
- r1 = radial->cd1.radius;
-
- if (radial->cd2.center.x == radial->cd1.center.x &&
- radial->cd2.center.y == radial->cd1.center.y)
- {
- /* XXX dr == 0, meaningless with anything other than PAD */
- r->constants[0] = radial->cd1.center.x / dr;
- r->constants[1] = radial->cd1.center.y / dr;
- r->constants[2] = 1. / dr;
- r->constants[3] = -r1 / dr;
-
- r->constants[4] = 0;
- r->constants[5] = 0;
- r->constants[6] = 0;
- r->constants[7] = 0;
-
- r->base.mode = RADIAL_ONE;
- } else {
- r->constants[0] = -radial->cd1.center.x;
- r->constants[1] = -radial->cd1.center.y;
- r->constants[2] = r1;
- r->constants[3] = -4 * (dx*dx + dy*dy - dr*dr);
-
- r->constants[4] = -2 * dx;
- r->constants[5] = -2 * dy;
- r->constants[6] = -2 * r1 * dr;
- r->constants[7] = 1 / (2 * (dx*dx + dy*dy - dr*dr));
-
- r->base.mode = RADIAL_TWO;
- }
-
- r->base.matrix = radial->base.base.matrix;
-}
-
-/* Max instruction count: 10 */
-static void
-i915_shader_radial_coord (i915_device_t *device,
- enum i915_shader_radial_mode mode,
- int in, int g0, int g1, int out)
-{
- switch (mode) {
- case RADIAL_ONE:
- /*
- pdx = (x - c1x) / dr, pdy = (y - c1y) / dr;
- r² = pdx*pdx + pdy*pdy
- t = r²/sqrt(r²) - r1/dr;
- */
- i915_fs_mad (FS_U0, MASK_X | MASK_Y,
- i915_fs_operand (in, X, Y, ZERO, ZERO),
- i915_fs_operand (g0, Z, Z, ZERO, ZERO),
- i915_fs_operand (g0, NEG_X, NEG_Y, ZERO, ZERO));
- i915_fs_dp2add (FS_U0, MASK_X,
- i915_fs_operand (FS_U0, X, Y, ZERO, ZERO),
- i915_fs_operand (FS_U0, X, Y, ZERO, ZERO),
- i915_fs_operand_zero ());
- i915_fs_rsq (out, MASK_X, i915_fs_operand (FS_U0, X, X, X, X));
- i915_fs_mad (out, MASK_X,
- i915_fs_operand (FS_U0, X, ZERO, ZERO, ZERO),
- i915_fs_operand (out, X, ZERO, ZERO, ZERO),
- i915_fs_operand (g0, W, ZERO, ZERO, ZERO));
- break;
-
- case RADIAL_TWO:
- /*
- pdx = x - c1x, pdy = y - c1y;
- A = dx² + dy² - dr²
- B = -2*(pdx*dx + pdy*dy + r1*dr);
- C = pdx² + pdy² - r1²;
- det = B*B - 4*A*C;
- t = (-B + sqrt (det)) / (2 * A)
- */
-
- /* u0.x = pdx, u0.y = pdy, u[0].z = r1; */
- i915_fs_add (FS_U0,
- i915_fs_operand (in, X, Y, ZERO, ZERO),
- i915_fs_operand (g0, X, Y, Z, ZERO));
- /* u0.x = pdx, u0.y = pdy, u[0].z = r1, u[0].w = B; */
- i915_fs_dp3 (FS_U0, MASK_W,
- i915_fs_operand (FS_U0, X, Y, ONE, ZERO),
- i915_fs_operand (g1, X, Y, Z, ZERO));
- /* u1.x = pdx² + pdy² - r1²; [C] */
- i915_fs_dp3 (FS_U1, MASK_X,
- i915_fs_operand (FS_U0, X, Y, Z, ZERO),
- i915_fs_operand (FS_U0, X, Y, NEG_Z, ZERO));
- /* u1.x = C, u1.y = B, u1.z=-4*A; */
- i915_fs_mov_masked (FS_U1, MASK_Y, i915_fs_operand (FS_U0, W, W, W, W));
- i915_fs_mov_masked (FS_U1, MASK_Z, i915_fs_operand (g0, W, W, W, W));
- /* u1.x = B² - 4*A*C */
- i915_fs_dp2add (FS_U1, MASK_X,
- i915_fs_operand (FS_U1, X, Y, ZERO, ZERO),
- i915_fs_operand (FS_U1, Z, Y, ZERO, ZERO),
- i915_fs_operand_zero ());
- /* out.x = -B + sqrt (B² - 4*A*C),
- * out.y = -B - sqrt (B² - 4*A*C),
- */
- i915_fs_rsq (out, MASK_X, i915_fs_operand (FS_U1, X, X, X, X));
- i915_fs_mad (out, MASK_X | MASK_Y,
- i915_fs_operand (out, X, X, ZERO, ZERO),
- i915_fs_operand (FS_U1, X, NEG_X, ZERO, ZERO),
- i915_fs_operand (FS_U0, NEG_W, NEG_W, ZERO, ZERO));
- /* out.x = (-B + sqrt (B² - 4*A*C)) / (2 * A),
- * out.y = (-B - sqrt (B² - 4*A*C)) / (2 * A)
- */
- i915_fs_mul (out,
- i915_fs_operand (out, X, Y, ZERO, ZERO),
- i915_fs_operand (g1, W, W, ZERO, ZERO));
- /* if (A > 0)
- * out = (-B + sqrt (B² - 4*A*C)) / (2 * A),
- * else
- * out = (-B - sqrt (B² - 4*A*C)) / (2 * A)
- */
- i915_fs_cmp (out,
- i915_fs_operand (g1, W, ZERO, ZERO, ZERO),
- i915_fs_operand (out, X, ZERO, ZERO, ZERO),
- i915_fs_operand (out, Y, ZERO, ZERO, ZERO));
- break;
- }
-}
-
-/* Max instruction count: 7 */
-static inline void
-i915_shader_yuv_color (i915_device_t *device,
- int y, int u, int v,
- int c0, int c1, int c2,
- int out)
-{
- i915_fs_mov_masked (FS_U0, MASK_X, i915_fs_operand_reg (y));
- i915_fs_mov_masked (FS_U0, MASK_Y, i915_fs_operand_reg (u));
- i915_fs_mov_masked (FS_U0, MASK_Z, i915_fs_operand_reg (v));
-
- i915_fs_add (FS_U0,
- i915_fs_operand_reg (FS_U0),
- i915_fs_operand_reg (c0));
- i915_fs_dp3 (out, MASK_X,
- i915_fs_operand_reg (FS_U0),
- i915_fs_operand (c1, X, ZERO, Y, ZERO));
- i915_fs_dp3 (out, MASK_Z,
- i915_fs_operand_reg (FS_U0),
- i915_fs_operand (c1, Z, W, ZERO, ZERO));
- i915_fs_dp3 (out, MASK_Y,
- i915_fs_operand_reg (FS_U0),
- i915_fs_operand_reg (c2));
-}
-
-static inline uint32_t
-i915_shader_channel_key (const union i915_shader_channel *channel)
-{
- return (channel->type.fragment & 0x0f) | (channel->base.mode << FS_DETAILS_SHIFT);
-}
-
-static uint32_t
-i915_shader_channel_get_num_tex_coords (const union i915_shader_channel *channel)
-{
- switch (channel->type.fragment) {
- default:
- case FS_ZERO:
- case FS_ONE:
- case FS_CONSTANT:
- case FS_PURE:
- case FS_DIFFUSE:
- return 0;
-
- case FS_LINEAR:
- case FS_RADIAL:
- case FS_TEXTURE:
- case FS_SPANS:
- case FS_YUV:
- return 1;
- }
-}
-
-static uint32_t
-i915_shader_get_num_tex_coords (const i915_shader_t *shader)
-{
- uint32_t num_tex_coords;
-
- num_tex_coords = 0;
-
- num_tex_coords += i915_shader_channel_get_num_tex_coords (&shader->source);
- num_tex_coords += i915_shader_channel_get_num_tex_coords (&shader->mask);
- num_tex_coords += i915_shader_channel_get_num_tex_coords (&shader->clip);
- num_tex_coords += i915_shader_channel_get_num_tex_coords (&shader->dst);
-
- return num_tex_coords;
-}
-
-#define i915_fs_operand_impure(reg, channel, pure) \
- (reg | \
- (((pure & (1 << 0)) ? channel##_CHANNEL_VAL : ZERO_CHANNEL_VAL) << X_CHANNEL_SHIFT) | \
- (((pure & (1 << 1)) ? channel##_CHANNEL_VAL : ZERO_CHANNEL_VAL) << Y_CHANNEL_SHIFT) | \
- (((pure & (1 << 2)) ? channel##_CHANNEL_VAL : ZERO_CHANNEL_VAL) << Z_CHANNEL_SHIFT) | \
- (((pure & (1 << 3)) ? channel##_CHANNEL_VAL : ZERO_CHANNEL_VAL) << W_CHANNEL_SHIFT))
-
-#define i915_fs_operand_pure(pure) \
- (FS_R0 | \
- (((pure & (1 << 0)) ? ONE_CHANNEL_VAL : ZERO_CHANNEL_VAL) << X_CHANNEL_SHIFT) | \
- (((pure & (1 << 1)) ? ONE_CHANNEL_VAL : ZERO_CHANNEL_VAL) << Y_CHANNEL_SHIFT) | \
- (((pure & (1 << 2)) ? ONE_CHANNEL_VAL : ZERO_CHANNEL_VAL) << Z_CHANNEL_SHIFT) | \
- (((pure & (1 << 3)) ? ONE_CHANNEL_VAL : ZERO_CHANNEL_VAL) << W_CHANNEL_SHIFT))
-
-static void
-i915_set_shader_program (i915_device_t *device,
- const i915_shader_t *shader)
-{
- uint32_t num_tex_coords;
- uint32_t num_samplers;
- uint32_t n;
- uint32_t texture_offset = 0;
- uint32_t constant_offset = 0;
- uint32_t sampler_offset = 0;
- uint32_t source_reg;
- uint32_t source_pure;
- uint32_t mask_reg;
- uint32_t out_reg;
- uint32_t dest_reg;
- FS_LOCALS;
-
- n = (i915_shader_channel_key (&shader->source) << 0) |
- (i915_shader_channel_key (&shader->mask) << 8) |
- (i915_shader_channel_key (&shader->clip) << 16) |
- (shader->op << 24) |
- ((shader->opacity < 1.) << 30) |
- (((shader->content & CAIRO_CONTENT_ALPHA) == CAIRO_CONTENT_ALPHA) << 31);
- if (n == device->current_program)
- return;
- device->current_program = n;
-
- FS_BEGIN ();
-
- if (shader->source.type.fragment == FS_ZERO) {
- if (shader->clip.type.fragment == FS_TEXTURE) {
- /* XXX need_combine */
- assert (shader->mask.type.fragment == (i915_fragment_shader_t) -1);
- i915_fs_dcl (FS_T0);
- i915_fs_texld (FS_U0, FS_S0, FS_T0);
- if ((shader->content & CAIRO_CONTENT_COLOR) == 0)
- i915_fs_mov (FS_OC, i915_fs_operand (FS_U0, W, W, W, W));
- else
- i915_fs_mov (FS_OC, i915_fs_operand (FS_U0, ZERO, ZERO, ZERO, W));
- } else {
- i915_fs_mov (FS_OC, i915_fs_operand_zero ());
- }
-
- FS_END ();
- return;
- }
-
- num_tex_coords = i915_shader_get_num_tex_coords (shader);
- for (n = 0; n < num_tex_coords; n++)
- i915_fs_dcl (FS_T0 + n);
-
- num_samplers =
- shader->source.base.n_samplers +
- shader->mask.base.n_samplers +
- shader->clip.base.n_samplers +
- shader->dst.base.n_samplers;
- for (n = 0; n < num_samplers; n++)
- i915_fs_dcl (FS_S0 + n);
-
- source_reg = ~0;
- source_pure = 0;
- out_reg = FS_R0;
- if (! shader->need_combine &&
- shader->mask.type.fragment == (i915_fragment_shader_t) -1 &&
- shader->clip.type.fragment != FS_TEXTURE &&
- shader->content != CAIRO_CONTENT_ALPHA)
- {
- out_reg = FS_OC;
- }
-
- switch (shader->source.type.fragment) {
- default:
- case FS_ZERO:
- case FS_SPANS:
- ASSERT_NOT_REACHED;
-
- case FS_PURE:
- source_pure = shader->source.solid.pure;
- case FS_ONE:
- break;
-
- case FS_CONSTANT:
- source_reg = FS_C0;
- constant_offset += 1;
- break;
-
- case FS_DIFFUSE:
- i915_fs_dcl (FS_T8);
- source_reg = FS_T8;
- break;
-
- case FS_LINEAR:
- i915_shader_linear_color (device, shader->source.base.mode,
- FS_T0, /* input */
- FS_C0, FS_C1, /* colour ramp */
- FS_U3); /* unpremultiplied output */
- /* XXX can we defer premultiplication? */
- i915_fs_mul (out_reg,
- i915_fs_operand_reg (FS_U3),
- i915_fs_operand (FS_U3, W, W, W, ONE));
-
- constant_offset += 2;
- texture_offset += 1;
- source_reg = out_reg;
- break;
-
- case FS_RADIAL:
- i915_shader_radial_coord (device, shader->source.base.mode,
- FS_T0, /* input */
- FS_C0, FS_C1, /* gradient constants */
- FS_R0); /* coordinate */
-
- i915_fs_texld (out_reg, FS_S0, FS_R0);
- constant_offset += 2;
- texture_offset += 1;
- sampler_offset += 1;
- source_reg = out_reg;
- break;
-
- case FS_TEXTURE:
- i915_fs_texld (out_reg, FS_S0, FS_T0);
- texture_offset += 1;
- sampler_offset += 1;
- source_reg = out_reg;
- break;
-
- case FS_YUV:
- /* Load samplers to temporaries. */
- i915_fs_texld (FS_R0, FS_S0, FS_T0);
- i915_fs_texld (FS_R1, FS_S1, FS_T0);
- i915_fs_texld (FS_R2, FS_S2, FS_T0);
-
- i915_shader_yuv_color (device,
- FS_R0, FS_R1, FS_R2, /* y, u, v */
- FS_C0, FS_C1, FS_C2, /* coefficients */
- out_reg);
-
- constant_offset += 3;
- texture_offset += 1;
- sampler_offset += 3;
- source_reg = out_reg;
- break;
- }
-
- mask_reg = ~0;
- switch (shader->mask.type.fragment) {
- case FS_PURE:
- case FS_ZERO:
- case FS_YUV:
- case FS_DIFFUSE:
- ASSERT_NOT_REACHED;
- case FS_ONE:
- default:
- break;
-
- case FS_SPANS:
- mask_reg = FS_T0 + texture_offset;
- texture_offset += 1;
- break;
-
- case FS_CONSTANT:
- mask_reg = FS_C0 + constant_offset;
- constant_offset += 1;
- break;
-
- case FS_LINEAR:
- i915_shader_linear_color (device, shader->mask.base.mode,
- FS_T0 + texture_offset, /* input */
- FS_C0 + constant_offset,
- FS_C0 + constant_offset + 1, /* colour ramp */
- FS_R1); /* unpremultiplied output */
- constant_offset += 2;
- texture_offset += 1;
- mask_reg = FS_R1;
- break;
-
- case FS_RADIAL:
- i915_shader_radial_coord (device, shader->mask.base.mode,
- FS_T0 + texture_offset, /* input */
- FS_C0 + constant_offset,
- FS_C0 + constant_offset + 1, /* gradient constants */
- FS_R1); /* coordinate */
-
- i915_fs_texld (FS_R1, FS_S0 + sampler_offset, FS_R1);
- constant_offset += 2;
- texture_offset += 1;
- sampler_offset += 1;
- mask_reg = FS_R1;
- break;
-
- case FS_TEXTURE:
- i915_fs_texld (FS_R1, FS_S0 + sampler_offset, FS_T0 + texture_offset);
- texture_offset += 1;
- sampler_offset += 1;
- mask_reg = FS_R1;
- break;
- }
-
- if (mask_reg != ~0U) {
- if (! shader->need_combine &&
- shader->clip.type.fragment != FS_TEXTURE &&
- (shader->content != CAIRO_CONTENT_ALPHA || source_reg == ~0U))
- {
- out_reg = FS_OC;
- }
- if (source_reg == ~0U) {
- if (source_pure) {
- if (shader->mask.type.fragment == FS_SPANS) {
- if (out_reg == FS_OC && shader->content == CAIRO_CONTENT_ALPHA) {
- if (source_pure & (1 << 3))
- i915_fs_mov (out_reg, i915_fs_operand (mask_reg, X, X, X, X));
- else
- i915_fs_mov (out_reg, i915_fs_operand_zero ());
- } else {
- i915_fs_mov (out_reg,
- i915_fs_operand_impure (mask_reg, X, source_pure));
- }
- } else {
- /* XXX ComponentAlpha
- i915_fs_mov (out_reg,
- i915_fs_operand_pure (mask_reg,
- shader->source.solid.pure));
- */
- if (out_reg == FS_OC && shader->content == CAIRO_CONTENT_ALPHA) {
- if (source_pure & (1 << 3))
- i915_fs_mov (out_reg, i915_fs_operand (mask_reg, W, W, W, W));
- else
- i915_fs_mov (out_reg, i915_fs_operand_zero ());
- } else {
- i915_fs_mov (out_reg,
- i915_fs_operand_impure (mask_reg, W, source_pure));
- }
- }
- source_reg = out_reg;
- } else if (shader->mask.type.fragment == FS_SPANS) {
- i915_fs_mov (out_reg,
- i915_fs_operand (mask_reg, X, X, X, X));
- source_reg = out_reg;
- } else {
- source_reg = mask_reg;
- }
- } else {
- if (shader->mask.type.fragment == FS_SPANS) {
- if (out_reg == FS_OC && shader->content == CAIRO_CONTENT_ALPHA) {
- i915_fs_mul (out_reg,
- i915_fs_operand (source_reg, W, W, W, W),
- i915_fs_operand (mask_reg, X, X, X, X));
- } else {
- i915_fs_mul (out_reg,
- i915_fs_operand_reg (source_reg),
- i915_fs_operand (mask_reg, X, X, X, X));
- }
- } else {
- /* XXX ComponentAlpha
- i915_fs_mul (FS_R0,
- i915_fs_operand_reg (source_reg),
- i915_fs_operand_reg (mask_reg));
- */
- if (out_reg == FS_OC && shader->content == CAIRO_CONTENT_ALPHA) {
- i915_fs_mul (out_reg,
- i915_fs_operand (source_reg, W, W, W, W),
- i915_fs_operand (mask_reg, W, W, W, W));
- } else {
- i915_fs_mul (out_reg,
- i915_fs_operand_reg (source_reg),
- i915_fs_operand (mask_reg, W, W, W, W));
- }
- }
-
- source_reg = out_reg;
- }
- }
-
- if (shader->opacity < 1.) {
- i915_fs_mul (source_reg,
- i915_fs_operand_reg (source_reg),
- i915_fs_operand_reg (FS_C0 + constant_offset));
- constant_offset++;
- }
-
- /* need to preserve order of src, mask, clip, dst */
- mask_reg = ~0;
- if (shader->clip.type.fragment == FS_TEXTURE) {
- i915_fs_texld (FS_R1, FS_S0 + sampler_offset, FS_T0 + texture_offset);
- texture_offset += 1;
- sampler_offset += 1;
- mask_reg = FS_R1;
- }
-
- if (shader->need_combine) {
- assert (shader->dst.type.fragment == FS_TEXTURE);
-
- i915_fs_texld (FS_R2, FS_S0 + sampler_offset, FS_T0 + texture_offset);
- texture_offset += 1;
- sampler_offset += 1;
- dest_reg = FS_R2;
-
- switch (shader->op) {
- case CAIRO_OPERATOR_CLEAR:
- case CAIRO_OPERATOR_SOURCE:
- ASSERT_NOT_REACHED;
-
- case CAIRO_OPERATOR_OVER:
- if (source_reg == ~0U) {
- /* XXX shader->source.type.fragment == FS_PURE */
- dest_reg = FS_OC;
- } else {
- i915_fs_add (FS_U0,
- i915_fs_operand (source_reg, NEG_W, NEG_W, NEG_W, NEG_W),
- i915_fs_operand_one ());
- i915_fs_mul (FS_U0,
- i915_fs_operand_reg (FS_U0),
- dest_reg);
- i915_fs_add (FS_R3,
- i915_fs_operand_reg (source_reg),
- i915_fs_operand_reg (FS_U0));
- source_reg = FS_R3;
- }
- break;
-
- case CAIRO_OPERATOR_IN:
- if (source_reg == ~0U) {
- /* XXX shader->source.type.fragment == FS_PURE */
- source_reg = dest_reg;
- } else {
- i915_fs_mul (FS_R3,
- i915_fs_operand_reg (source_reg),
- dest_reg);
- source_reg = FS_R3;
- }
- break;
-
- case CAIRO_OPERATOR_OUT:
- if (source_reg == ~0U) {
- /* XXX shader->source.type.fragment == FS_PURE */
- i915_fs_mov (FS_R3, i915_fs_operand_zero ());
- source_reg = FS_R3;
- } else {
- i915_fs_add (FS_U0,
- i915_fs_operand (source_reg, NEG_W, NEG_W, NEG_W, NEG_W),
- i915_fs_operand_one ());
- i915_fs_mul (FS_R3,
- i915_fs_operand_reg (FS_U0),
- dest_reg);
- source_reg = FS_R3;
- }
- break;
-
- case CAIRO_OPERATOR_ATOP:
-
- case CAIRO_OPERATOR_DEST:
- case CAIRO_OPERATOR_DEST_OVER:
- case CAIRO_OPERATOR_DEST_IN:
- case CAIRO_OPERATOR_DEST_OUT:
- case CAIRO_OPERATOR_DEST_ATOP:
-
- case CAIRO_OPERATOR_XOR:
- case CAIRO_OPERATOR_ADD:
- case CAIRO_OPERATOR_SATURATE:
-
- case CAIRO_OPERATOR_MULTIPLY:
- case CAIRO_OPERATOR_SCREEN:
- case CAIRO_OPERATOR_OVERLAY:
- case CAIRO_OPERATOR_DARKEN:
- case CAIRO_OPERATOR_LIGHTEN:
- case CAIRO_OPERATOR_COLOR_DODGE:
- case CAIRO_OPERATOR_COLOR_BURN:
- case CAIRO_OPERATOR_HARD_LIGHT:
- case CAIRO_OPERATOR_SOFT_LIGHT:
- case CAIRO_OPERATOR_DIFFERENCE:
- case CAIRO_OPERATOR_EXCLUSION:
- case CAIRO_OPERATOR_HSL_HUE:
- case CAIRO_OPERATOR_HSL_SATURATION:
- case CAIRO_OPERATOR_HSL_COLOR:
- case CAIRO_OPERATOR_HSL_LUMINOSITY:
- ASSERT_NOT_REACHED;
- break;
- }
- }
-
- if (shader->clip.type.fragment == FS_TEXTURE) {
- assert (mask_reg != ~0U);
-
- if (! shader->need_combine) {
- /* (source IN clip) */
- if (source_reg == ~0U) {
- if (source_pure == 0) {
- source_reg = mask_reg;
- } else {
- out_reg = FS_OC;
- if ((shader->content & CAIRO_CONTENT_COLOR) == 0) {
- if (source_pure & (1 << 3))
- i915_fs_mov (out_reg, i915_fs_operand (mask_reg, W, W, W, W));
- else
- i915_fs_mov (out_reg, i915_fs_operand_zero ());
- } else {
- i915_fs_mov (out_reg,
- i915_fs_operand_impure (mask_reg, W, source_pure));
- }
- source_reg = out_reg;
- }
- } else if (mask_reg) {
- out_reg = FS_OC;
- if ((shader->content & CAIRO_CONTENT_COLOR) == 0) {
- i915_fs_mul (out_reg,
- i915_fs_operand (source_reg, W, W, W, W),
- i915_fs_operand (mask_reg, W, W, W, W));
- } else {
- i915_fs_mul (out_reg,
- i915_fs_operand_reg (source_reg),
- i915_fs_operand (mask_reg, W, W, W, W));
- }
-
- source_reg = out_reg;
- }
- } else {
- /* (source OP dest) LERP_clip dest */
- if (source_reg == ~0U) {
- if (source_pure == 0) {
- i915_fs_mov (FS_R3,
- i915_fs_operand (mask_reg, W, W, W, W));
- } else {
- i915_fs_mov (FS_R3,
- i915_fs_operand_impure (mask_reg, W, source_pure));
- }
- } else {
- i915_fs_mul (FS_R3,
- i915_fs_operand_reg (source_reg),
- i915_fs_operand (mask_reg, W, W, W, W));
- }
-
- i915_fs_add (mask_reg,
- i915_fs_operand_one (),
- i915_fs_operand (mask_reg, NEG_W, NEG_W, NEG_W, NEG_W));
-
- if (dest_reg != FS_OC) {
- if (dest_reg == ~0U) {
- assert (shader->dst.type.fragment == FS_TEXTURE);
-
- i915_fs_texld (FS_R2, FS_S0 + sampler_offset, FS_T0 + texture_offset);
- texture_offset += 1;
- sampler_offset += 1;
- dest_reg = FS_R2;
- }
-
- i915_fs_mul (FS_U1,
- i915_fs_operand_reg (dest_reg),
- i915_fs_operand_reg (mask_reg));
- mask_reg = FS_U1;
- }
-
- source_reg = FS_OC;
- if ((shader->content & CAIRO_CONTENT_COLOR) == 0) {
- i915_fs_add (source_reg,
- i915_fs_operand (FS_R3, W, W, W, W),
- i915_fs_operand (mask_reg, W, W, W, W));
- } else {
- i915_fs_add (source_reg,
- i915_fs_operand_reg (FS_R3),
- i915_fs_operand_reg (mask_reg));
- }
- }
- }
-
- if (source_reg != FS_OC) {
- if (source_reg == ~0U) {
- if (source_pure) {
- if ((shader->content & CAIRO_CONTENT_COLOR) == 0) {
- if (source_pure & (1 << 3))
- i915_fs_mov (FS_OC, i915_fs_operand_one ());
- else
- i915_fs_mov (FS_OC, i915_fs_operand_zero ());
- } else
- i915_fs_mov (FS_OC, i915_fs_operand_pure (source_pure));
- } else {
- i915_fs_mov (FS_OC, i915_fs_operand_one ());
- }
- } else if ((shader->content & CAIRO_CONTENT_COLOR) == 0) {
- i915_fs_mov (FS_OC, i915_fs_operand (source_reg, W, W, W, W));
- } else {
- i915_fs_mov (FS_OC, i915_fs_operand_reg (source_reg));
- }
- }
-
- FS_END ();
-}
-
-static cairo_bool_t
-i915_shader_linear_init (struct i915_shader_linear *l,
- const cairo_linear_pattern_t *linear)
-{
- double x0, y0, sf;
- double dx, dy, offset;
-
- dx = linear->pd2.x - linear->pd1.x;
- dy = linear->pd2.y - linear->pd1.y;
- sf = dx * dx + dy * dy;
- if (sf <= 1e-5)
- return FALSE;
-
- dx /= sf;
- dy /= sf;
-
- x0 = linear->pd1.x;
- y0 = linear->pd1.y;
- offset = dx*x0 + dy*y0;
-
- if (_cairo_matrix_is_identity (&linear->base.base.matrix)) {
- l->dx = dx;
- l->dy = dy;
- l->offset = -offset;
- } else {
- cairo_matrix_t m;
-
- cairo_matrix_init (&m, dx, 0, dy, 0, -offset, 0);
- cairo_matrix_multiply (&m, &linear->base.base.matrix, &m);
- l->dx = m.xx;
- l->dy = m.xy;
- l->offset = m.x0;
- }
-
- return TRUE;
-}
-
-static cairo_bool_t
-i915_shader_linear_contains_rectangle (struct i915_shader_linear *l,
- const cairo_rectangle_int_t *extents)
-{
- double v;
-
- v = i915_shader_linear_texcoord (l,
- extents->x,
- extents->y);
- if (v < 0.)
- return FALSE;
- if (v > 1.)
- return FALSE;
-
- v = i915_shader_linear_texcoord (l,
- extents->x + extents->width,
- extents->y);
- if (v < 0.)
- return FALSE;
- if (v > 1.)
- return FALSE;
-
- v = i915_shader_linear_texcoord (l,
- extents->x,
- extents->y + extents->height);
- if (v < 0.)
- return FALSE;
- if (v > 1.)
- return FALSE;
-
- v = i915_shader_linear_texcoord (l,
- extents->x + extents->width,
- extents->y + extents->height);
- if (v < 0.)
- return FALSE;
- if (v > 1.)
- return FALSE;
-
- return TRUE;
-}
-
-#define is_pure(C,mask) (((mask) == 0) || (C) <= 0x00ff || (C) >= 0xff00)
-#define is_one(C,mask) (((mask) != 0) && (C) >= 0xff00)
-#define is_zero(C,mask) (((mask) != 0) && (C) <= 0x00ff)
-
-static cairo_status_t
-i915_shader_acquire_solid (i915_shader_t *shader,
- union i915_shader_channel *src,
- const cairo_solid_pattern_t *solid,
- const cairo_rectangle_int_t *extents)
-{
- cairo_content_t content;
-
- content = CAIRO_CONTENT_COLOR_ALPHA;
- src->solid.color = solid->color;
- if (content == 0 || solid->color.alpha_short <= 0x00ff)
- {
- src->base.content = CAIRO_CONTENT_ALPHA;
- src->type.fragment = FS_ZERO;
- }
- else if ((((content & CAIRO_CONTENT_COLOR) == 0) ||
- (solid->color.red_short >= 0xff00 &&
- solid->color.green_short >= 0xff00 &&
- solid->color.blue_short >= 0xff00)) &&
- ((content & CAIRO_CONTENT_ALPHA) == 0 ||
- solid->color.alpha_short >= 0xff00))
- {
- src->base.content = CAIRO_CONTENT_ALPHA;
- src->type.fragment = FS_ONE;
- }
- else if (is_pure (solid->color.red_short, content & CAIRO_CONTENT_COLOR) &&
- is_pure (solid->color.green_short, content & CAIRO_CONTENT_COLOR) &&
- is_pure (solid->color.blue_short, content & CAIRO_CONTENT_COLOR) &&
- is_pure (solid->color.alpha_short, content & CAIRO_CONTENT_ALPHA))
- {
- src->solid.pure = 0;
- src->solid.pure |= is_one (solid->color.red_short, content & CAIRO_CONTENT_COLOR) << 0;
- src->solid.pure |= is_one (solid->color.green_short, content & CAIRO_CONTENT_COLOR) << 1;
- src->solid.pure |= is_one (solid->color.blue_short, content & CAIRO_CONTENT_COLOR) << 2;
- src->solid.pure |= (! is_zero (solid->color.alpha_short, content & CAIRO_CONTENT_ALPHA)) << 3;
-
- if (src->solid.pure == 0) {
- src->base.content = CAIRO_CONTENT_ALPHA;
- src->type.fragment = FS_ZERO;
- } else if (src->solid.pure == 0x7) {
- src->base.content = CAIRO_CONTENT_ALPHA;
- src->type.fragment = FS_ONE;
- } else {
- src->base.content = content;
- src->type.fragment = FS_PURE;
- src->base.mode = src->solid.pure;
- }
- }
- else
- {
- src->base.content = content;
- src->type.fragment = src == &shader->source ? FS_DIFFUSE : FS_CONSTANT;
- }
- src->type.vertex = src->type.fragment == FS_ZERO ? VS_ZERO : VS_CONSTANT;
- src->type.pattern = PATTERN_CONSTANT;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-i915_shader_acquire_linear (i915_shader_t *shader,
- union i915_shader_channel *src,
- const cairo_linear_pattern_t *linear,
- const cairo_rectangle_int_t *extents)
-{
- cairo_bool_t mode = LINEAR_TEXTURE;
- cairo_status_t status;
-
- if (i915_shader_linear_init (&src->linear, linear) &&
- linear->base.n_stops == 2 &&
- linear->base.stops[0].offset == 0.0 &&
- linear->base.stops[1].offset == 1.0)
- {
- if (i915_shader_linear_contains_rectangle (&src->linear,
- extents))
- {
- /* XXX can also lerp if contained within offset range */
- mode = LINEAR_NONE;
- }
- else switch (linear->base.base.extend) {
- case CAIRO_EXTEND_REPEAT:
- mode = LINEAR_REPEAT;
- break;
- case CAIRO_EXTEND_PAD:
- mode = LINEAR_PAD;
- break;
- case CAIRO_EXTEND_NONE:
- break;
- case CAIRO_EXTEND_REFLECT:
- break;
- default:
- ASSERT_NOT_REACHED;
- break;
- }
- }
-
- src->type.vertex = VS_LINEAR;
- src->type.pattern = PATTERN_LINEAR;
- src->base.texfmt = TEXCOORDFMT_1D;
- src->base.content = CAIRO_CONTENT_COLOR_ALPHA;
- src->base.mode = mode;
- if (mode == LINEAR_TEXTURE) {
- intel_buffer_t buffer;
-
- status = intel_gradient_render ((intel_device_t *) shader->target->intel.drm.base.device,
- &linear->base, &buffer);
- if (unlikely (status))
- return status;
-
- src->type.fragment = FS_TEXTURE;
- src->base.bo = intel_bo_reference (buffer.bo);
- src->base.n_samplers = 1;
- src->base.offset[0] = buffer.offset;
- src->base.map[0] = buffer.map0;
- src->base.map[1] = buffer.map1;
- src->base.sampler[0] =
- (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
- i915_texture_filter (CAIRO_FILTER_BILINEAR);
- src->base.sampler[1] =
- SS3_NORMALIZED_COORDS |
- i915_texture_extend (linear->base.base.extend);
- } else {
- src->type.fragment = FS_LINEAR;
- src->linear.color0.red = linear->base.stops[0].color.red;
- src->linear.color0.green = linear->base.stops[0].color.green;
- src->linear.color0.blue = linear->base.stops[0].color.blue;
- src->linear.color0.alpha = linear->base.stops[0].color.alpha;
-
- src->linear.color1.red = linear->base.stops[1].color.red;
- src->linear.color1.green = linear->base.stops[1].color.green;
- src->linear.color1.blue = linear->base.stops[1].color.blue;
- src->linear.color1.alpha = linear->base.stops[1].color.alpha;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-i915_shader_acquire_radial (i915_shader_t *shader,
- union i915_shader_channel *src,
- const cairo_radial_pattern_t *radial,
- const cairo_rectangle_int_t *extents)
-{
- intel_buffer_t buffer;
- cairo_status_t status;
-
- status = intel_gradient_render ((intel_device_t *) shader->target->intel.drm.base.device,
- &radial->base, &buffer);
- if (unlikely (status))
- return status;
-
- i915_shader_radial_init (&src->radial, radial);
-
- src->type.vertex = VS_TEXTURE;
- src->type.fragment = FS_RADIAL;
- src->type.pattern = PATTERN_RADIAL;
- src->base.texfmt = TEXCOORDFMT_2D;
-
- src->base.content = CAIRO_CONTENT_COLOR_ALPHA;
- src->base.bo = intel_bo_reference (buffer.bo);
- src->base.n_samplers = 1;
- src->base.offset[0] = buffer.offset;
- src->base.map[0] = buffer.map0;
- src->base.map[1] = buffer.map1;
- src->base.sampler[0] =
- (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
- i915_texture_filter (CAIRO_FILTER_BILINEAR);
- src->base.sampler[1] =
- SS3_NORMALIZED_COORDS |
- i915_texture_extend (radial->base.base.extend);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-i915_surface_clone (i915_device_t *device,
- cairo_image_surface_t *image,
- i915_surface_t **clone_out)
-{
- i915_surface_t *clone;
- cairo_status_t status;
-
-#if 0
- clone =
- i915_surface_create_from_cacheable_image_internal (device, image);
- if (unlikely (clone->intel.drm.base.status))
- return clone->intel.drm.base.status;
-#else
- cairo_format_t format;
-
- format = image->format;
- if (format == CAIRO_FORMAT_A1)
- format = CAIRO_FORMAT_A8;
-
- clone = (i915_surface_t *)
- i915_surface_create_internal (&device->intel.base,
- format,
- image->width,
- image->height,
- I915_TILING_DEFAULT,
- FALSE);
- if (unlikely (clone->intel.drm.base.status))
- return clone->intel.drm.base.status;
-
- status = intel_bo_put_image (&device->intel,
- to_intel_bo (clone->intel.drm.bo),
- image,
- 0, 0,
- image->width, image->height,
- 0, 0);
-
- if (unlikely (status))
- return status;
-#endif
-
- *clone_out = clone;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-i915_surface_clone_subimage (i915_device_t *device,
- cairo_image_surface_t *image,
- const cairo_rectangle_int_t *extents,
- i915_surface_t **clone_out)
-{
- i915_surface_t *clone;
- cairo_status_t status;
- cairo_format_t format;
-
- format = image->format;
- if (format == CAIRO_FORMAT_A1)
- format = CAIRO_FORMAT_A8;
-
- clone = (i915_surface_t *)
- i915_surface_create_internal (&device->intel.base,
- format,
- extents->width,
- extents->height,
- I915_TILING_NONE,
- FALSE);
- if (unlikely (clone->intel.drm.base.status))
- return clone->intel.drm.base.status;
-
- status = intel_bo_put_image (&device->intel,
- to_intel_bo (clone->intel.drm.bo),
- image,
- extents->x, extents->y,
- extents->width, extents->height,
- 0, 0);
-
- if (unlikely (status))
- return status;
-
- *clone_out = clone;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-i915_surface_render_pattern (i915_device_t *device,
- const cairo_surface_pattern_t *pattern,
- const cairo_rectangle_int_t *extents,
- i915_surface_t **clone_out)
-{
- i915_surface_t *clone;
- cairo_surface_t *image;
- cairo_status_t status;
- void *ptr;
-
- clone = (i915_surface_t *)
- i915_surface_create_internal (&device->intel.base,
- _cairo_format_from_content (pattern->surface->content),
- extents->width,
- extents->height,
- I915_TILING_NONE,
- FALSE);
- if (unlikely (clone->intel.drm.base.status))
- return clone->intel.drm.base.status;
-
- ptr = intel_bo_map (&device->intel,
- to_intel_bo (clone->intel.drm.bo));
- if (unlikely (ptr == NULL)) {
- cairo_surface_destroy (&clone->intel.drm.base);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- image = cairo_image_surface_create_for_data (ptr,
- clone->intel.drm.format,
- clone->intel.drm.width,
- clone->intel.drm.height,
- clone->intel.drm.stride);
- if (unlikely (image->status)) {
- cairo_surface_destroy (&clone->intel.drm.base);
- return image->status;
- }
-
- status = _cairo_surface_offset_paint (image,
- extents->x, extents->y,
- CAIRO_OPERATOR_SOURCE,
- &pattern->base,
- NULL);
- cairo_surface_destroy (image);
-
- if (unlikely (status)) {
- cairo_surface_destroy (&clone->intel.drm.base);
- return status;
- }
-
- *clone_out = clone;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-i915_shader_acquire_solid_surface (i915_shader_t *shader,
- union i915_shader_channel *src,
- cairo_surface_t *surface,
- const cairo_rectangle_int_t *extents)
-{
- cairo_surface_pattern_t pattern;
- cairo_surface_t *pixel;
- cairo_image_surface_t *image;
- void *image_extra;
- cairo_status_t status;
- uint32_t argb;
-
- status = _cairo_surface_acquire_source_image (surface, &image, &image_extra);
- if (unlikely (status))
- return status;
-
- /* extract the pixel as argb32 */
- pixel = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
- _cairo_pattern_init_for_surface (&pattern, &image->base);
- cairo_matrix_init_translate (&pattern.base.matrix, extents->x, extents->y);
- pattern.base.filter = CAIRO_FILTER_NEAREST;
- status = _cairo_surface_paint (pixel, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL);
- _cairo_pattern_fini (&pattern.base);
-
- _cairo_surface_release_source_image (surface, image, image_extra);
-
- if (unlikely (status)) {
- cairo_surface_destroy (pixel);
- return status;
- }
-
- image = (cairo_image_surface_t *) pixel;
- argb = *(uint32_t *) image->data;
- cairo_surface_destroy (pixel);
-
- if (argb >> 24 == 0) {
- _cairo_color_init_rgba (&src->solid.color, 0, 0, 0, 0);
- } else {
- uint8_t alpha = argb >> 24;
-
- _cairo_color_init_rgba (&src->solid.color,
- ((((argb >> 16) & 0xff) * 255 + alpha / 2) / alpha) / 255.,
- ((((argb >> 8) & 0xff) * 255 + alpha / 2) / alpha) / 255.,
- ((((argb >> 0) & 0xff) * 255 + alpha / 2) / alpha) / 255.,
- alpha / 255.);
- }
-
- src->base.content = CAIRO_CONTENT_COLOR_ALPHA;
- src->type.fragment = FS_CONSTANT;
- src->type.vertex = VS_CONSTANT;
- src->type.pattern = PATTERN_CONSTANT;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_filter_t
-sampled_area (const cairo_surface_pattern_t *pattern,
- const cairo_rectangle_int_t *extents,
- cairo_rectangle_int_t *sample)
-{
- cairo_rectangle_int_t surface_extents;
- cairo_filter_t filter;
- double x1, x2, y1, y2;
- double pad;
-
- x1 = extents->x;
- y1 = extents->y;
- x2 = extents->x + (int) extents->width;
- y2 = extents->y + (int) extents->height;
-
- if (_cairo_matrix_is_translation (&pattern->base.matrix)) {
- x1 += pattern->base.matrix.x0; x2 += pattern->base.matrix.x0;
- y1 += pattern->base.matrix.y0; y2 += pattern->base.matrix.y0;
- } else {
- _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
- &x1, &y1, &x2, &y2,
- NULL);
- }
-
- filter = _cairo_pattern_analyze_filter (&pattern->base, &pad);
- sample->x = floor (x1 - pad);
- sample->y = floor (y1 - pad);
- sample->width = ceil (x2 + pad) - sample->x;
- sample->height = ceil (y2 + pad) - sample->y;
-
- if (_cairo_surface_get_extents (pattern->surface, &surface_extents))
- _cairo_rectangle_intersect (sample, &surface_extents);
-
- return filter;
-}
-
-static cairo_status_t
-i915_shader_acquire_surface (i915_shader_t *shader,
- union i915_shader_channel *src,
- const cairo_surface_pattern_t *pattern,
- const cairo_rectangle_int_t *extents)
-{
- int surface_width, surface_height;
- cairo_surface_t *surface, *drm;
- cairo_extend_t extend;
- cairo_filter_t filter;
- cairo_matrix_t m;
- int src_x = 0, src_y = 0;
- cairo_surface_t *free_me = NULL;
- cairo_status_t status;
- cairo_rectangle_int_t sample;
-
- assert (src->type.fragment == (i915_fragment_shader_t) -1);
- drm = surface = pattern->surface;
-
- extend = pattern->base.extend;
- src->base.matrix = pattern->base.matrix;
- filter = sampled_area (pattern, extents, &sample);
-
- if (surface->type == CAIRO_SURFACE_TYPE_DRM) {
- if (surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
- drm = ((cairo_surface_subsurface_t *) surface)->target;
- } else if (surface->backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT) {
- drm = ((cairo_surface_snapshot_t *) surface)->target;
- }
- }
-
- if (drm->type == CAIRO_SURFACE_TYPE_DRM) {
- i915_surface_t *s = (i915_surface_t *) drm;
-
- if (surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
- if (s->intel.drm.base.device == shader->target->intel.drm.base.device &&
- s != shader->target)
- {
- cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) surface;
- int x;
-
- status = i915_surface_fallback_flush (s);
- if (unlikely (status))
- return status;
-
- /* XXX blt subimage and cache snapshot */
-
- if (to_intel_bo (s->intel.drm.bo)->batch_write_domain) {
- /* XXX pipelined flush of RENDER/TEXTURE cache */
- }
-
- src->type.fragment = FS_TEXTURE;
- src->surface.pixel = NONE;
- surface_width = sub->extents.width;
- surface_height = sub->extents.height;
-
- src->base.bo = intel_bo_reference (to_intel_bo (s->intel.drm.bo));
- src->base.n_samplers = 1;
-
- x = sub->extents.x;
- if (s->intel.drm.format != CAIRO_FORMAT_A8)
- x *= 4;
-
- /* XXX tiling restrictions upon offset? */
- src->base.offset[0] = s->offset + sub->extents.y * s->intel.drm.stride + x;
- src->base.map[0] = s->map0;
- src->base.map[0] &= ~((2047 << MS3_HEIGHT_SHIFT) | (2047 << MS3_WIDTH_SHIFT));
- src->base.map[0] |=
- ((sub->extents.height - 1) << MS3_HEIGHT_SHIFT) |
- ((sub->extents.width - 1) << MS3_WIDTH_SHIFT);
- src->base.map[1] = (s->intel.drm.stride / 4 - 1) << MS4_PITCH_SHIFT;
- }
- } else {
- /* XXX if s == shader->dst allow if FILTER_NEAREST, EXTEND_NONE? */
- if (s->intel.drm.base.device == shader->target->intel.drm.base.device) {
- status = i915_surface_fallback_flush (s);
- if (unlikely (status))
- return status;
-
- if (s == shader->target || i915_surface_needs_tiling (s)) {
- status = i915_surface_copy_subimage (i915_device (shader->target),
- s, &sample, TRUE, &s);
- if (unlikely (status))
- return status;
-
- free_me = drm = &s->intel.drm.base;
- }
-
- src->type.fragment = FS_TEXTURE;
- src->surface.pixel = NONE;
-
- surface_width = s->intel.drm.width;
- surface_height = s->intel.drm.height;
-
- src->base.bo = intel_bo_reference (to_intel_bo (s->intel.drm.bo));
- src->base.n_samplers = 1;
- src->base.offset[0] = s->offset;
- src->base.map[0] = s->map0;
- src->base.map[1] = s->map1;
- }
- }
- }
-
- if (src->type.fragment == (i915_fragment_shader_t) -1) {
- i915_surface_t *s;
-
- if (extents->width == 1 && extents->height == 1) {
- return i915_shader_acquire_solid_surface (shader, src,
- surface, extents);
- }
-
- s = (i915_surface_t *)
- _cairo_surface_has_snapshot (surface,
- shader->target->intel.drm.base.backend);
- if (s == NULL) {
- cairo_status_t status;
-
-#if 0
- /* XXX hackity hack hack */
- status = i915_clone_yuv (surface, src,
- image->width, image->height,
- clone_out);
-#endif
-
- if (sample.width > 2048 || sample.height > 2048) {
- status = i915_surface_render_pattern (i915_device (shader->target),
- pattern, extents,
- &s);
- if (unlikely (status))
- return status;
-
- extend = CAIRO_EXTEND_NONE;
- filter = CAIRO_FILTER_NEAREST;
- cairo_matrix_init_translate (&src->base.matrix,
- -extents->x, -extents->y);
- } else {
- cairo_image_surface_t *image;
- void *image_extra;
-
- status = _cairo_surface_acquire_source_image (surface, &image, &image_extra);
- if (unlikely (status))
- return status;
-
- if (image->width < 2048 &&
- image->height < 2048 &&
- sample.width >= image->width / 4 &&
- sample.height >= image->height /4)
- {
-
- status = i915_surface_clone (i915_device (shader->target),
- image, &s);
-
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
- _cairo_surface_attach_snapshot (surface,
- &s->intel.drm.base,
- intel_surface_detach_snapshot);
-
- status = intel_snapshot_cache_insert (&i915_device (shader->target)->intel,
- &s->intel);
- if (unlikely (status)) {
- cairo_surface_finish (&s->intel.drm.base);
- cairo_surface_destroy (&s->intel.drm.base);
- }
- }
- }
- else
- {
- status = i915_surface_clone_subimage (i915_device (shader->target),
- image, &sample, &s);
- src_x = -extents->x;
- src_y = -extents->y;
- }
-
- _cairo_surface_release_source_image (surface, image, image_extra);
- if (unlikely (status))
- return status;
- }
-
- free_me = &s->intel.drm.base;
- }
-
- src->type.fragment = FS_TEXTURE;
- src->surface.pixel = NONE;
-
- src->base.bo = intel_bo_reference (to_intel_bo (s->intel.drm.bo));
- src->base.n_samplers = 1;
- src->base.offset[0] = s->offset;
- src->base.map[0] = s->map0;
- src->base.map[1] = s->map1;
-
- drm = &s->intel.drm.base;
-
- surface_width = s->intel.drm.width;
- surface_height = s->intel.drm.height;
- }
-
- /* XXX transform nx1 or 1xn surfaces to 1D */
-
- src->type.pattern = PATTERN_TEXTURE;
- if (extend != CAIRO_EXTEND_NONE &&
- sample.x >= 0 && sample.y >= 0 &&
- sample.x + sample.width <= surface_width &&
- sample.y + sample.height <= surface_height)
- {
- extend = CAIRO_EXTEND_NONE;
- }
- if (extend == CAIRO_EXTEND_NONE) {
- src->type.vertex = VS_TEXTURE_16;
- src->base.texfmt = TEXCOORDFMT_2D_16;
- } else {
- src->type.vertex = VS_TEXTURE;
- src->base.texfmt = TEXCOORDFMT_2D;
- }
- src->base.content = drm->content;
-
- src->base.sampler[0] =
- (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
- i915_texture_filter (filter);
- src->base.sampler[1] =
- SS3_NORMALIZED_COORDS |
- i915_texture_extend (extend);
-
- /* tweak the src matrix to map from dst to texture coordinates */
- if (src_x | src_y)
- cairo_matrix_translate (&src->base.matrix, src_x, src_x);
- cairo_matrix_init_scale (&m, 1. / surface_width, 1. / surface_height);
- cairo_matrix_multiply (&src->base.matrix, &src->base.matrix, &m);
-
- if (free_me != NULL)
- cairo_surface_destroy (free_me);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-i915_shader_acquire_pattern (i915_shader_t *shader,
- union i915_shader_channel *src,
- const cairo_pattern_t *pattern,
- const cairo_rectangle_int_t *extents)
-{
- switch (pattern->type) {
- case CAIRO_PATTERN_TYPE_SOLID:
- return i915_shader_acquire_solid (shader, src,
- (cairo_solid_pattern_t *) pattern,
- extents);
-
- case CAIRO_PATTERN_TYPE_LINEAR:
- return i915_shader_acquire_linear (shader, src,
- (cairo_linear_pattern_t *) pattern,
- extents);
-
- case CAIRO_PATTERN_TYPE_RADIAL:
- return i915_shader_acquire_radial (shader, src,
- (cairo_radial_pattern_t *) pattern,
- extents);
-
- case CAIRO_PATTERN_TYPE_SURFACE:
- return i915_shader_acquire_surface (shader, src,
- (cairo_surface_pattern_t *) pattern,
- extents);
-
- default:
- ASSERT_NOT_REACHED;
- return CAIRO_STATUS_SUCCESS;
- }
-}
-
-static uint32_t
-i915_get_blend (cairo_operator_t op,
- i915_surface_t *dst)
-{
-#define SBLEND(X) ((BLENDFACT_##X) << S6_CBUF_SRC_BLEND_FACT_SHIFT)
-#define DBLEND(X) ((BLENDFACT_##X) << S6_CBUF_DST_BLEND_FACT_SHIFT)
- static const struct blendinfo {
- cairo_bool_t dst_alpha;
- uint32_t src_blend;
- uint32_t dst_blend;
- enum {
- BOUNDED,
- SIMPLE,
- XRENDER,
- } kind;
- } i915_blend_op[] = {
- {0, SBLEND (ZERO), DBLEND (ZERO), BOUNDED}, /* Clear */
- {0, SBLEND (ONE), DBLEND (ZERO), BOUNDED}, /* Src */
-
- {0, SBLEND (ONE), DBLEND (INV_SRC_ALPHA), SIMPLE}, /* Over */
- {1, SBLEND (DST_ALPHA), DBLEND (ZERO), XRENDER}, /* In */
- {1, SBLEND (INV_DST_ALPHA), DBLEND (ZERO), XRENDER}, /* Out */
- {1, SBLEND (DST_ALPHA), DBLEND (INV_SRC_ALPHA), SIMPLE}, /* Atop */
-
- {0, SBLEND (ZERO), DBLEND (ONE), SIMPLE}, /* Dst */
- {1, SBLEND (INV_DST_ALPHA), DBLEND (ONE), SIMPLE}, /* OverReverse */
- {0, SBLEND (ZERO), DBLEND (SRC_ALPHA), XRENDER}, /* InReverse */
- {0, SBLEND (ZERO), DBLEND (INV_SRC_ALPHA), SIMPLE}, /* OutReverse */
- {1, SBLEND (INV_DST_ALPHA), DBLEND (SRC_ALPHA), XRENDER}, /* AtopReverse */
-
- {1, SBLEND (INV_DST_ALPHA), DBLEND (INV_SRC_ALPHA), SIMPLE}, /* Xor */
- {0, SBLEND (ONE), DBLEND (ONE), SIMPLE}, /* Add */
- //{0, 0, SBLEND (SRC_ALPHA_SATURATE), DBLEND (ONE), SIMPLE}, /* XXX Saturate */
- };
- uint32_t sblend, dblend;
-
- if (op >= ARRAY_LENGTH (i915_blend_op))
- return 0;
-
- if (i915_blend_op[op].kind == BOUNDED)
- return 0;
-
- sblend = i915_blend_op[op].src_blend;
- dblend = i915_blend_op[op].dst_blend;
-
- /* If there's no dst alpha channel, adjust the blend op so that we'll treat
- * it as always 1.
- */
- if ((dst->intel.drm.base.content & CAIRO_CONTENT_ALPHA) == 0 &&
- i915_blend_op[op].dst_alpha)
- {
- if (sblend == SBLEND (DST_ALPHA))
- sblend = SBLEND (ONE);
- else if (sblend == SBLEND (INV_DST_ALPHA))
- sblend = SBLEND (ZERO);
- }
-
- /* i915 engine reads 8bit color buffer into green channel in cases
- like color buffer blending etc., and also writes back green channel.
- So with dst_alpha blend we should use color factor. See spec on
- "8-bit rendering" */
- if (dst->intel.drm.format == CAIRO_FORMAT_A8 && i915_blend_op[op].dst_alpha) {
- if (sblend == SBLEND (DST_ALPHA))
- sblend = SBLEND (DST_COLR);
- else if (sblend == SBLEND (INV_DST_ALPHA))
- sblend = SBLEND (INV_DST_COLR);
- }
-
- return sblend | dblend;
-#undef SBLEND
-#undef DBLEND
-}
-
-static void
-i915_shader_channel_init (union i915_shader_channel *channel)
-{
- channel->type.vertex = (i915_vertex_shader_t) -1;
- channel->type.fragment = (i915_fragment_shader_t) -1;
- channel->type.pattern = (i915_shader_channel_t) -1;
- channel->base.texfmt = TEXCOORDFMT_NOT_PRESENT;
- channel->base.bo = NULL;
- channel->base.n_samplers = 0;
- channel->base.mode = 0;
-}
-
-static void
-i915_shader_channel_fini (i915_device_t *device,
- union i915_shader_channel *channel)
-{
- switch (channel->type.pattern) {
- case PATTERN_TEXTURE:
- case PATTERN_BASE:
- case PATTERN_LINEAR:
- case PATTERN_RADIAL:
- if (channel->base.bo != NULL)
- intel_bo_destroy (&device->intel, channel->base.bo);
- break;
-
- default:
- case PATTERN_CONSTANT:
- break;
- }
-}
-
-static void
-i915_shader_channel_reset (i915_device_t *device,
- union i915_shader_channel *channel)
-{
- i915_shader_channel_fini (device, channel);
- i915_shader_channel_init (channel);
-}
-
-void
-i915_shader_init (i915_shader_t *shader,
- i915_surface_t *dst,
- cairo_operator_t op,
- double opacity)
-{
- shader->committed = FALSE;
- shader->device = i915_device (dst);
- shader->target = dst;
- shader->op = op;
- shader->opacity = opacity;
-
- shader->blend = i915_get_blend (op, dst);
- shader->need_combine = FALSE;
-
- shader->content = dst->intel.drm.base.content;
-
- i915_shader_channel_init (&shader->source);
- i915_shader_channel_init (&shader->mask);
- i915_shader_channel_init (&shader->clip);
- i915_shader_channel_init (&shader->dst);
-}
-
-static void
-i915_set_shader_samplers (i915_device_t *device,
- const i915_shader_t *shader)
-{
- uint32_t n_samplers, n_maps, n;
- uint32_t samplers[2*4];
- uint32_t maps[4*4];
- uint32_t mask, s, m;
-
- n_maps =
- shader->source.base.n_samplers +
- shader->mask.base.n_samplers +
- shader->clip.base.n_samplers +
- shader->dst.base.n_samplers;
- assert (n_maps <= 4);
-
- if (n_maps == 0)
- return;
-
- n_samplers =
- !! shader->source.base.bo +
- !! shader->mask.base.bo +
- !! shader->clip.base.bo +
- !! shader->dst.base.bo;
-
- mask = (1 << n_maps) - 1;
-
- /* We check for repeated setting of sample state mainly to catch
- * continuation of text strings across multiple show-glyphs.
- */
- s = m = 0;
- if (shader->source.base.bo != NULL) {
- samplers[s++] = shader->source.base.sampler[0];
- samplers[s++] = shader->source.base.sampler[1];
- maps[m++] = shader->source.base.bo->base.handle;
- for (n = 0; n < shader->source.base.n_samplers; n++) {
- maps[m++] = shader->source.base.offset[n];
- maps[m++] = shader->source.base.map[2*n+0];
- maps[m++] = shader->source.base.map[2*n+1];
- }
- }
- if (shader->mask.base.bo != NULL) {
- samplers[s++] = shader->mask.base.sampler[0];
- samplers[s++] = shader->mask.base.sampler[1];
- maps[m++] = shader->mask.base.bo->base.handle;
- for (n = 0; n < shader->mask.base.n_samplers; n++) {
- maps[m++] = shader->mask.base.offset[n];
- maps[m++] = shader->mask.base.map[2*n+0];
- maps[m++] = shader->mask.base.map[2*n+1];
- }
- }
- if (shader->clip.base.bo != NULL) {
- samplers[s++] = shader->clip.base.sampler[0];
- samplers[s++] = shader->clip.base.sampler[1];
- maps[m++] = shader->clip.base.bo->base.handle;
- for (n = 0; n < shader->clip.base.n_samplers; n++) {
- maps[m++] = shader->clip.base.offset[n];
- maps[m++] = shader->clip.base.map[2*n+0];
- maps[m++] = shader->clip.base.map[2*n+1];
- }
- }
- if (shader->dst.base.bo != NULL) {
- samplers[s++] = shader->dst.base.sampler[0];
- samplers[s++] = shader->dst.base.sampler[1];
- maps[m++] = shader->dst.base.bo->base.handle;
- for (n = 0; n < shader->dst.base.n_samplers; n++) {
- maps[m++] = shader->dst.base.offset[n];
- maps[m++] = shader->dst.base.map[2*n+0];
- maps[m++] = shader->dst.base.map[2*n+1];
- }
- }
-
- if (n_maps > device->current_n_maps ||
- memcmp (device->current_maps,
- maps,
- m * sizeof (uint32_t)))
- {
- memcpy (device->current_maps, maps, m * sizeof (uint32_t));
- device->current_n_maps = n_maps;
-
- if (device->current_source != NULL)
- *device->current_source = 0;
- if (device->current_mask != NULL)
- *device->current_mask = 0;
- if (device->current_clip != NULL)
- *device->current_clip = 0;
-
-#if 0
- if (shader->source.type.pattern == PATTERN_TEXTURE) {
- switch ((int) shader->source.surface.surface->type) {
- case CAIRO_SURFACE_TYPE_DRM:
- {
- i915_surface_t *surface =
- (i915_surface_t *) shader->source.surface.surface;
- device->current_source = &surface->is_current_texture;
- surface->is_current_texture |= CURRENT_SOURCE;
- break;
- }
-
- case I915_PACKED_PIXEL_SURFACE_TYPE:
- {
- i915_packed_pixel_surface_t *surface =
- (i915_packed_pixel_surface_t *) shader->source.surface.surface;
- device->current_source = &surface->is_current_texture;
- surface->is_current_texture |= CURRENT_SOURCE;
- break;
- }
-
- default:
- device->current_source = NULL;
- break;
- }
- } else
- device->current_source = NULL;
-
- if (shader->mask.type.pattern == PATTERN_TEXTURE) {
- switch ((int) shader->mask.surface.surface->type) {
- case CAIRO_SURFACE_TYPE_DRM:
- {
- i915_surface_t *surface =
- (i915_surface_t *) shader->mask.surface.surface;
- device->current_mask = &surface->is_current_texture;
- surface->is_current_texture |= CURRENT_MASK;
- break;
- }
-
- case I915_PACKED_PIXEL_SURFACE_TYPE:
- {
- i915_packed_pixel_surface_t *surface =
- (i915_packed_pixel_surface_t *) shader->mask.surface.surface;
- device->current_mask = &surface->is_current_texture;
- surface->is_current_texture |= CURRENT_MASK;
- break;
- }
-
- default:
- device->current_mask = NULL;
- break;
- }
- } else
- device->current_mask = NULL;
-#endif
-
- OUT_DWORD (_3DSTATE_MAP_STATE | (3 * n_maps));
- OUT_DWORD (mask);
- for (n = 0; n < shader->source.base.n_samplers; n++) {
- i915_batch_emit_reloc (device, shader->source.base.bo,
- shader->source.base.offset[n],
- I915_GEM_DOMAIN_SAMPLER, 0,
- FALSE);
- OUT_DWORD (shader->source.base.map[2*n+0]);
- OUT_DWORD (shader->source.base.map[2*n+1]);
- }
- for (n = 0; n < shader->mask.base.n_samplers; n++) {
- i915_batch_emit_reloc (device, shader->mask.base.bo,
- shader->mask.base.offset[n],
- I915_GEM_DOMAIN_SAMPLER, 0,
- FALSE);
- OUT_DWORD (shader->mask.base.map[2*n+0]);
- OUT_DWORD (shader->mask.base.map[2*n+1]);
- }
- for (n = 0; n < shader->clip.base.n_samplers; n++) {
- i915_batch_emit_reloc (device, shader->clip.base.bo,
- shader->clip.base.offset[n],
- I915_GEM_DOMAIN_SAMPLER, 0,
- FALSE);
- OUT_DWORD (shader->clip.base.map[2*n+0]);
- OUT_DWORD (shader->clip.base.map[2*n+1]);
- }
- for (n = 0; n < shader->dst.base.n_samplers; n++) {
- i915_batch_emit_reloc (device, shader->dst.base.bo,
- shader->dst.base.offset[n],
- I915_GEM_DOMAIN_SAMPLER, 0,
- FALSE);
- OUT_DWORD (shader->dst.base.map[2*n+0]);
- OUT_DWORD (shader->dst.base.map[2*n+1]);
- }
- }
-
- if (n_samplers > device->current_n_samplers ||
- memcmp (device->current_samplers,
- samplers,
- s * sizeof (uint32_t)))
- {
- device->current_n_samplers = s;
- memcpy (device->current_samplers, samplers, s * sizeof (uint32_t));
-
- OUT_DWORD (_3DSTATE_SAMPLER_STATE | (3 * n_maps));
- OUT_DWORD (mask);
- s = 0;
- for (n = 0; n < shader->source.base.n_samplers; n++) {
- OUT_DWORD (shader->source.base.sampler[0]);
- OUT_DWORD (shader->source.base.sampler[1] |
- (s << SS3_TEXTUREMAP_INDEX_SHIFT));
- OUT_DWORD (0x0);
- s++;
- }
- for (n = 0; n < shader->mask.base.n_samplers; n++) {
- OUT_DWORD (shader->mask.base.sampler[0]);
- OUT_DWORD (shader->mask.base.sampler[1] |
- (s << SS3_TEXTUREMAP_INDEX_SHIFT));
- OUT_DWORD (0x0);
- s++;
- }
- for (n = 0; n < shader->clip.base.n_samplers; n++) {
- OUT_DWORD (shader->clip.base.sampler[0]);
- OUT_DWORD (shader->clip.base.sampler[1] |
- (s << SS3_TEXTUREMAP_INDEX_SHIFT));
- OUT_DWORD (0x0);
- s++;
- }
- for (n = 0; n < shader->dst.base.n_samplers; n++) {
- OUT_DWORD (shader->dst.base.sampler[0]);
- OUT_DWORD (shader->dst.base.sampler[1] |
- (s << SS3_TEXTUREMAP_INDEX_SHIFT));
- OUT_DWORD (0x0);
- s++;
- }
- }
-}
-
-static uint32_t
-i915_shader_get_texcoords (const i915_shader_t *shader)
-{
- uint32_t texcoords;
- uint32_t tu;
-
- texcoords = S2_TEXCOORD_NONE;
- tu = 0;
- if (shader->source.base.texfmt != TEXCOORDFMT_NOT_PRESENT) {
- texcoords &= ~S2_TEXCOORD_FMT (tu, S2_TEXCOORD_FMT0_MASK);
- texcoords |= S2_TEXCOORD_FMT (tu, shader->source.base.texfmt);
- tu++;
- }
- if (shader->mask.base.texfmt != TEXCOORDFMT_NOT_PRESENT) {
- texcoords &= ~S2_TEXCOORD_FMT (tu, S2_TEXCOORD_FMT0_MASK);
- texcoords |= S2_TEXCOORD_FMT (tu, shader->mask.base.texfmt);
- tu++;
- }
- if (shader->clip.base.texfmt != TEXCOORDFMT_NOT_PRESENT) {
- texcoords &= ~S2_TEXCOORD_FMT (tu, S2_TEXCOORD_FMT0_MASK);
- texcoords |= S2_TEXCOORD_FMT (tu, shader->clip.base.texfmt);
- tu++;
- }
- if (shader->dst.base.texfmt != TEXCOORDFMT_NOT_PRESENT) {
- texcoords &= ~S2_TEXCOORD_FMT (tu, S2_TEXCOORD_FMT0_MASK);
- texcoords |= S2_TEXCOORD_FMT (tu, shader->dst.base.texfmt);
- tu++;
- }
-
- return texcoords;
-}
-
-static void
-i915_set_shader_mode (i915_device_t *device,
- const i915_shader_t *shader)
-{
- uint32_t texcoords;
- uint32_t mask, cnt;
-
- texcoords = i915_shader_get_texcoords (shader);
-
- mask = cnt = 0;
-
- if (device->current_texcoords != texcoords)
- mask |= I1_LOAD_S (2), cnt++;
-
- if (device->current_blend != shader->blend)
- mask |= I1_LOAD_S (6), cnt++;
-
- if (cnt == 0)
- return;
-
- OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | mask | (cnt-1));
-
- if (device->current_texcoords != texcoords) {
- OUT_DWORD (texcoords);
- device->current_texcoords = texcoords;
- }
-
- if (device->current_blend != shader->blend) {
- if (shader->blend) {
- OUT_DWORD (S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
- (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) |
- shader->blend);
- } else {
- OUT_DWORD (S6_COLOR_WRITE_ENABLE);
- }
-
- device->current_blend = shader->blend;
- }
-}
-
-static void
-i915_set_constants (i915_device_t *device,
- const uint32_t *constants,
- uint32_t n_constants)
-{
- uint32_t n;
-
- OUT_DWORD (_3DSTATE_PIXEL_SHADER_CONSTANTS | n_constants);
- OUT_DWORD ((1 << (n_constants >> 2)) - 1);
-
- for (n = 0; n < n_constants; n++)
- OUT_DWORD (constants[n]);
-
- device->current_n_constants = n_constants;
- memcpy (device->current_constants, constants, n_constants*4);
-}
-
-static uint32_t
-pack_constants (const union i915_shader_channel *channel,
- uint32_t *constants)
-{
- uint32_t count = 0, n;
-
- switch (channel->type.fragment) {
- case FS_ZERO:
- case FS_ONE:
- case FS_PURE:
- case FS_DIFFUSE:
- break;
-
- case FS_CONSTANT:
- constants[count++] = pack_float (channel->solid.color.red);
- constants[count++] = pack_float (channel->solid.color.green);
- constants[count++] = pack_float (channel->solid.color.blue);
- constants[count++] = pack_float (channel->solid.color.alpha);
- break;
-
- case FS_LINEAR:
- constants[count++] = pack_float (channel->linear.color0.red);
- constants[count++] = pack_float (channel->linear.color0.green);
- constants[count++] = pack_float (channel->linear.color0.blue);
- constants[count++] = pack_float (channel->linear.color0.alpha);
-
- constants[count++] = pack_float (channel->linear.color1.red);
- constants[count++] = pack_float (channel->linear.color1.green);
- constants[count++] = pack_float (channel->linear.color1.blue);
- constants[count++] = pack_float (channel->linear.color1.alpha);
- break;
-
- case FS_RADIAL:
- for (n = 0; n < ARRAY_LENGTH (channel->radial.constants); n++)
- constants[count++] = pack_float (channel->radial.constants[n]);
- break;
-
- case FS_TEXTURE:
- case FS_YUV:
- case FS_SPANS:
- break;
- }
-
- return count;
-}
-
-static void
-i915_set_shader_constants (i915_device_t *device,
- const i915_shader_t *shader)
-{
- uint32_t constants[4*4*3+4];
- unsigned n_constants;
-
- n_constants = 0;
- if (shader->source.type.fragment == FS_DIFFUSE) {
- uint32_t diffuse;
-
- diffuse =
- ((shader->source.solid.color.alpha_short >> 8) << 24) |
- ((shader->source.solid.color.red_short >> 8) << 16) |
- ((shader->source.solid.color.green_short >> 8) << 8) |
- ((shader->source.solid.color.blue_short >> 8) << 0);
-
- if (diffuse != device->current_diffuse) {
- OUT_DWORD (_3DSTATE_DFLT_DIFFUSE_CMD);
- OUT_DWORD (diffuse);
- device->current_diffuse = diffuse;
- }
- } else {
- n_constants += pack_constants (&shader->source, constants + n_constants);
- }
- n_constants += pack_constants (&shader->mask, constants + n_constants);
-
- if (shader->opacity < 1.) {
- constants[n_constants+0] =
- constants[n_constants+1] =
- constants[n_constants+2] =
- constants[n_constants+3] = pack_float (shader->opacity);
- n_constants += 4;
- }
-
- if (n_constants != 0 &&
- (device->current_n_constants != n_constants ||
- memcmp (device->current_constants, constants, n_constants*4)))
- {
- i915_set_constants (device, constants, n_constants);
- }
-}
-
-static cairo_bool_t
-i915_shader_needs_update (const i915_shader_t *shader,
- const i915_device_t *device)
-{
- uint32_t count, n;
- uint32_t buf[64];
-
- if (device->current_target != shader->target)
- return TRUE;
-
- count =
- !! shader->source.base.bo +
- !! shader->mask.base.bo +
- !! shader->clip.base.bo +
- !! shader->dst.base.bo;
- if (count > device->current_n_samplers)
- return TRUE;
-
- count =
- shader->source.base.n_samplers +
- shader->mask.base.n_samplers +
- shader->clip.base.n_samplers +
- shader->dst.base.n_samplers;
- if (count > device->current_n_maps)
- return TRUE;
-
- if (count) {
- count = 0;
- if (shader->source.base.bo != NULL) {
- buf[count++] = shader->source.base.sampler[0];
- buf[count++] = shader->source.base.sampler[1];
- }
- if (shader->mask.base.bo != NULL) {
- buf[count++] = shader->mask.base.sampler[0];
- buf[count++] = shader->mask.base.sampler[1];
- }
- if (shader->clip.base.bo != NULL) {
- buf[count++] = shader->clip.base.sampler[0];
- buf[count++] = shader->clip.base.sampler[1];
- }
- if (shader->dst.base.bo != NULL) {
- buf[count++] = shader->dst.base.sampler[0];
- buf[count++] = shader->dst.base.sampler[1];
- }
- if (memcmp (device->current_samplers, buf, count * sizeof (uint32_t)))
- return TRUE;
-
- count = 0;
- if (shader->source.base.bo != NULL) {
- buf[count++] = shader->source.base.bo->base.handle;
- for (n = 0; n < shader->source.base.n_samplers; n++) {
- buf[count++] = shader->source.base.offset[n];
- buf[count++] = shader->source.base.map[2*n+0];
- buf[count++] = shader->source.base.map[2*n+1];
- }
- }
- if (shader->mask.base.bo != NULL) {
- buf[count++] = shader->mask.base.bo->base.handle;
- for (n = 0; n < shader->mask.base.n_samplers; n++) {
- buf[count++] = shader->mask.base.offset[n];
- buf[count++] = shader->mask.base.map[2*n+0];
- buf[count++] = shader->mask.base.map[2*n+1];
- }
- }
- if (shader->clip.base.bo != NULL) {
- buf[count++] = shader->clip.base.bo->base.handle;
- for (n = 0; n < shader->clip.base.n_samplers; n++) {
- buf[count++] = shader->clip.base.offset[n];
- buf[count++] = shader->clip.base.map[2*n+0];
- buf[count++] = shader->clip.base.map[2*n+1];
- }
- }
- if (shader->dst.base.bo != NULL) {
- buf[count++] = shader->dst.base.bo->base.handle;
- for (n = 0; n < shader->dst.base.n_samplers; n++) {
- buf[count++] = shader->dst.base.offset[n];
- buf[count++] = shader->dst.base.map[2*n+0];
- buf[count++] = shader->dst.base.map[2*n+1];
- }
- }
- if (memcmp (device->current_maps, buf, count * sizeof (uint32_t)))
- return TRUE;
- }
-
- if (i915_shader_get_texcoords (shader) != device->current_texcoords)
- return TRUE;
- if (device->current_blend != shader->blend)
- return TRUE;
-
- count = 0;
- if (shader->source.type.fragment == FS_DIFFUSE) {
- uint32_t diffuse;
-
- diffuse =
- ((shader->source.solid.color.alpha_short >> 8) << 24) |
- ((shader->source.solid.color.red_short >> 8) << 16) |
- ((shader->source.solid.color.green_short >> 8) << 8) |
- ((shader->source.solid.color.blue_short >> 8) << 0);
-
- if (diffuse != device->current_diffuse)
- return TRUE;
- } else {
- count += pack_constants (&shader->source, buf + count);
- }
- count += pack_constants (&shader->mask, buf + count);
-
- if (count &&
- (device->current_n_constants != count ||
- memcmp (device->current_constants, buf, count*4)))
- {
- return TRUE;
- }
-
- n = (i915_shader_channel_key (&shader->source) << 0) |
- (i915_shader_channel_key (&shader->mask) << 8) |
- (i915_shader_channel_key (&shader->clip) << 16) |
- (shader->op << 24) |
- ((shader->opacity < 1.) << 30) |
- (((shader->content & CAIRO_CONTENT_ALPHA) == CAIRO_CONTENT_ALPHA) << 31);
- return n != device->current_program;
-}
-
-void
-i915_set_dst (i915_device_t *device, i915_surface_t *dst)
-{
- uint32_t size;
-
- if (device->current_target != dst) {
- intel_bo_t *bo;
-
- bo = to_intel_bo (dst->intel.drm.bo);
- assert (bo != NULL);
-
- OUT_DWORD (_3DSTATE_BUF_INFO_CMD);
- OUT_DWORD (BUF_3D_ID_COLOR_BACK |
- BUF_tiling (bo->tiling) |
- BUF_3D_PITCH (dst->intel.drm.stride));
- OUT_RELOC (dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
-
- device->current_target = dst;
- }
-
- if (dst->colorbuf != device->current_colorbuf) {
- OUT_DWORD (_3DSTATE_DST_BUF_VARS_CMD);
- OUT_DWORD (dst->colorbuf);
- device->current_colorbuf = dst->colorbuf;
- }
-
- size = DRAW_YMAX (dst->intel.drm.height) | DRAW_XMAX (dst->intel.drm.width);
- if (size != device->current_size) {
- OUT_DWORD (_3DSTATE_DRAW_RECT_CMD);
- OUT_DWORD (0); /* dither */
- OUT_DWORD (0); /* top-left */
- OUT_DWORD (size);
- OUT_DWORD (0); /* origin */
- device->current_size = size;
- }
-}
-
-static void
-i915_set_shader_target (i915_device_t *device,
- const i915_shader_t *shader)
-{
- i915_set_dst (device, shader->target);
-}
-
-int
-i915_shader_num_texcoords (const i915_shader_t *shader)
-{
- int cnt = 0;
-
- switch (shader->source.base.texfmt) {
- default:
- ASSERT_NOT_REACHED;
- case TEXCOORDFMT_NOT_PRESENT: break;
- case TEXCOORDFMT_2D: cnt += 2; break;
- case TEXCOORDFMT_3D: cnt += 3; break;
- case TEXCOORDFMT_4D: cnt += 4; break;
- case TEXCOORDFMT_1D: cnt += 1; break;
- case TEXCOORDFMT_2D_16: cnt += 1; break;
- }
-
- switch (shader->mask.base.texfmt) {
- default:
- ASSERT_NOT_REACHED;
- case TEXCOORDFMT_NOT_PRESENT: break;
- case TEXCOORDFMT_2D: cnt += 2; break;
- case TEXCOORDFMT_3D: cnt += 3; break;
- case TEXCOORDFMT_4D: cnt += 4; break;
- case TEXCOORDFMT_1D: cnt += 1; break;
- case TEXCOORDFMT_2D_16: cnt += 1; break;
- }
-
- switch (shader->clip.base.texfmt) {
- default:
- ASSERT_NOT_REACHED;
- case TEXCOORDFMT_NOT_PRESENT: break;
- case TEXCOORDFMT_2D: cnt += 2; break;
- case TEXCOORDFMT_3D: cnt += 3; break;
- case TEXCOORDFMT_4D: cnt += 4; break;
- case TEXCOORDFMT_1D: cnt += 1; break;
- case TEXCOORDFMT_2D_16: cnt += 1; break;
- }
-
- switch (shader->dst.base.texfmt) {
- default:
- ASSERT_NOT_REACHED;
- case TEXCOORDFMT_NOT_PRESENT: break;
- case TEXCOORDFMT_2D: cnt += 2; break;
- case TEXCOORDFMT_3D: cnt += 3; break;
- case TEXCOORDFMT_4D: cnt += 4; break;
- case TEXCOORDFMT_1D: cnt += 1; break;
- case TEXCOORDFMT_2D_16: cnt += 1; break;
- }
-
- return cnt;
-}
-
-void
-i915_shader_fini (i915_shader_t *shader)
-{
- i915_device_t *device = i915_device (shader->target);
-
- i915_shader_channel_fini (device, &shader->source);
- i915_shader_channel_fini (device, &shader->mask);
- i915_shader_channel_fini (device, &shader->clip);
-}
-
-void
-i915_shader_set_clip (i915_shader_t *shader,
- cairo_clip_t *clip)
-{
- cairo_surface_t *clip_surface;
- int clip_x, clip_y;
- union i915_shader_channel *channel;
- i915_surface_t *s;
-
- clip_surface = _cairo_clip_get_surface (clip, &shader->target->intel.drm.base, &clip_x, &clip_y);
- assert (clip_surface->status == CAIRO_STATUS_SUCCESS);
- assert (clip_surface->type == CAIRO_SURFACE_TYPE_DRM);
-
- channel = &shader->clip;
- channel->type.vertex = VS_TEXTURE_16;
- channel->base.texfmt = TEXCOORDFMT_2D_16;
- channel->base.content = CAIRO_CONTENT_ALPHA;
-
- channel->type.fragment = FS_TEXTURE;
- channel->surface.pixel = NONE;
-
- s = (i915_surface_t *) clip_surface;
- channel->base.bo = to_intel_bo (s->intel.drm.bo);
- channel->base.n_samplers = 1;
- channel->base.offset[0] = s->offset;
- channel->base.map[0] = s->map0;
- channel->base.map[1] = s->map1;
-
- channel->base.sampler[0] =
- (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
- i915_texture_filter (CAIRO_FILTER_NEAREST);
- channel->base.sampler[1] =
- SS3_NORMALIZED_COORDS |
- i915_texture_extend (CAIRO_EXTEND_NONE);
-
- cairo_matrix_init_scale (&shader->clip.base.matrix,
- 1. / s->intel.drm.width,
- 1. / s->intel.drm.height);
- cairo_matrix_translate (&shader->clip.base.matrix,
- -clip_x, -clip_y);
-}
-
-static cairo_status_t
-i915_shader_check_aperture (i915_shader_t *shader,
- i915_device_t *device)
-{
- cairo_status_t status;
- intel_bo_t *bo_array[4];
- uint32_t n = 0;
-
- if (shader->target != device->current_target)
- bo_array[n++] = to_intel_bo (shader->target->intel.drm.bo);
-
- if (shader->source.base.bo != NULL)
- bo_array[n++] = shader->source.base.bo;
-
- if (shader->mask.base.bo != NULL)
- bo_array[n++] = shader->mask.base.bo;
-
- if (shader->clip.base.bo != NULL)
- bo_array[n++] = shader->clip.base.bo;
-
- if (n == 0 || i915_check_aperture (device, bo_array, n))
- return CAIRO_STATUS_SUCCESS;
-
- status = i915_batch_flush (device);
- if (unlikely (status))
- return status;
-
- assert (i915_check_aperture (device, bo_array, n));
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-i915_shader_combine_mask (i915_shader_t *shader, i915_device_t *device)
-{
- if (shader->mask.type.fragment == (i915_fragment_shader_t) -1 ||
- shader->mask.type.fragment == FS_CONSTANT)
- {
- return;
- }
-
- if (shader->mask.type.fragment == FS_PURE) {
- if (shader->mask.solid.pure & (1<<3)) {
- shader->mask.type.fragment = FS_ONE;
- } else {
- shader->mask.type.fragment = FS_ZERO;
- }
- }
-
- if (shader->mask.type.fragment == FS_ONE ||
- (shader->mask.base.content & CAIRO_CONTENT_ALPHA) == 0)
- {
- i915_shader_channel_reset (device, &shader->mask);
- }
-
- if (shader->mask.type.fragment == FS_ZERO) {
- i915_shader_channel_fini (device, &shader->source);
-
- shader->source.type.fragment = FS_ZERO;
- shader->source.type.vertex = VS_ZERO;
- shader->source.base.texfmt = TEXCOORDFMT_NOT_PRESENT;
- shader->source.base.mode = 0;
- shader->source.base.n_samplers = 0;
- }
-
- if (shader->source.type.fragment == FS_ZERO) {
- i915_shader_channel_reset (device, &shader->mask);
- i915_shader_channel_reset (device, &shader->clip);
- }
-}
-
-static void
-i915_shader_setup_dst (i915_shader_t *shader)
-{
- union i915_shader_channel *channel;
- i915_surface_t *s;
-
- /* We need to manual blending if we have a clip surface and an unbounded op,
- * or an extended blend mode.
- */
- if (shader->need_combine ||
- (shader->op < CAIRO_OPERATOR_SATURATE &&
- (shader->clip.type.fragment == (i915_fragment_shader_t) -1 ||
- _cairo_operator_bounded_by_mask (shader->op))))
- {
- return;
- }
-
- shader->need_combine = TRUE;
-
- channel = &shader->dst;
- channel->type.vertex = VS_TEXTURE_16;
- channel->base.texfmt = TEXCOORDFMT_2D_16;
- channel->base.content = shader->content;
-
- channel->type.fragment = FS_TEXTURE;
- channel->surface.pixel = NONE;
-
- s = shader->target;
- channel->base.bo = to_intel_bo (s->intel.drm.bo);
- channel->base.n_samplers = 1;
- channel->base.offset[0] = s->offset;
- channel->base.map[0] = s->map0;
- channel->base.map[1] = s->map1;
-
- channel->base.sampler[0] =
- (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
- i915_texture_filter (CAIRO_FILTER_NEAREST);
- channel->base.sampler[1] =
- SS3_NORMALIZED_COORDS |
- i915_texture_extend (CAIRO_EXTEND_NONE);
-
- cairo_matrix_init_scale (&shader->dst.base.matrix,
- 1. / s->intel.drm.width,
- 1. / s->intel.drm.height);
-}
-
-static void
-i915_shader_combine_source (i915_shader_t *shader,
- i915_device_t *device)
-{
- if (device->last_source_fragment == shader->source.type.fragment)
- return;
-
- if (device->last_source_fragment == FS_DIFFUSE) {
- switch (shader->source.type.fragment) {
- case FS_ONE:
- case FS_PURE:
- case FS_CONSTANT:
- case FS_DIFFUSE:
- shader->source.type.fragment = FS_DIFFUSE;
- shader->source.base.mode = 0;
- break;
- case FS_ZERO:
- case FS_LINEAR:
- case FS_RADIAL:
- case FS_TEXTURE:
- case FS_YUV:
- case FS_SPANS:
- default:
- break;
- }
- }
-
- device->last_source_fragment = shader->source.type.fragment;
-}
-
-static inline float *
-i915_composite_vertex (float *v,
- const i915_shader_t *shader,
- double x, double y)
-{
- double s, t;
-
- /* Each vertex is:
- * 2 vertex coordinates
- * [0-2] source texture coordinates
- * [0-2] mask texture coordinates
- */
-
- *v++ = x; *v++ = y;
- switch (shader->source.type.vertex) {
- case VS_ZERO:
- case VS_CONSTANT:
- break;
- case VS_LINEAR:
- *v++ = i915_shader_linear_texcoord (&shader->source.linear, x, y);
- break;
- case VS_TEXTURE:
- s = x, t = y;
- cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
- *v++ = s; *v++ = t;
- break;
- case VS_TEXTURE_16:
- s = x, t = y;
- cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
- *v++ = texcoord_2d_16 (s, t);
- break;
- }
- switch (shader->mask.type.vertex) {
- case VS_ZERO:
- case VS_CONSTANT:
- break;
- case VS_LINEAR:
- *v++ = i915_shader_linear_texcoord (&shader->mask.linear, x, y);
- break;
- case VS_TEXTURE:
- s = x, t = y;
- cairo_matrix_transform_point (&shader->mask.base.matrix, &s, &t);
- *v++ = s; *v++ = t;
- break;
- case VS_TEXTURE_16:
- s = x, t = y;
- cairo_matrix_transform_point (&shader->mask.base.matrix, &s, &t);
- *v++ = texcoord_2d_16 (s, t);
- break;
- }
-
- return v;
-}
-
-static inline void
-i915_shader_add_rectangle_general (const i915_shader_t *shader,
- int x, int y,
- int w, int h)
-{
- float *vertices;
-
- vertices = i915_add_rectangle (shader->device);
- vertices = i915_composite_vertex (vertices, shader, x + w, y + h);
- vertices = i915_composite_vertex (vertices, shader, x, y + h);
- vertices = i915_composite_vertex (vertices, shader, x, y);
- /* XXX overflow! */
-}
-
-void
-i915_vbo_flush (i915_device_t *device)
-{
- assert (device->floats_per_vertex);
- assert (device->vertex_count);
-
- if (device->vbo == 0) {
- OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
- I1_LOAD_S (0) |
- I1_LOAD_S (1) |
- 1);
- device->vbo = device->batch.used++;
- device->vbo_max_index = device->batch.used;
- OUT_DWORD ((device->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
- (device->floats_per_vertex << S1_VERTEX_PITCH_SHIFT));
- }
-
- OUT_DWORD (PRIM3D_RECTLIST |
- PRIM3D_INDIRECT_SEQUENTIAL |
- device->vertex_count);
- OUT_DWORD (device->vertex_index);
-
- device->vertex_index += device->vertex_count;
- device->vertex_count = 0;
-}
-
-cairo_status_t
-i915_shader_commit (i915_shader_t *shader,
- i915_device_t *device)
-{
- unsigned floats_per_vertex;
- cairo_status_t status;
-
- assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex));
-
- if (! shader->committed) {
- device->shader = shader;
-
- i915_shader_combine_mask (shader, device);
- i915_shader_combine_source (shader, device);
- i915_shader_setup_dst (shader);
-
- shader->add_rectangle = i915_shader_add_rectangle_general;
-
- if ((status = setjmp (shader->unwind)))
- return status;
-
- shader->committed = TRUE;
- }
-
- if (i915_shader_needs_update (shader, device)) {
- if (i915_batch_space (device) < 256) {
- status = i915_batch_flush (device);
- if (unlikely (status))
- return status;
- }
-
- if (device->vertex_count)
- i915_vbo_flush (device);
-
- status = i915_shader_check_aperture (shader, device);
- if (unlikely (status))
- return status;
-
- update_shader:
- i915_set_shader_target (device, shader);
- i915_set_shader_mode (device, shader);
- i915_set_shader_samplers (device, shader);
- i915_set_shader_constants (device, shader);
- i915_set_shader_program (device, shader);
- }
-
- floats_per_vertex = 2 + i915_shader_num_texcoords (shader);
- if (device->floats_per_vertex == floats_per_vertex)
- return CAIRO_STATUS_SUCCESS;
-
- if (i915_batch_space (device) < 8) {
- status = i915_batch_flush (device);
- if (unlikely (status))
- return status;
-
- goto update_shader;
- }
-
- if (device->vertex_count)
- i915_vbo_flush (device);
-
- if (device->vbo) {
- device->batch_base[device->vbo_max_index] |= device->vertex_index;
- OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S (1) | 0);
- device->vbo_max_index = device->batch.used;
- OUT_DWORD ((floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
- (floats_per_vertex << S1_VERTEX_PITCH_SHIFT));
- }
-
- device->floats_per_vertex = floats_per_vertex;
- device->rectangle_size = floats_per_vertex * 3 * sizeof (float);
- device->vertex_index =
- (device->vbo_used + 4*floats_per_vertex - 1) / (4 * floats_per_vertex);
- device->vbo_offset = 4 * device->vertex_index * floats_per_vertex;
-
- return CAIRO_STATUS_SUCCESS;
-}