Merge branch 'master' into 28
authorCampbell Barton <ideasman42@gmail.com>
Wed, 12 Apr 2017 10:23:30 +0000 (20:23 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 12 Apr 2017 10:23:44 +0000 (20:23 +1000)
1  2 
source/blender/gpu/intern/gpu_basic_shader.c
source/blender/gpu/intern/gpu_buffers.c
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_framebuffer.c
source/blender/gpu/intern/gpu_material.c
source/blender/gpu/intern/gpu_texture.c
source/blender/gpu/intern/gpu_viewport.c

index bbd28c8803d3bc19b502f724cb8579cdca3be4ba,8505bd847a0c53a4d81280abe8637fabfb004c48..ff385683a1e6ae0e57918f74c6d8dbd9138a9ce5
@@@ -294,12 -420,34 +294,12 @@@ static void gpu_basic_shader_uniform_au
  
  void GPU_basic_shader_bind(int options)
  {
 -      if (USE_GLSL) {
 -              if (options) {
 -                      const int bound_options = GPU_MATERIAL_STATE.bound_options;
 -
 -                      /* texture options need to be set for basic shader too */
 -                      if (options & GPU_SHADER_TEXTURE_2D) {
 -                              glEnable(GL_TEXTURE_2D);
 -                      }
 -                      else if (bound_options & GPU_SHADER_TEXTURE_2D) {
 -                              glDisable(GL_TEXTURE_2D);
 -                      }
 -
 -                      if (options & GPU_SHADER_TEXTURE_RECT) {
 -                              glEnable(GL_TEXTURE_RECTANGLE);
 -                      }
 -                      else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
 -                              glDisable(GL_TEXTURE_RECTANGLE);
 -                      }
 +      if (options) {
 +              GPUShader *shader = gpu_basic_shader(options);
  
 -                      GPUShader *shader = gpu_basic_shader(options);
 -
 -                      if (shader) {
 -                              GPU_shader_bind(shader);
 -                              gpu_basic_shader_uniform_autoset(shader, options);
 -                      }
 -              }
 -              else {
 -                      GPU_shader_unbind();
 +              if (shader) {
 +                      GPU_shader_bind(shader);
-                       GPU_basic_shader_uniform_autoset(shader, options);
++                      gpu_basic_shader_uniform_autoset(shader, options);
                }
        }
        else {
index 6008e32f0fd8fb03ac1dadd6487e5b61ddc03418,074fadf600354472d5da3c736850fa8aa0a86ed0..3ef0a02718d631278ed9693b552087cba06738bb
@@@ -1175,9 -1203,11 +1175,9 @@@ void GPU_paint_set_mipmap(bool mipmap
  
  
  /* check if image has been downscaled and do scaled partial update */
- static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
+ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
  {
 -      if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) ||
 -          is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y))
 -      {
 +      if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) {
                int x_limit = smaller_power_of_2_limit(ibuf->x);
                int y_limit = smaller_power_of_2_limit(ibuf->y);
  
@@@ -1265,8 -1295,8 +1265,8 @@@ void GPU_paint_update_image(Image *ima
                        float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf");
                        bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0;
                        IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
 -                      
 +
-                       if (GPU_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
+                       if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
                                MEM_freeN(buffer);
                                BKE_image_release_ibuf(ima, ibuf, NULL);
                                return;
@@@ -1945,8 -1964,9 +1945,8 @@@ int GPU_object_material_bind(int nr, vo
                        GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv);
                        GPU_material_vertex_attributes(gpumat, gattribs);
  
 -                      if (GMS.dob) {
 +                      if (GMS.dob)
-                               GPU_get_particle_info(&partile_info);
+                               gpu_get_particle_info(&partile_info);
 -                      }
  
                        GPU_material_bind(
                                gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
index fabcf4409da40cd881bc64d339c635213d046a0a,e7a8beae5cc93aa5b36760221f1f9fe429787326..ce3b37b3a662b5f6bafa69902700e47c70430ef4
@@@ -51,42 -50,48 +51,42 @@@ struct GPUFrameBuffer 
        GLuint object;
        GPUTexture *colortex[GPU_FB_MAX_SLOTS];
        GPUTexture *depthtex;
 +      struct GPUStateValues attribs;
  };
  
- static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
+ static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
  {
 +      const char *format = "GPUFrameBuffer: framebuffer status %s\n";
        const char *err = "unknown";
  
 +#define format_status(X) \
 +      case GL_FRAMEBUFFER_##X: err = "GL_FRAMEBUFFER_"#X; \
 +              break;
 +
        switch (status) {
 -              case GL_FRAMEBUFFER_COMPLETE_EXT:
 -                      break;
 -              case GL_INVALID_OPERATION:
 -                      err = "Invalid operation";
 -                      break;
 -              case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
 -                      err = "Incomplete attachment";
 -                      break;
 -              case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
 -                      err = "Unsupported framebuffer format";
 -                      break;
 -              case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
 -                      err = "Missing attachment";
 -                      break;
 -              case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
 -                      err = "Attached images must have same dimensions";
 -                      break;
 -              case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
 -                      err = "Attached images must have same format";
 -                      break;
 -              case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
 -                      err = "Missing draw buffer";
 -                      break;
 -              case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
 -                      err = "Missing read buffer";
 -                      break;
 +              /* success */
 +              format_status(COMPLETE)
 +              /* errors shared by OpenGL desktop & ES */
 +              format_status(INCOMPLETE_ATTACHMENT)
 +              format_status(INCOMPLETE_MISSING_ATTACHMENT)
 +              format_status(UNSUPPORTED)
 +#if 0 /* for OpenGL ES only */
 +              format_status(INCOMPLETE_DIMENSIONS)
 +#else /* for desktop GL only */
 +              format_status(INCOMPLETE_DRAW_BUFFER)
 +              format_status(INCOMPLETE_READ_BUFFER)
 +              format_status(INCOMPLETE_MULTISAMPLE)
 +              format_status(UNDEFINED)
 +#endif
        }
  
 +#undef format_status
 +
        if (err_out) {
 -              BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
 -                      (int)status, err);
 +              BLI_snprintf(err_out, 256, format, err);
        }
        else {
 -              fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
 -                      (int)status, err);
 +              fprintf(stderr, format, err);
        }
  }
  
@@@ -320,17 -319,22 +320,17 @@@ bool GPU_framebuffer_bound(GPUFrameBuff
  
  bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
  {
 -      GLenum status;
 -      
 -      glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
 +      glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
        GG.currentfb = fb->object;
 -      
 -      /* Clean glError buffer. */
 -      while (glGetError() != GL_NO_ERROR) {}
 -      
 -      status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 -      
 -      if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
 +
 +      GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 +
 +      if (status != GL_FRAMEBUFFER_COMPLETE) {
                GPU_framebuffer_restore();
-               GPU_print_framebuffer_error(status, err_out);
+               gpu_print_framebuffer_error(status, err_out);
                return false;
        }
 -      
 +
        return true;
  }
  
index 4b3570e3831b57226c4ce218d654f3a684bdcd3b,1c97c2ce81101748a19c2447fe265e3f97b0bb87..d0f5a5a5b158aa9c0b8a3ccb44b04057d1e2655c
@@@ -61,165 -62,33 +61,167 @@@ struct GPUTexture 
  
        GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
        int fb_attachment;  /* slot the texture is attached to */
 -      int depth;          /* is a depth texture? if 3D how deep? */
 +      bool depth;         /* is a depth texture? */
 +      bool stencil;       /* is a stencil texture? */
  };
  
- static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil)
 -static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
++static GLenum gpu_texture_get_format(
++        int components, GPUTextureFormat data_type,
++        GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil)
  {
 -      unsigned char *pixels, *p;
 -      const float *fp = fpixels;
 -      const int len = 4 * length;
 +      if (data_type == GPU_DEPTH_COMPONENT24 ||
 +          data_type == GPU_DEPTH_COMPONENT16 ||
 +          data_type == GPU_DEPTH_COMPONENT32F)
 +      {
 +              *is_depth = true;
 +              *is_stencil = false;
 +              *data_format = GL_FLOAT;
 +              *format = GL_DEPTH_COMPONENT;
 +      }
 +      else if (data_type == GPU_DEPTH24_STENCIL8) {
 +              *is_depth = true;
 +              *is_stencil = true;
 +              *data_format = GL_UNSIGNED_INT_24_8;
 +              *format = GL_DEPTH_STENCIL;
 +      }
 +      else {
 +              *is_depth = false;
 +              *is_stencil = false;
 +              *data_format = GL_FLOAT;
 +
 +              switch (components) {
 +                      case 1: *format = GL_RED; break;
 +                      case 2: *format = GL_RG; break;
 +                      case 3: *format = GL_RGB; break;
 +                      case 4: *format = GL_RGBA; break;
 +                      default: break;
 +              }
 +      }
 +
 +      /* You can add any of the available type to this list
 +       * For available types see GPU_texture.h */
 +      switch (data_type) {
 +              /* Formats texture & renderbuffer */
 +              case GPU_RGBA16F: return GL_RGBA16F;
 +              case GPU_RG32F: return GL_RG32F;
 +              case GPU_RG16F: return GL_RG16F;
 +              case GPU_RGBA8: return GL_RGBA8;
 +              case GPU_R16F: return GL_R16F;
 +              case GPU_R8: return GL_R8;
 +              /* Special formats texture & renderbuffer */
 +              case GPU_DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8;
 +              /* Texture only format */
 +              /* ** Add Format here **/
 +              /* Special formats texture only */
 +              /* ** Add Format here **/
 +              /* Depth Formats */
 +              case GPU_DEPTH_COMPONENT32F: return GL_DEPTH_COMPONENT32F;
 +              case GPU_DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT24;
 +              case GPU_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT16;
 +              default:
 +                      fprintf(stderr, "Texture format incorrect or unsupported\n");
 +                      return 0;
 +      }
 +}
  
 -      p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
 +static float *GPU_texture_3D_rescale(GPUTexture *tex, int w, int h, int d, int channels, const float *fpixels)
 +{
 +      const unsigned int xf = w / tex->w, yf = h / tex->h, zf = d / tex->d;
 +      float *nfpixels = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->d, "GPUTexture Rescaled 3Dtex");
 +
 +      if (nfpixels) {
 +              GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
 +
 +              for (unsigned k = 0; k < tex->d; k++) {
 +                      for (unsigned j = 0; j < tex->h; j++) {
 +                              for (unsigned i = 0; i < tex->w; i++) {
 +                                      /* obviously doing nearest filtering here,
 +                                       * it's going to be slow in any case, let's not make it worse */
 +                                      float xb = i * xf;
 +                                      float yb = j * yf;
 +                                      float zb = k * zf;
 +                                      unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
 +                                      unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
  
 -      for (int a = 0; a < len; a++, p++, fp++)
 -              *p = FTOCHAR((*fp));
 +                                      if (channels == 4) {
 +                                              nfpixels[offset * 4] = fpixels[offset_orig * 4];
 +                                              nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
 +                                              nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
 +                                              nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
 +                                      }
 +                                      else
 +                                              nfpixels[offset] = fpixels[offset_orig];
 +                              }
 +                      }
 +              }
 +      }
  
 -      return pixels;
 +      return nfpixels;
  }
  
 -static void gpu_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
 +/* This tries to allocate video memory for a given texture
 + * If alloc fails, lower the resolution until it fits. */
- static bool GPU_texture_try_alloc(
++static bool gpu_texture_try_alloc(
 +        GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum format, GLenum data_format,
 +        int channels, bool try_rescale, const float *fpixels, float **rescaled_fpixels)
  {
 -      void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
 +      int r_width;
  
 -      if (target == GL_TEXTURE_1D)
 -              glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
 -      else
 -              glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
 -      
 -      MEM_freeN(pixels);
 +      switch (proxy) {
 +              case GL_PROXY_TEXTURE_1D:
 +                      glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL);
 +                      break;
 +              case GL_PROXY_TEXTURE_1D_ARRAY:
 +              case GL_PROXY_TEXTURE_2D:
 +                      glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
 +                      break;
 +              case GL_PROXY_TEXTURE_2D_ARRAY:
 +              case GL_PROXY_TEXTURE_3D:
 +                      glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL);
 +                      break;
 +      }
 +
 +      glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &r_width);
 +
 +      if (r_width == 0 && try_rescale) {
 +              const int w = tex->w, h = tex->h, d = tex->d;
 +
 +              /* Find largest texture possible */
 +              while (r_width == 0) {
 +                      tex->w /= 2;
 +                      tex->h /= 2;
 +                      tex->d /= 2;
 +
 +                      /* really unlikely to happen but keep this just in case */
 +                      if (tex->w == 0) break;
 +                      if (tex->h == 0 && proxy != GL_PROXY_TEXTURE_1D) break;
 +                      if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) break;
 +
 +                      if (proxy == GL_PROXY_TEXTURE_1D)
 +                              glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL);
 +                      else if (proxy == GL_PROXY_TEXTURE_2D)
 +                              glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
 +                      else if (proxy == GL_PROXY_TEXTURE_3D)
 +                              glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL);
 +
 +                      glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
 +              }
 +
 +              /* Rescale */
 +              if (r_width > 0) {
 +                      switch (proxy) {
 +                              case GL_PROXY_TEXTURE_1D:
 +                              case GL_PROXY_TEXTURE_2D:
 +                                      /* Do nothing for now */
 +                                      return false;
 +                              case GL_PROXY_TEXTURE_3D:
 +                                      *rescaled_fpixels = GPU_texture_3D_rescale(tex, w, h, d, channels, fpixels);
 +                                      return (bool)*rescaled_fpixels;
 +                      }
 +              }
 +      }
 +
 +      return (r_width > 0);
  }
  
  static GPUTexture *GPU_texture_create_nD(
        GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
        tex->w = w;
        tex->h = h;
 +      tex->d = d;
        tex->number = -1;
        tex->refcount = 1;
 -      tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
 -      tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
 -      tex->depth = depth;
        tex->fb_attachment = -1;
  
-       internalformat = GPU_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil);
 +      if (n == 1) {
 +              if (h == 0)
 +                      tex->target_base = tex->target = GL_TEXTURE_1D;
 +              else
 +                      tex->target_base = tex->target = GL_TEXTURE_1D_ARRAY;
 +      }
 +      else if (n == 2) {
 +              if (d == 0)
 +                      tex->target_base = tex->target = GL_TEXTURE_2D;
 +              else
 +                      tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY;
 +      }
 +      else if (n == 3) {
 +              tex->target_base = tex->target = GL_TEXTURE_3D;
 +      }
 +
 +      if (samples && n == 2 && d == 0)
 +              tex->target = GL_TEXTURE_2D_MULTISAMPLE;
 +
