class_docstr: Texture mixin class for smarter scaling decisions.
  
  This class wraps the logic to normalize data on the CPU before sending
  it to the GPU (the texture). Pre-scaling on the CPU can be helpful in
  cases where OpenGL 2/ES requirements limit the texture storage to an
  8-bit normalized integer internally.
  
  This class includes optimizations where image data is not re-normalized
  if the previous normalization can still be used to visualize the data
  with the new color limits.
  
  This class should only be used internally. For similar features where
  scaling occurs on the GPU see
  :class:`vispy.visuals._scalable_textures.GPUScaledTextureMixin`.
  
  To use this mixin, a subclass should be created to combine this mixin with
  the texture class being used. Existing subclasses already exist in this
  module. Note that this class **must** appear first in the subclass's parent
  classes so that its ``__init__`` method is called instead of the parent
  Texture class.
class_docstr_tok: ["Texture","mixin","class","for","smarter","scaling","decisions",".","This","class","wraps","the","logic","to","normalize","data","on","the","CPU","before","sending","it","to","the","GPU","(","the","texture",")",".","Pre-scaling","on","the","CPU","can","be","helpful","in","cases","where","OpenGL","2\/ES","requirements","limit","the","texture","storage","to","an","8-bit","normalized","integer","internally",".","This","class","includes","optimizations","where","image","data","is","not","re-normalized","if","the","previous","normalization","can","still","be","used","to","visualize","the","data","with","the","new","color","limits",".","This","class","should","only","be","used","internally",".","For","similar","features","where","scaling","occurs","on","the","GPU","see",":","class",":","`","vispy.visuals._scalable_textures.GPUScaledTextureMixin","`",".","To","use","this","mixin",",","a","subclass","should","be","created","to","combine","this","mixin","with","the","texture","class","being","used",".","Existing","subclasses","already","exist","in","this","module",".","Note","that","this","class","*","*","must","*","*","appear","first","in","the","subclass","'s","parent","classes","so","that","its","``","__init__","``","method","is","called","instead","of","the","parent","Texture","class","."]
docstr: Upload new data to the GPU, scaling if necessary.
docstr_tok: ["Upload","new","data","to","the","GPU",",","scaling","if","necessary","."]
code: def scale_and_set_data(self, data, offset=None, copy=True):
      """Upload new data to the GPU, scaling if necessary."""
      if self._data_dtype is None:
          data.dtype == self._data_dtype
  
      # ensure dtype is the same as it was before, or funny things happen
      # no copy is performed unless asked for or necessary
      data = convert_dtype_and_clip(data, self._data_dtype, copy=copy)
  
      clim = self._clim
      is_auto = isinstance(clim, str) and clim == "auto"
      if data.ndim == self._ndim or data.shape[self._ndim] == 1:
          if is_auto:
              clim = get_default_clim_from_data(data)
          data = self._scale_data_on_cpu(data, clim, copy=False)
          data_limits = clim
      else:
          data_limits = get_default_clim_from_dtype(data.dtype)
          if is_auto:
              clim = data_limits
  
      self._clim = float(clim[0]), float(clim[1])
      self._data_limits = data_limits
      return super().scale_and_set_data(data, offset=offset, copy=False)
  
imports: import warnings
  import numpy
  from vispy.gloo.texture import Texture2D, Texture3D, convert_dtype_and_clip
label_desc: Use image node_id 6 for calling the CPUScaledTextureMixin obj's underlying member method code with example usage: obj.scale_and_set_data(data, offset, copy) and returns: super