a
    VŸ$cï)  ã                   @   sh   d dl mZ d dlZd dlZd dlZd dlZi Zdd„ ZG dd„ deƒZ	i Z
dd„ ZG d	d
„ d
eƒZdS )é    )Úprint_functionNc                 K   s   t | fi |¤Ž dS )a§  
    :doc: register_shader

    This registers a shader part. This takes `name`, and then
    keyword arguments.

    `name`
        A string giving the name of the shader part. Names starting with an
        underscore or "renpy." are reserved for Ren'Py.

    `variables`
        The variables used by the shader part. These should be listed one per
        line, a storage (uniform, attribute, or varying) followed by a type,
        name, and semicolon. For example::

            variables='''
            uniform sampler2D tex0;
            attribute vec2 a_tex_coord;
            varying vec2 v_tex_coord;
            '''

    `vertex_functions`
        If given, a string containing functions that will be included in the
        vertex shader.

    `fragment_functions`
        If given, a string containing functions that will be included in the
        fragment shader.

    Other keyword arguments should start with ``vertex_`` or ``fragment_``,
    and end with an integer priority. So "fragment_200" or "vertex_300". These
    give text that's placed in the appropriate shader at the given priority,
    with lower priority numbers inserted before higher priority numbers.
    N)Ú
ShaderPart)ÚnameÚkwargs© r   úrenpy/gl2\gl2shadercache.pyÚregister_shader   s    $r   c                   @   s   e Zd ZdZddd„ZdS )r   z0
    Arguments are as for register_shader.

    Ú c              	   K   s¾  t  d|¡std |¡ƒ‚|| _| t|< || _|| _g | _g | _	t
ƒ | _t
ƒ | _t
ƒ }t
ƒ }| ¡ D ]¤\}}	| d¡\}
}}|s„d }
zt|ƒ}W n ty¦   d }
Y n0 |
dkr¼| j}|}n|
dkrÐ| j	}|}ntdƒ‚| ||	f¡ t  d|	¡D ]}| | d¡¡ qòqd| d	¡D ]ž}| d
¡}| ¡ }|s4qt|ƒ}t|ƒdkr\td | j|¡ƒ‚|d }|d }||v r‚| j |¡ ||v r˜| j |¡ |dkrtjj |¡ q|| _d S )Nz	^[\w\.]+$zwThe shader name {!r} contains an invalid character. Shader names are limited to ASCII alphanumeric characters, _, and .Ú_ÚvertexÚfragmentzQKeyword arguments to ShaderPart must be of the form {vertex,fragment}_{priority}.z\b\w+\br   Ú
z ;é   zp{}: Unknown shader variable line {!r}. Only the form '{{uniform,attribute,vertex}} {{type}} {{name}} is allowed.é   Úuniform)ÚreÚmatchÚ	ExceptionÚformatr   Úshader_partÚvertex_functionsÚfragment_functionsÚvertex_partsÚfragment_partsÚsetÚvertex_variablesÚfragment_variablesÚitemsÚ	partitionÚintÚappendÚfinditerÚaddÚgroupÚsplitÚstripÚtupleÚlenÚrenpyÚdisplayÚ	transformÚadd_uniformÚraw_variables)Úselfr   Ú	variablesr   r   r   Úvertex_usedÚfragment_usedÚkÚvÚshaderr
   ÚpriorityÚpartsÚusedÚmÚlÚaÚkindr   r   r   Ú__init__9   s^    




zShaderPart.__init__N)r	   r	   r	   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r;   r   r   r   r   r   3   s   r   c                 C   sœ   g }|r"|  d¡ |r,|  d¡ n
|  d¡ | |¡ t| ƒD ]\}}}|  d |||¡¡ q>|  d¡ | ¡  |D ]\}	}
|  |
¡ qt|  d¡ d |¡S )zÀ
    Given lists of variables and parts, converts them into textual source
    code for a shader.

    `fragment`
        Should be set to true to generate the code for a fragment shader.
    z#version 100
zprecision mediump float;
z#version 120
z
{} {} {};
z
void main() {
z}
r	   )r    ÚextendÚsortedr   ÚsortÚjoin)r.   r5   Ú	functionsr   ÚglesÚrvÚstorageÚtype_r   r
   Úpartr   r   r   Úsource‹   s    	