++      internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil);
 +
 +      /* Generate Texture object */
        glGenTextures(1, &tex->bindcode);
  
        if (!tex->bindcode) {
        tex->number = 0;
        glBindTexture(tex->target, tex->bindcode);
  
 -      if (depth) {
 -              type = GL_UNSIGNED_BYTE;
 -              format = GL_DEPTH_COMPONENT;
 -              internalformat = GL_DEPTH_COMPONENT;
 +      /* Check if texture fit in VRAM */
 +      if (n == 1) {
 +              if (h == 0)
 +                      proxy = GL_PROXY_TEXTURE_1D;
 +              else
 +                      proxy = GL_PROXY_TEXTURE_1D_ARRAY;
        }
 -      else {
 -              type = GL_FLOAT;
 -
 -              if (components == 4) {
 -                      format = GL_RGBA;
 -                      switch (hdr_type) {
 -                              case GPU_HDR_NONE:
 -                                      internalformat = GL_RGBA8;
 -                                      break;
 -                              /* the following formats rely on ARB_texture_float or OpenGL 3.0 */
 -                              case GPU_HDR_HALF_FLOAT:
 -                                      internalformat = GL_RGBA16F_ARB;
 -                                      break;
 -                              case GPU_HDR_FULL_FLOAT:
 -                                      internalformat = GL_RGBA32F_ARB;
 -                                      break;
 -                              default:
 -                                      break;
 -                      }
 -              }
 -              else if (components == 2) {
 -                      /* these formats rely on ARB_texture_rg or OpenGL 3.0 */
 -                      format = GL_RG;
 -                      switch (hdr_type) {
 -                              case GPU_HDR_NONE:
 -                                      internalformat = GL_RG8;
 -                                      break;
 -                              case GPU_HDR_HALF_FLOAT:
 -                                      internalformat = GL_RG16F;
 -                                      break;
 -                              case GPU_HDR_FULL_FLOAT:
 -                                      internalformat = GL_RG32F;
 -                                      break;
 -                              default:
 -                                      break;
 -                      }
 -              }
 -
 -              if (fpixels && hdr_type == GPU_HDR_NONE) {
 -                      type = GL_UNSIGNED_BYTE;
 -                      pixels = GPU_texture_convert_pixels(w * h, fpixels);
 -              }
 +      else if (n == 2) {
 +              if (d == 0)
 +                      proxy = GL_PROXY_TEXTURE_2D;
 +              else
 +                      proxy = GL_PROXY_TEXTURE_2D_ARRAY;
 +      }
 +      else if (n == 3) {
 +              proxy = GL_PROXY_TEXTURE_3D;
        }
  
-       valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, data_format, components, can_rescale, fpixels,
 -      if (tex->target == GL_TEXTURE_1D) {
 -              glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
++      valid = gpu_texture_try_alloc(tex, proxy, internalformat, format, data_format, components, can_rescale, fpixels,
 +                                    &rescaled_fpixels);
 +
 +      if (!valid) {
 +              if (err_out)
 +                      BLI_snprintf(err_out, 256, "GPUTexture: texture alloc failed");
 +              else
 +                      fprintf(stderr, "GPUTexture: texture alloc failed. Not enough Video Memory.");
 +              GPU_texture_free(tex);
 +              return NULL;
 +      }
  
 -              if (fpixels) {
 -                      glTexSubImage1D(tex->target, 0, 0, w, format, type,
 -                              pixels ? pixels : fpixels);
 +      /* Upload Texture */
 +      pix = (rescaled_fpixels) ? rescaled_fpixels : fpixels;
  
 -                      if (tex->w > w) {
 -                              gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
 -                      }
 -              }
 +      if (tex->target == GL_TEXTURE_1D) {
 +              glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, data_format, pix);
        }
 -      else {
 +      else if (tex->target == GL_TEXTURE_1D_ARRAY ||
 +               tex->target == GL_TEXTURE_2D ||
 +               tex->target == GL_TEXTURE_2D_MULTISAMPLE)
 +      {
                if (samples) {
                        glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
 +                      if (pix)
 +                              glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, data_format, pix);
                }
                else {
 -                      glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
 -                                   format, type, NULL);
 -              }
 -
 -              if (fpixels) {
 -                      glTexSubImage2D(tex->target, 0, 0, 0, w, h,
 -                              format, type, pixels ? pixels : fpixels);
 -
 -                      if (tex->w > w) {
 -                              gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h);
 -                      }
 -                      if (tex->h > h) {
 -                              gpu_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h);
 -                      }
 +                      glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, data_format, pix);
                }
        }
 +      else {
 +              glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, pix);
 +      }
  
 -      if (pixels)
 -              MEM_freeN(pixels);
 +      if (rescaled_fpixels)
 +              MEM_freeN(rescaled_fpixels);
  
 -      if (depth) {
 +      /* Texture Parameters */
 +      if (tex->depth) {
                glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
@@@ -372,23 -252,13 +374,23 @@@ static GPUTexture *GPU_texture_cube_cre
  
        GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
        tex->w = w;
 -      tex->h = h;
 -      tex->depth = depth;
 +      tex->h = w;
 +      tex->d = d;
        tex->number = -1;
        tex->refcount = 1;
 -      tex->target = GL_TEXTURE_3D;
 -      tex->target_base = GL_TEXTURE_3D;
 +      tex->fb_attachment = -1;
  
-       internalformat = GPU_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil);
 +      if (d == 0) {
 +              tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
 +      }
 +      else {
 +              BLI_assert(false && "Cubemap array Not implemented yet");
 +              // tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY;
 +      }
 +
++      internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil);
 +
 +      /* Generate Texture object */
        glGenTextures(1, &tex->bindcode);
  
        if (!tex->bindcode) {
index d703b06fa973cf5412ac4c3fa7567de3e903fa76,0000000000000000000000000000000000000000..dc71e030b7ecf2c5e17427b39adf15a4dfaff7a8
mode 100644,000000..100644
--- /dev/null
@@@ -1,450 -1,0 +1,450 @@@
- static void GPU_viewport_buffers_free(FramebufferList *fbl, int fbl_len, TextureList *txl, int txl_len);
- static void GPU_viewport_storage_free(StorageList *stl, int stl_len);
- static void GPU_viewport_passes_free(PassList *psl, int psl_len);
 +/*
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + * The Original Code is Copyright (C) 2006 Blender Foundation.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s):
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/gpu/intern/gpu_viewport.c
 + *  \ingroup gpu
 + *
 + * System that manages viewport drawing.
 + */
 +
 +#include <string.h>
 +
 +#include "BLI_listbase.h"
 +#include "BLI_rect.h"
 +#include "BLI_string.h"
 +
 +#include "DNA_vec_types.h"
 +
 +#include "BKE_global.h"
 +
 +#include "GPU_framebuffer.h"
 +#include "GPU_glew.h"
 +#include "GPU_immediate.h"
 +#include "GPU_texture.h"
 +#include "GPU_viewport.h"
 +
 +#include "DRW_engine.h"
 +
 +#include "MEM_guardedalloc.h"
 +
 +static const int default_fbl_len = (sizeof(DefaultFramebufferList)) / sizeof(void *);
 +static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *);
 +
 +struct GPUViewport {
 +      float pad[4];
 +
 +      /* debug */
 +      GPUTexture *debug_depth;
 +      int size[2];
 +
 +      ListBase data;  /* ViewportEngineData wrapped in LinkData */
 +      unsigned int data_hash;  /* If hash mismatch we free all ViewportEngineData in this viewport */
 +
 +      DefaultFramebufferList *fbl;
 +      DefaultTextureList *txl;
 +};
 +
