1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Mesa 3-D graphics library
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Version:  7.9
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 2010 LunarG Inc.
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice shall be included
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in all copies or substantial portions of the Software.
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE.
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Authors:
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    Chia-I Wu <olv@lunarg.com>
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "xm_api.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "xm_st.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_inlines.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_atomic.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct xmesa_st_framebuffer {
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   XMesaDisplay display;
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   XMesaBuffer buffer;
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_screen *screen;
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct st_visual stvis;
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   enum pipe_texture_target target;
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned texture_width, texture_height, texture_mask;
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_resource *display_resource;
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE struct xmesa_st_framebuffer *
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_st_framebuffer(struct st_framebuffer_iface *stfbi)
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return (struct xmesa_st_framebuffer *) stfbi->st_manager_private;
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Display an attachment to the xlib_drawable of the framebuffer.
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic boolean
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi,
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             enum st_attachment_type statt)
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_resource *ptex = xstfb->textures[statt];
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_resource *pres;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!ptex)
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return TRUE;
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pres = xstfb->display_resource;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* (re)allocate the surface for the texture to be displayed */
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!pres || pres != ptex) {
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pipe_resource_reference(&xstfb->display_resource, ptex);
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pres = xstfb->display_resource;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws);
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copy the contents between the attachments.
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi,
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   enum st_attachment_type src_statt,
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   enum st_attachment_type dst_statt,
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   unsigned x, unsigned y,
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   unsigned width, unsigned height)
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_resource *src_ptex = xstfb->textures[src_statt];
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_resource *dst_ptex = xstfb->textures[dst_statt];
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_box src_box;
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_context *pipe;
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!src_ptex || !dst_ptex)
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe = xmesa_get_context(stfbi);
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   u_box_2d(x, y, width, height, &src_box);
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (src_ptex && dst_ptex)
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pipe->resource_copy_region(pipe, dst_ptex, 0, x, y, 0,
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 src_ptex, 0, &src_box);
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Remove outdated textures and create the requested ones.
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This is a helper used during framebuffer validation.
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgboolean
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       unsigned width, unsigned height,
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       unsigned mask)
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_resource templ;
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   enum st_attachment_type i;
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* remove outdated textures */
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (xstfb->texture_width != width || xstfb->texture_height != height) {
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         pipe_resource_reference(&xstfb->textures[i], NULL);
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&templ, 0, sizeof(templ));
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   templ.target = xstfb->target;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   templ.width0 = width;
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   templ.height0 = height;
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   templ.depth0 = 1;
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   templ.array_size = 1;
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   templ.last_level = 0;
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      enum pipe_format format;
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned bind;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* the texture already exists or not requested */
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (xstfb->textures[i] || !(mask & (1 << i))) {
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* remember the texture */
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (xstfb->textures[i])
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            mask |= (1 << i);
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         continue;
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch (i) {
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case ST_ATTACHMENT_FRONT_LEFT:
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case ST_ATTACHMENT_BACK_LEFT:
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case ST_ATTACHMENT_FRONT_RIGHT:
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case ST_ATTACHMENT_BACK_RIGHT:
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         format = xstfb->stvis.color_format;
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bind = PIPE_BIND_DISPLAY_TARGET |
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     PIPE_BIND_RENDER_TARGET;
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case ST_ATTACHMENT_DEPTH_STENCIL:
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         format = xstfb->stvis.depth_stencil_format;
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bind = PIPE_BIND_DEPTH_STENCIL;
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         format = PIPE_FORMAT_NONE;
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (format != PIPE_FORMAT_NONE) {
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         templ.format = format;
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         templ.bind = bind;
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         xstfb->textures[i] =
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            xstfb->screen->resource_create(xstfb->screen, &templ);
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!xstfb->textures[i])
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return FALSE;
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb->texture_width = width;
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb->texture_height = height;
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb->texture_mask = mask;
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Check that a framebuffer's attachments match the window's size.
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Called via st_framebuffer_iface::validate()
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param statts  array of framebuffer attachments
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param count  number of framebuffer attachments in statts[]
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param out  returns resources for each of the attachments
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic boolean
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              const enum st_attachment_type *statts,
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              unsigned count,
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              struct pipe_resource **out)
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned statt_mask, new_mask, i;
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   boolean resized;
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   boolean ret;
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* build mask of ST_ATTACHMENT bits */
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   statt_mask = 0x0;
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < count; i++)
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      statt_mask |= 1 << statts[i];
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* record newly allocated textures */
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   new_mask = statt_mask & ~xstfb->texture_mask;
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* If xmesa_strict_invalidate is not set, we will not yet have
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * called XGetGeometry().  Do so here:
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!xmesa_strict_invalidate)
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      xmesa_check_buffer_size(xstfb->buffer);
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   resized = (xstfb->buffer->width != xstfb->texture_width ||
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              xstfb->buffer->height != xstfb->texture_height);
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* revalidate textures */
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (resized || new_mask) {
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ret = xmesa_st_framebuffer_validate_textures(stfbi,
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  xstfb->buffer->width, xstfb->buffer->height, statt_mask);
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!ret)
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return ret;
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!resized) {
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         enum st_attachment_type back, front;
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         back = ST_ATTACHMENT_BACK_LEFT;
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         front = ST_ATTACHMENT_FRONT_LEFT;
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* copy the contents if front is newly allocated and back is not */
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if ((statt_mask & (1 << back)) &&
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             (new_mask & (1 << front)) &&
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             !(new_mask & (1 << back))) {
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            xmesa_st_framebuffer_copy_textures(stfbi, back, front,
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  0, 0, xstfb->texture_width, xstfb->texture_height);
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < count; i++) {
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      out[i] = NULL;
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pipe_resource_reference(&out[i], xstfb->textures[statts[i]]);
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Called via st_framebuffer_iface::flush_front()
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic boolean
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 enum st_attachment_type statt)
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   boolean ret;
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ret = xmesa_st_framebuffer_display(stfbi, statt);
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ret && xmesa_strict_invalidate)
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      xmesa_check_buffer_size(xstfb->buffer);
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return ret;
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct st_framebuffer_iface *
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b)
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct st_framebuffer_iface *stfbi;
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(xmdpy->display == b->xm_visual->display);
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stfbi = CALLOC_STRUCT(st_framebuffer_iface);
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb = CALLOC_STRUCT(xmesa_st_framebuffer);
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!stfbi || !xstfb) {
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (stfbi)
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         FREE(stfbi);
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (xstfb)
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         FREE(xstfb);
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb->display = xmdpy;
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb->buffer = b;
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb->screen = xmdpy->screen;
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xstfb->stvis = b->xm_visual->stvis;
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(xstfb->screen->get_param(xstfb->screen, PIPE_CAP_NPOT_TEXTURES))
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      xstfb->target = PIPE_TEXTURE_2D;
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      xstfb->target = PIPE_TEXTURE_RECT;
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stfbi->visual = &xstfb->stvis;
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stfbi->flush_front = xmesa_st_framebuffer_flush_front;
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stfbi->validate = xmesa_st_framebuffer_validate;
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p_atomic_set(&stfbi->stamp, 1);
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stfbi->st_manager_private = (void *) xstfb;
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return stfbi;
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int i;
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_resource_reference(&xstfb->display_resource, NULL);
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pipe_resource_reference(&xstfb->textures[i], NULL);
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(xstfb);
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(stfbi);
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi)
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   boolean ret;
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT);
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ret) {
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct pipe_resource **front, **back, *tmp;
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT];
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT];
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* swap textures only if the front texture has been allocated */
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (*front) {
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         tmp = *front;
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         *front = *back;
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         *back = tmp;
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* the current context should validate the buffer after swapping */
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!xmesa_strict_invalidate)
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            xmesa_notify_invalid_buffer(xstfb->buffer);
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (xmesa_strict_invalidate)
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 xmesa_check_buffer_size(xstfb->buffer);
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          enum st_attachment_type src,
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          enum st_attachment_type dst,
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          int x, int y, int w, int h)
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h);
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (dst == ST_ATTACHMENT_FRONT_LEFT)
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      xmesa_st_framebuffer_display(stfbi, dst);
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct pipe_resource*
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_get_attachment(struct st_framebuffer_iface *stfbi,
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     enum st_attachment_type st_attachment)
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_resource* res;
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   res = xstfb->textures[st_attachment];
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return res;
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct pipe_context*
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxmesa_get_context(struct st_framebuffer_iface* stfbi)
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_context *pipe;
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe = xstfb->display->pipe;
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!pipe) {
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pipe = xstfb->screen->context_create(xstfb->screen, NULL);
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!pipe)
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return NULL;
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      xstfb->display->pipe = pipe;
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return pipe;
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
387