rJ   c                   @   sH   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dS )ÚShaderCachezË
    This class caches shaders that were compiled. It's also responsible for
    recording shaders that have been used, persisting them to disk, and then
    loading the shaders back into the cache.
    c                 C   s$   || _ || _i | _tƒ | _d| _d S )NF)ÚfilenamerE   Úcacher   ÚmissingÚdirty)r-   rL   rE   r   r   r   r;   ½   s
    zShaderCache.__init__c                 C   s°  | j  |d¡}|dur|S tƒ }tƒ }|D ],}| d¡rL| |dd… ¡ q*| |¡ q*||8 }d|vrv| tjj¡ tt	|ƒƒ}| j  |d¡}|dur¦|| j |< |S tƒ }g }g }	tƒ }
g }g }|D ]j}t
 |d¡}|du rìtd |¡ƒ‚||jO }| |j¡ |	 |j¡ |
|jO }
| |j¡ | |j¡ qÆt|||	d| jƒ}t|
||d| jƒ}|  d||¡ |  d	||¡ d
dlm} ||||ƒ}| ¡  || j |< || j |< d| _|S )z¹
        Gets a shader, creating it if necessary.

        `partnames`
            A tuple of strings, giving the names of the shader parts to include in
            the cache.
        Nú-é   z	renpy.ftlz {!r} is not a known shader part.FTr   r   r   )ÚProgram)rM   Úgetr   Ú
startswithr"   r(   ÚconfigÚdefault_shaderr&   rA   r   r   r   r   r@   r   r    r   r   r   r   rJ   rE   Ú
log_shaderÚrenpy.gl2.gl2shaderrR   ÚloadrO   )r-   Ú	partnamesrF   ÚpartnamesetÚpartnamenotsetÚiÚsortedpartnamesr   r   r   r   r   r   Úpr   r   rR   r   r   r   rS   Ñ   sX    	





zShaderCache.getc                 C   s   |D ]}|t vr dS qdS )zf
        Returns true if every part in partnames is a known part, or False
        otherwise.
        FT)r   )r-   rZ   r]   r   r   r   Úcheck  s    zShaderCache.checkc                 C   s  | j s
dS tjjsdS d}z¾tj tjjtj 	| j
¡¡}|d }tj|dddB}t| j ¡ ƒ| jB }|D ]}| d |¡d ¡ qjW d  ƒ n1 s˜0    Y  zt |¡ W n tyÂ   Y n0 t ||¡ d	| _ W n4 ty   tjj d
 |¡¡ tjj ¡  Y n0 dS )z8
        Saves the list of shaders to the file.
        Nz	<unknown>z.tmpÚwúutf-8)Úencodingú z
FzSaving shaders to {!r}:)rO   r(   rU   Ú	developerÚosÚpathrC   ÚgamedirÚloaderÚget_pathrL   ÚioÚopenr   rM   ÚkeysrN   ÚwriteÚunlinkr   Úrenamer)   Úlogr   Ú	exception)r-   ÚfnÚtmpÚfÚshadersr]   r   r   r   Úsave+  s*    4
zShaderCache.savec              
   C   sö   zÆt j | j¡¤}|D ]Ž}| ¡  d¡}t| ¡  ¡ ƒ}|s>q|  |¡sV| j	 
|¡ qz|  |¡ W q ty¢   t jj d |¡¡ t jj ¡  | j	 
|¡ Y q0 qW d  ƒ n1 sº0    Y  W n* tyð   t jj d | j¡¡ Y dS 0 dS )z
        Loads the list of shaders from the file, and compiles all shaders
        for which the parts exist, and for which compilation can succeed.
        rb   zPrecompiling shader {!r}:NzCould not open {!r}:)r(   ri   rY   rL   r%   Údecoder&   r$   r`   rN   r"   rS   r   r)   rq   rn   r   rr   )r-   ru   r8   rZ   r   r   r   rY   P  s&    
6zShaderCache.loadc                 C   s   | j  ¡  | j ¡  dS )zD
        Clears the shader cache and the shaders inside it.
        N)rM   ÚclearrN   )r-   r   r   r   ry   m  s    
zShaderCache.clearc                 C   sn   t jjsdS |d d |¡ d }|dtddt|ƒ ƒ  }t jj d|¡ t jj d|¡ t jj d¡ dS )	z2
        Logs the shader text to the log.
        Nrd   z, rP   r   éP   z%szP--------------------------------------------------------------------------------)	r(   rU   Úlog_gl_shadersrC   Úmaxr'   r)   rq   rn   )r-   r:   rZ   Útextr   r   r   r   rW   u  s    zShaderCache.log_shaderN)r<   r=   r>   r?   r;   rS   r`   rw   rY   ry   rW   r   r   r   r   rK   ¶   s   N%rK   )Ú
__future__r   r   rk   rf   r(   r   r   Úobjectr   rM   rJ   rK   r   r   r   r   Ú<module>   s   'U+