- static void GPU_viewport_engines_data_free(GPUViewport *viewport)
++static void gpu_viewport_buffers_free(FramebufferList *fbl, int fbl_len, TextureList *txl, int txl_len);
++static void gpu_viewport_storage_free(StorageList *stl, int stl_len);
++static void gpu_viewport_passes_free(PassList *psl, int psl_len);
 +
 +GPUViewport *GPU_viewport_create(void)
 +{
 +      GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport");
 +      viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList");
 +      viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList");
 +
 +      viewport->size[0] = viewport->size[1] = -1;
 +
 +      return viewport;
 +}
 +
 +void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
 +{
 +      LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData");
 +      ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData");
 +      int fbl_len, txl_len, psl_len, stl_len;
 +
 +      DRW_engine_viewport_data_size_get(engine_type, &fbl_len, &txl_len, &psl_len, &stl_len);
 +
 +      data->engine_type = engine_type;
 +
 +      data->fbl = MEM_callocN((sizeof(void *) * fbl_len) + sizeof(FramebufferList), "FramebufferList");
 +      data->txl = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList), "TextureList");
 +      data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList");
 +      data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList");
 +
 +      ld->data = data;
 +      BLI_addtail(&viewport->data, ld);
 +
 +      return data;
 +}
 +
