1 /*
2  * Cogl
3  *
4  * A Low Level GPU Graphics and Utilities API
5  *
6  * Copyright (C) 2012 Intel Corporation.
7  *
8  * Permission is hereby granted, free of charge, to any person
9  * obtaining a copy of this software and associated documentation
10  * files (the "Software"), to deal in the Software without
11  * restriction, including without limitation the rights to use, copy,
12  * modify, merge, publish, distribute, sublicense, and/or sell copies
13  * of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be
17  * included in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26  * SOFTWARE.
27  *
28  */
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #ifdef HAVE_STRINGS_H
35 #include <strings.h>
36 #endif
37 
38 #include "cogl-context-private.h"
39 #include "cogl-util-gl-private.h"
40 #include "cogl-texture-gl-private.h"
41 #include "cogl-texture-3d-private.h"
42 #include "cogl-util.h"
43 #include "cogl-pipeline-opengl-private.h"
44 
45 static inline int
calculate_alignment(int rowstride)46 calculate_alignment (int rowstride)
47 {
48   int alignment = 1 << (_cogl_util_ffs (rowstride) - 1);
49 
50   return MIN (alignment, 8);
51 }
52 
53 void
_cogl_texture_gl_prep_alignment_for_pixels_upload(CoglContext * ctx,int pixels_rowstride)54 _cogl_texture_gl_prep_alignment_for_pixels_upload (CoglContext *ctx,
55                                                    int pixels_rowstride)
56 {
57   GE( ctx, glPixelStorei (GL_UNPACK_ALIGNMENT,
58                           calculate_alignment (pixels_rowstride)) );
59 }
60 
61 void
_cogl_texture_gl_prep_alignment_for_pixels_download(CoglContext * ctx,int bpp,int width,int rowstride)62 _cogl_texture_gl_prep_alignment_for_pixels_download (CoglContext *ctx,
63                                                      int bpp,
64                                                      int width,
65                                                      int rowstride)
66 {
67   int alignment;
68 
69   /* If no padding is needed then we can always use an alignment of 1.
70    * We want to do this even though it is equivalent to the alignment
71    * of the rowstride because the Intel driver in Mesa currently has
72    * an optimisation when reading data into a PBO that only works if
73    * the alignment is exactly 1.
74    *
75    * https://bugs.freedesktop.org/show_bug.cgi?id=46632
76    */
77 
78   if (rowstride == bpp * width)
79     alignment = 1;
80   else
81     alignment = calculate_alignment (rowstride);
82 
83   GE( ctx, glPixelStorei (GL_PACK_ALIGNMENT, alignment) );
84 }
85 
86 void
_cogl_texture_gl_flush_legacy_texobj_wrap_modes(CoglTexture * texture,unsigned int wrap_mode_s,unsigned int wrap_mode_t,unsigned int wrap_mode_p)87 _cogl_texture_gl_flush_legacy_texobj_wrap_modes (CoglTexture *texture,
88                                                  unsigned int wrap_mode_s,
89                                                  unsigned int wrap_mode_t,
90                                                  unsigned int wrap_mode_p)
91 {
92   texture->vtable->gl_flush_legacy_texobj_wrap_modes (texture,
93                                                       wrap_mode_s,
94                                                       wrap_mode_t,
95                                                       wrap_mode_p);
96 }
97 
98 void
_cogl_texture_gl_flush_legacy_texobj_filters(CoglTexture * texture,unsigned int min_filter,unsigned int mag_filter)99 _cogl_texture_gl_flush_legacy_texobj_filters (CoglTexture *texture,
100                                               unsigned int min_filter,
101                                               unsigned int mag_filter)
102 {
103   texture->vtable->gl_flush_legacy_texobj_filters (texture,
104                                                    min_filter, mag_filter);
105 }
106 
107 void
_cogl_texture_gl_maybe_update_max_level(CoglTexture * texture,int max_level)108 _cogl_texture_gl_maybe_update_max_level (CoglTexture *texture,
109                                          int max_level)
110 {
111   /* This isn't supported on GLES */
112 #ifdef HAVE_COGL_GL
113   CoglContext *ctx = texture->context;
114 
115   if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL) &&
116       texture->max_level < max_level)
117     {
118       CoglContext *ctx = texture->context;
119       GLuint gl_handle;
120       GLenum gl_target;
121 
122       cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);
123 
124       texture->max_level = max_level;
125 
126       _cogl_bind_gl_texture_transient (gl_target,
127                                        gl_handle,
128                                        _cogl_texture_is_foreign (texture));
129 
130       GE( ctx, glTexParameteri (gl_target,
131                                 GL_TEXTURE_MAX_LEVEL, texture->max_level));
132     }
133 #endif /* HAVE_COGL_GL */
134 }
135 
136 void
_cogl_texture_gl_generate_mipmaps(CoglTexture * texture)137 _cogl_texture_gl_generate_mipmaps (CoglTexture *texture)
138 {
139   CoglContext *ctx = texture->context;
140   int n_levels = _cogl_texture_get_n_levels (texture);
141   GLuint gl_handle;
142   GLenum gl_target;
143 
144   _cogl_texture_gl_maybe_update_max_level (texture, n_levels - 1);
145 
146   cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);
147 
148   _cogl_bind_gl_texture_transient (gl_target,
149                                    gl_handle,
150                                    _cogl_texture_is_foreign (texture));
151   GE( ctx, glGenerateMipmap (gl_target) );
152 }
153 
154 GLenum
_cogl_texture_gl_get_format(CoglTexture * texture)155 _cogl_texture_gl_get_format (CoglTexture *texture)
156 {
157   return texture->vtable->get_gl_format (texture);
158 }
159