OSDN Git Service

intel: Add some defense against buffer allocation failure for subimage blits
[android-x86/external-mesa.git] / src / mesa / drivers / dri / intel / intel_tex_subimage.c
1
2 /**************************************************************************
3  * 
4  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
5  * All Rights Reserved.
6  * 
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  * 
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  * 
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  * 
27  **************************************************************************/
28
29 #include "main/mtypes.h"
30 #include "main/pbo.h"
31 #include "main/texobj.h"
32 #include "main/texstore.h"
33 #include "main/texcompress.h"
34 #include "main/enums.h"
35
36 #include "intel_context.h"
37 #include "intel_tex.h"
38 #include "intel_mipmap_tree.h"
39 #include "intel_blit.h"
40
41 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
42
43 static void
44 intelTexSubimage(struct gl_context * ctx,
45                  GLint dims,
46                  GLenum target, GLint level,
47                  GLint xoffset, GLint yoffset, GLint zoffset,
48                  GLint width, GLint height, GLint depth,
49                  GLsizei imageSize,
50                  GLenum format, GLenum type, const void *pixels,
51                  const struct gl_pixelstore_attrib *packing,
52                  struct gl_texture_object *texObj,
53                  struct gl_texture_image *texImage,
54                  GLboolean compressed)
55 {
56    struct intel_context *intel = intel_context(ctx);
57    struct intel_texture_image *intelImage = intel_texture_image(texImage);
58    GLuint dstRowStride = 0;
59    drm_intel_bo *temp_bo = NULL, *dst_bo = NULL;
60    unsigned int blit_x = 0, blit_y = 0;
61
62    DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
63        _mesa_lookup_enum_by_nr(target),
64        level, xoffset, yoffset, width, height);
65
66    intel_flush(ctx);
67
68    if (compressed)
69       pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize,
70                                                       pixels, packing,
71                                                       "glCompressedTexImage");
72    else
73       pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
74                                            format, type, pixels, packing,
75                                            "glTexSubImage");
76    if (!pixels)
77       return;
78
79    intel_prepare_render(intel);
80
81    /* Map buffer if necessary.  Need to lock to prevent other contexts
82     * from uploading the buffer under us.
83     */
84    if (intelImage->mt) {
85       dst_bo = intel_region_buffer(intel, intelImage->mt->region,
86                                    INTEL_WRITE_PART);
87
88       if (!compressed &&
89           intelImage->mt->region->tiling != I915_TILING_Y &&
90           intel->gen < 6 && target == GL_TEXTURE_2D &&
91           drm_intel_bo_busy(dst_bo))
92       {
93          unsigned long pitch;
94          uint32_t tiling_mode = I915_TILING_NONE;
95
96          temp_bo = drm_intel_bo_alloc_tiled(intel->bufmgr,
97                                             "subimage blit bo",
98                                             width, height,
99                                             intelImage->mt->cpp,
100                                             &tiling_mode,
101                                             &pitch,
102                                             0);
103          if (temp_bo == NULL)
104             return;
105
106          if (drm_intel_gem_bo_map_gtt(temp_bo)) {
107             drm_intel_bo_unreference(temp_bo);
108             return;
109          }
110
111          texImage->Data = temp_bo->virtual;
112          texImage->ImageOffsets[0] = 0;
113          dstRowStride = pitch;
114
115          intel_miptree_get_image_offset(intelImage->mt, level,
116                                         intelImage->face, 0,
117                                         &blit_x, &blit_y);
118          blit_x += xoffset;
119          blit_y += yoffset;
120          xoffset = 0;
121          yoffset = 0;
122       } else {
123          texImage->Data = intel_miptree_image_map(intel,
124                                                   intelImage->mt,
125                                                   intelImage->face,
126                                                   intelImage->level,
127                                                   &dstRowStride,
128                                                   texImage->ImageOffsets);
129       }
130    } else {
131       if (_mesa_is_format_compressed(texImage->TexFormat)) {
132          dstRowStride =
133             _mesa_format_row_stride(texImage->TexFormat, width);
134          assert(dims != 3);
135       }
136       else {
137          dstRowStride = texImage->RowStride * _mesa_get_format_bytes(texImage->TexFormat);
138       }
139    }
140
141    assert(dstRowStride);
142
143    if (compressed) {
144       if (intelImage->mt) {
145          struct intel_region *dst = intelImage->mt->region;
146          
147          _mesa_copy_rect(texImage->Data, dst->cpp, dst->pitch,
148                          xoffset, yoffset / 4,
149                          (width + 3)  & ~3, (height + 3) / 4,
150                          pixels, (width + 3) & ~3, 0, 0);
151       }
152       else {
153         memcpy(texImage->Data, pixels, imageSize);
154       }
155    }
156    else {
157       if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
158                           texImage->TexFormat,
159                           texImage->Data,
160                           xoffset, yoffset, zoffset,
161                           dstRowStride,
162                           texImage->ImageOffsets,
163                           width, height, depth,
164                           format, type, pixels, packing)) {
165          _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
166       }
167
168       if (temp_bo) {
169          GLboolean ret;
170          unsigned int dst_pitch = intelImage->mt->region->pitch *
171             intelImage->mt->cpp;
172
173          drm_intel_gem_bo_unmap_gtt(temp_bo);
174          texImage->Data = NULL;
175
176          ret = intelEmitCopyBlit(intel,
177                                  intelImage->mt->cpp,
178                                  dstRowStride / intelImage->mt->cpp,
179                                  temp_bo, 0, GL_FALSE,
180                                  dst_pitch / intelImage->mt->cpp, dst_bo, 0,
181                                  intelImage->mt->region->tiling,
182                                  0, 0, blit_x, blit_y, width, height,
183                                  GL_COPY);
184          assert(ret);
185       }
186    }
187
188    _mesa_unmap_teximage_pbo(ctx, packing);
189
190    if (temp_bo) {
191       drm_intel_bo_unreference(temp_bo);
192       temp_bo = NULL;
193    } else if (intelImage->mt) {
194       intel_miptree_image_unmap(intel, intelImage->mt);
195       texImage->Data = NULL;
196    }
197 }
198
199
200 static void
201 intelTexSubImage3D(struct gl_context * ctx,
202                    GLenum target,
203                    GLint level,
204                    GLint xoffset, GLint yoffset, GLint zoffset,
205                    GLsizei width, GLsizei height, GLsizei depth,
206                    GLenum format, GLenum type,
207                    const GLvoid * pixels,
208                    const struct gl_pixelstore_attrib *packing,
209                    struct gl_texture_object *texObj,
210                    struct gl_texture_image *texImage)
211 {
212    intelTexSubimage(ctx, 3,
213                     target, level,
214                     xoffset, yoffset, zoffset,
215                     width, height, depth, 0,
216                     format, type, pixels, packing, texObj, texImage, GL_FALSE);
217 }
218
219
220 static void
221 intelTexSubImage2D(struct gl_context * ctx,
222                    GLenum target,
223                    GLint level,
224                    GLint xoffset, GLint yoffset,
225                    GLsizei width, GLsizei height,
226                    GLenum format, GLenum type,
227                    const GLvoid * pixels,
228                    const struct gl_pixelstore_attrib *packing,
229                    struct gl_texture_object *texObj,
230                    struct gl_texture_image *texImage)
231 {
232    intelTexSubimage(ctx, 2,
233                     target, level,
234                     xoffset, yoffset, 0,
235                     width, height, 1, 0,
236                     format, type, pixels, packing, texObj, texImage, GL_FALSE);
237 }
238
239
240 static void
241 intelTexSubImage1D(struct gl_context * ctx,
242                    GLenum target,
243                    GLint level,
244                    GLint xoffset,
245                    GLsizei width,
246                    GLenum format, GLenum type,
247                    const GLvoid * pixels,
248                    const struct gl_pixelstore_attrib *packing,
249                    struct gl_texture_object *texObj,
250                    struct gl_texture_image *texImage)
251 {
252    intelTexSubimage(ctx, 1,
253                     target, level,
254                     xoffset, 0, 0,
255                     width, 1, 1, 0,
256                     format, type, pixels, packing, texObj, texImage, GL_FALSE);
257 }
258
259 static void
260 intelCompressedTexSubImage2D(struct gl_context * ctx,
261                              GLenum target,
262                              GLint level,
263                              GLint xoffset, GLint yoffset,
264                              GLsizei width, GLsizei height,
265                              GLenum format, GLsizei imageSize,
266                              const GLvoid * pixels,
267                              struct gl_texture_object *texObj,
268                              struct gl_texture_image *texImage)
269 {
270    intelTexSubimage(ctx, 2,
271                     target, level,
272                     xoffset, yoffset, 0,
273                     width, height, 1, imageSize,
274                     format, 0, pixels, &ctx->Unpack, texObj, texImage, GL_TRUE);
275 }
276
277
278
279 void
280 intelInitTextureSubImageFuncs(struct dd_function_table *functions)
281 {
282    functions->TexSubImage1D = intelTexSubImage1D;
283    functions->TexSubImage2D = intelTexSubImage2D;
284    functions->TexSubImage3D = intelTexSubImage3D;
285    functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D;
286 }