-               GPU_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
-               GPU_viewport_passes_free(data->psl, psl_len);
-               GPU_viewport_storage_free(data->stl, stl_len);
++static void gpu_viewport_engines_data_free(GPUViewport *viewport)
 +{
 +      int fbl_len, txl_len, psl_len, stl_len;
 +
 +      LinkData *next;
 +      for (LinkData *link = viewport->data.first; link; link = next) {
 +              next = link->next;
 +              ViewportEngineData *data = link->data;
 +              DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len);
 +
-                       GPU_viewport_passes_free(data->psl, psl_len);
++              gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
++              gpu_viewport_passes_free(data->psl, psl_len);
++              gpu_viewport_storage_free(data->stl, stl_len);
 +
 +              MEM_freeN(data->fbl);
 +              MEM_freeN(data->txl);
 +              MEM_freeN(data->psl);
 +              MEM_freeN(data->stl);
 +
 +              MEM_freeN(data);
 +
 +              BLI_remlink(&viewport->data, link);
 +              MEM_freeN(link);
 +      }
 +}
 +
 +void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type)
 +{
 +      for (LinkData *link = viewport->data.first; link; link = link->next) {
 +              ViewportEngineData *vdata = link->data;
 +              if (vdata->engine_type == engine_type) {
 +                      return vdata;
 +              }
 +      }
 +      return NULL;
 +}
 +
 +void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport)
 +{
 +      return viewport->fbl;
 +}
 +
 +void *GPU_viewport_texture_list_get(GPUViewport *viewport)
 +{
 +      return viewport->txl;
 +}
 +
 +void GPU_viewport_size_get(GPUViewport *viewport, int *size)
 +{
 +      size[0] = viewport->size[0];
 +      size[1] = viewport->size[1];
 +}
 +
 +bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash)
 +{
 +      bool dirty = false;
 +
 +      /* TODO for testing only, we need proper cache invalidation */
 +      if (G.debug_value != 666 && G.debug_value != 667) {
 +              for (LinkData *link = viewport->data.first; link; link = link->next) {
 +                      ViewportEngineData *data = link->data;
 +                      int psl_len;
 +                      DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL);
-               GPU_viewport_engines_data_free(viewport);
++                      gpu_viewport_passes_free(data->psl, psl_len);
 +              }
 +              dirty = true;
 +      }
 +
 +      if (viewport->data_hash != hash) {
-                       GPU_viewport_buffers_free(
++              gpu_viewport_engines_data_free(viewport);
 +              dirty = true;
 +      }
 +
 +      viewport->data_hash = hash;
 +
 +      return dirty;
 +}
 +
 +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
 +{
 +      DefaultFramebufferList *dfbl = viewport->fbl;
 +      DefaultTextureList *dtxl = viewport->txl;
 +      int fbl_len, txl_len;
 +
 +      /* add one pixel because of scissor test */
 +      int rect_w = BLI_rcti_size_x(rect) + 1;
 +      int rect_h = BLI_rcti_size_y(rect) + 1;
 +
 +      if (dfbl->default_fb) {
 +              if (rect_w != viewport->size[0] || rect_h != viewport->size[1]) {
-                               GPU_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
++                      gpu_viewport_buffers_free(
 +                              (FramebufferList *)viewport->fbl, default_fbl_len,
 +                              (TextureList *)viewport->txl, default_txl_len);
 +
 +                      for (LinkData *link = viewport->data.first; link; link = link->next) {
 +                              ViewportEngineData *data = link->data;
 +                              DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL);
- static void GPU_viewport_buffers_free(
++                              gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
 +                      }
 +              }
 +      }
 +
 +      if (!dfbl->default_fb) {
 +              bool ok = true;
 +              viewport->size[0] = rect_w;
 +              viewport->size[1] = rect_h;
 +
 +              dfbl->default_fb = GPU_framebuffer_create();
 +              if (!dfbl->default_fb) {
 +                      ok = false;
 +                      goto cleanup;
 +              }
 +
 +              /* Color */
 +              /* No multi samples for now */
 +              dtxl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL);
 +              if (!dtxl->color) {
 +                      ok = false;
 +                      goto cleanup;
 +              }
 +
 +              if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->color, 0)) {
 +                      ok = false;
 +                      goto cleanup;
 +              }
 +
 +              /* Depth */
 +              dtxl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL);
 +              if (!dtxl->depth) {
 +                      ok = false;
 +                      goto cleanup;
 +              }
 +              else if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0)) {
 +                      ok = false;
 +                      goto cleanup;
 +              }
 +              else if (!GPU_framebuffer_check_valid(dfbl->default_fb, NULL)) {
 +                      ok = false;
 +                      goto cleanup;
 +              }
 +
 +cleanup:
 +              if (!ok) {
 +                      GPU_viewport_free(viewport);
 +                      MEM_freeN(viewport);
 +                      return;
 +              }
 +
 +              GPU_framebuffer_restore();
 +      }
 +
 +      GPU_framebuffer_slots_bind(dfbl->default_fb, 0);
 +}
 +
 +static void draw_ofs_to_screen(GPUViewport *viewport)
 +{
 +      DefaultTextureList *dtxl = viewport->txl;
 +
 +      GPUTexture *color = dtxl->color;
 +
 +      const float w = (float)GPU_texture_width(color);
 +      const float h = (float)GPU_texture_height(color);
 +
 +      VertexFormat *format = immVertexFormat();
 +      unsigned int texcoord = VertexFormat_add_attrib(format, "texCoord", COMP_F32, 2, KEEP_FLOAT);
 +      unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
 +      GPU_texture_bind(color, 0);
 +
 +      immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
 +
 +      immBegin(PRIM_TRIANGLE_STRIP, 4);
 +
 +      immAttrib2f(texcoord, 0.0f, 0.0f);
 +      immVertex2f(pos, 0.0f, 0.0f);
 +
 +      immAttrib2f(texcoord, 1.0f, 0.0f);
 +      immVertex2f(pos, w, 0.0f);
 +
 +      immAttrib2f(texcoord, 0.0f, 1.0f);
 +      immVertex2f(pos, 0.0f, h);
 +
 +      immAttrib2f(texcoord, 1.0f, 1.0f);
 +      immVertex2f(pos, w, h);
 +
 +      immEnd();
 +
 +      GPU_texture_unbind(color);
 +
 +      immUnbindProgram();
 +}
 +
 +void GPU_viewport_unbind(GPUViewport *viewport)
 +{
 +      DefaultFramebufferList *dfbl = viewport->fbl;
 +
 +      if (dfbl->default_fb) {
 +              GPU_framebuffer_texture_unbind(dfbl->default_fb, NULL);
 +              GPU_framebuffer_restore();
 +
 +              glEnable(GL_SCISSOR_TEST);
 +              glDisable(GL_DEPTH_TEST);
 +
 +              /* This might be bandwidth limiting */
 +              draw_ofs_to_screen(viewport);
 +      }
 +}
 +
- static void GPU_viewport_storage_free(StorageList *stl, int stl_len)
++static void gpu_viewport_buffers_free(
 +        FramebufferList *fbl, int fbl_len,
 +        TextureList *txl, int txl_len)
 +{
 +      for (int i = 0; i < fbl_len; i++) {
 +              GPUFrameBuffer *fb = fbl->framebuffers[i];
 +              if (fb) {
 +                      GPU_framebuffer_free(fb);
 +                      fbl->framebuffers[i] = NULL;
 +              }
 +      }
 +      for (int i = 0; i < txl_len; i++) {
 +              GPUTexture *tex = txl->textures[i];
 +              if (tex) {
 +                      GPU_texture_free(tex);
 +                      txl->textures[i] = NULL;
 +              }
 +      }
 +}
 +
- static void GPU_viewport_passes_free(PassList *psl, int psl_len)
++static void gpu_viewport_storage_free(StorageList *stl, int stl_len)
 +{
 +      for (int i = 0; i < stl_len; i++) {
 +              void *storage = stl->storage[i];
 +              if (storage) {
 +                      MEM_freeN(storage);
 +                      stl->storage[i] = NULL;
 +              }
 +      }
 +}
 +
-       GPU_viewport_engines_data_free(viewport);
++static void gpu_viewport_passes_free(PassList *psl, int psl_len)
 +{
 +      for (int i = 0; i < psl_len; i++) {
 +              struct DRWPass *pass = psl->passes[i];
 +              if (pass) {
 +                      DRW_pass_free(pass);
 +                      MEM_freeN(pass);
 +                      psl->passes[i] = NULL;
 +              }
 +      }
 +}
 +
 +void GPU_viewport_free(GPUViewport *viewport)
 +{
-       GPU_viewport_buffers_free(
++      gpu_viewport_engines_data_free(viewport);
 +
++      gpu_viewport_buffers_free(
 +              (FramebufferList *)viewport->fbl, default_fbl_len,
 +              (TextureList *)viewport->txl, default_txl_len);
 +
 +      MEM_freeN(viewport->fbl);
 +      MEM_freeN(viewport->txl);
 +
 +      GPU_viewport_debug_depth_free(viewport);
 +}
 +
 +/****************** debug ********************/
 +
 +bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256])
 +{
 +      viewport->debug_depth = GPU_texture_create_2D_custom(width, height, 4, GPU_RGBA16F, NULL, err_out);
 +      return (viewport->debug_depth != NULL);
 +}
 +
 +void GPU_viewport_debug_depth_free(GPUViewport *viewport)
 +{
 +      if (viewport->debug_depth != NULL) {
 +              MEM_freeN(viewport->debug_depth);
 +              viewport->debug_depth = NULL;
 +      }
 +}
 +
 +void GPU_viewport_debug_depth_store(GPUViewport *viewport, const int x, const int y)
 +{
 +      const int w = GPU_texture_width(viewport->debug_depth);
 +      const int h = GPU_texture_height(viewport->debug_depth);
 +
 +      GPU_texture_bind(viewport->debug_depth, 0);
 +      glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, x, y, w, h, 0);
 +      GPU_texture_unbind(viewport->debug_depth);
 +}
 +
 +void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, const float zfar)
 +{
 +      const float w = (float)GPU_texture_width(viewport->debug_depth);
 +      const float h = (float)GPU_texture_height(viewport->debug_depth);
 +
 +      VertexFormat *format = immVertexFormat();
 +      unsigned int texcoord = VertexFormat_add_attrib(format, "texCoord", COMP_F32, 2, KEEP_FLOAT);
 +      unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH);
 +
 +      GPU_texture_bind(viewport->debug_depth, 0);
 +
 +      immUniform1f("znear", znear);
 +      immUniform1f("zfar", zfar);
 +      immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
 +
 +      immBegin(PRIM_TRIANGLE_STRIP, 4);
 +
 +      immAttrib2f(texcoord, 0.0f, 0.0f);
 +      immVertex2f(pos, 0.0f, 0.0f);
 +
 +      immAttrib2f(texcoord, 1.0f, 0.0f);
 +      immVertex2f(pos, w, 0.0f);
 +
 +      immAttrib2f(texcoord, 0.0f, 1.0f);
 +      immVertex2f(pos, 0.0f, h);
 +
 +      immAttrib2f(texcoord, 1.0f, 1.0f);
 +      immVertex2f(pos, w, h);
 +
 +      immEnd();
 +
 +      GPU_texture_unbind(viewport->debug_depth);
 +
 +      immUnbindProgram();
 +}
 +
 +int GPU_viewport_debug_depth_width(const GPUViewport *viewport)
 +{
 +      return GPU_texture_width(viewport->debug_depth);
 +}
 +
 +int GPU_viewport_debug_depth_height(const GPUViewport *viewport)
 +{
 +      return GPU_texture_height(viewport->debug_depth);
 +}
 +
 +bool GPU_viewport_debug_depth_is_valid(GPUViewport *viewport)
 +{
 +      return viewport->debug_depth != NULL;
 +}